sfplanner 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +1 -1
- data/bin/sfplanner +8 -3
- data/lib/sfplanner/planner.rb +71 -40
- data/lib/sfplanner.rb +1 -2
- data/sfplanner.gemspec +2 -2
- metadata +5 -10
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
SFP Planner for Ruby
|
2
2
|
====================
|
3
3
|
- Author: Herry (herry13@gmail.com)
|
4
|
-
- Version: 0.1.
|
4
|
+
- Version: 0.1.1
|
5
5
|
- License: [BSD License](https://github.com/herry13/sfp-ruby/blob/master/LICENSE)
|
6
6
|
|
7
7
|
A Ruby gem that provides a Ruby API to SFP planner that solves a planning task written in [SFP language](https://github.com/herry13/nuri/wiki/SFP-language).
|
data/bin/sfplanner
CHANGED
@@ -4,7 +4,7 @@ libdir = File.expand_path(File.dirname(__FILE__))
|
|
4
4
|
require "#{libdir}/../lib/sfplanner"
|
5
5
|
|
6
6
|
opts = Trollop::options do
|
7
|
-
version "sfplanner 0.
|
7
|
+
version "sfplanner 0.1.1 (c) 2013 Herry"
|
8
8
|
banner <<-EOS
|
9
9
|
Solve a planning task specified in SFP language, and print the plan (if found) in JSON format.
|
10
10
|
|
@@ -30,10 +30,15 @@ filepath = ARGV[0].to_s
|
|
30
30
|
|
31
31
|
if filepath != ''
|
32
32
|
planner = Sfp::Planner.new
|
33
|
+
options = {:file => ARGV[0],
|
34
|
+
:json => !opts[:pretty],
|
35
|
+
:pretty_json => opts[:pretty],
|
36
|
+
:parallel => opts[:parallel]}
|
33
37
|
if opts[:json_input]
|
34
|
-
|
38
|
+
options[:input_json] = true
|
39
|
+
puts planner.solve(options)
|
35
40
|
else
|
36
|
-
puts planner.solve(
|
41
|
+
puts planner.solve(options)
|
37
42
|
end
|
38
43
|
else
|
39
44
|
Trollop::help
|
data/lib/sfplanner/planner.rb
CHANGED
@@ -2,6 +2,7 @@ module Sfp
|
|
2
2
|
class Planner
|
3
3
|
Heuristic = 'mixed' # lmcut, cg, cea, ff, mixed ([cg|cea|ff]=>lmcut)
|
4
4
|
Debug = false
|
5
|
+
TranslatorBenchmarkFile = 'sas_translator.benchmarks'
|
5
6
|
|
6
7
|
class Config
|
7
8
|
# The timeout for the solver in seconds (default 60s/1mins)
|
@@ -44,8 +45,12 @@ module Sfp
|
|
44
45
|
@parser.root = params[:sfp]
|
45
46
|
elsif params[:file].is_a?(String)
|
46
47
|
raise Exception, "File not found: #{params[:file]}" if not File.exist?(params[:file])
|
47
|
-
|
48
|
-
|
48
|
+
if params[:input_json]
|
49
|
+
@parser.root = json_to_sfp(JSON[File.read(params[:file])])
|
50
|
+
else
|
51
|
+
@parser.home_dir = File.expand_path(File.dirname(params[:file]))
|
52
|
+
@parser.parse(File.read(params[:file]))
|
53
|
+
end
|
49
54
|
end
|
50
55
|
|
51
56
|
@debug = true if params[:debug]
|
@@ -83,6 +88,16 @@ module Sfp
|
|
83
88
|
end
|
84
89
|
|
85
90
|
protected
|
91
|
+
def json_to_sfp(json)
|
92
|
+
json.accept(Sfp::Visitor::SfpGenerator.new(json))
|
93
|
+
json.each do |key,val|
|
94
|
+
next if key[0,1] == '_'
|
95
|
+
if val.is_a?(Hash) and val['_context'] == 'state'
|
96
|
+
#val.each { |k,v| v.delete('_parent') if k[0,1] != '_' and v.is_a?(Hash) and v.has_key?('_parent') }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
86
101
|
def save_sfp_task
|
87
102
|
sfp_task = Sfp::Helper.deep_clone(@parser.root)
|
88
103
|
sfp_task.accept(Sfp::Visitor::ParentEliminator.new)
|
@@ -266,14 +281,21 @@ module Sfp
|
|
266
281
|
|
267
282
|
tmp_dir = '/tmp/nuri_' + (rand * 100000).to_i.abs.to_s
|
268
283
|
begin
|
269
|
-
|
270
|
-
|
271
|
-
|
284
|
+
compile_time = Benchmark.measure do
|
285
|
+
parser.compile_step_1
|
286
|
+
p[:sas_post_processor].sas_post_processor(parser) if p[:sas_post_processor]
|
287
|
+
parser.compile_step_2
|
288
|
+
end
|
272
289
|
|
273
290
|
while File.exist?(tmp_dir)
|
274
291
|
tmp_dir = '/tmp/nuri_' + (rand * 100000).to_i.abs.to_s
|
275
292
|
end
|
276
293
|
Dir.mkdir(tmp_dir)
|
294
|
+
|
295
|
+
benchmarks = parser.benchmarks
|
296
|
+
benchmarks['compile time'] = compile_time
|
297
|
+
File.open(tmp_dir + '/' + TranslatorBenchmarkFile, 'w') { |f| f.write(JSON.pretty_generate(benchmarks)) }
|
298
|
+
|
277
299
|
sas_file = tmp_dir + '/problem.sas'
|
278
300
|
plan_file = tmp_dir + '/out.plan'
|
279
301
|
File.open(sas_file, 'w') do |f|
|
@@ -347,27 +369,18 @@ module Sfp
|
|
347
369
|
when 'cg' then '--search "lazy_greedy(cg(cost_type=2))"'
|
348
370
|
when 'cea' then '--search "lazy_greedy(cea(cost_type=2))"'
|
349
371
|
when 'mad' then '--search "lazy_greedy(mad())"'
|
350
|
-
when '
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
lazy_greedy([hff2,hlm2],preferred=[hff2,hlm2],
|
359
|
-
reopen_closed=false),
|
360
|
-
lazy_wastar([hff2,hlm2],preferred=[hff2,hlm2],w=5),
|
361
|
-
lazy_wastar([hff2,hlm2],preferred=[hff2,hlm2],w=3),
|
362
|
-
lazy_wastar([hff2,hlm2],preferred=[hff2,hlm2],w=2),
|
363
|
-
lazy_wastar([hff2,hlm2],preferred=[hff2,hlm2],w=1)],
|
364
|
-
repeat_last=true,continue_on_fail=true)"'
|
365
|
-
when 'autotune' then ' \
|
372
|
+
when 'cea2' then ' --heuristic "hCea=cea(cost_type=2)" \
|
373
|
+
--search "ehc(hCea, preferred=hCea,preferred_usage=0,cost_type=0)"'
|
374
|
+
when 'ff2' then ' --heuristic "hFF=ff(cost_type=1)" \
|
375
|
+
--search "lazy(alt([single(sum([g(),weight(hFF, 10)])),
|
376
|
+
single(sum([g(),weight(hFF, 10)]),pref_only=true)],
|
377
|
+
boost=2000),
|
378
|
+
preferred=hFF,reopen_closed=false,cost_type=1)"'
|
379
|
+
when 'autotune22' then ' \
|
366
380
|
--heuristic "hCea=cea(cost_type=2)" \
|
367
381
|
--heuristic "hCg=cg(cost_type=1)" \
|
368
382
|
--heuristic "hGoalCount=goalcount(cost_type=2)" \
|
369
383
|
--heuristic "hFF=ff(cost_type=0)" \
|
370
|
-
--heuristic "hMad=mad()" \
|
371
384
|
--search "lazy(alt([single(sum([weight(g(), 2),weight(hFF, 3)])),
|
372
385
|
single(sum([weight(g(), 2),weight(hFF, 3)]),pref_only=true),
|
373
386
|
single(sum([weight(g(), 2),weight(hCg, 3)])),
|
@@ -375,11 +388,26 @@ module Sfp
|
|
375
388
|
single(sum([weight(g(), 2),weight(hCea, 3)])),
|
376
389
|
single(sum([weight(g(), 2),weight(hCea, 3)]),pref_only=true),
|
377
390
|
single(sum([weight(g(), 2),weight(hGoalCount, 3)])),
|
378
|
-
single(sum([weight(g(), 2),weight(hGoalCount, 3)]),pref_only=true),
|
379
|
-
single(sum([weight(g(), 2),weight(hMad, 3)])),
|
380
|
-
single(sum([weight(g(), 2),weight(hMad, 3)]),pref_only=true)],
|
391
|
+
single(sum([weight(g(), 2),weight(hGoalCount, 3)]),pref_only=true)],
|
381
392
|
boost=200),
|
382
393
|
preferred=[hCea,hGoalCount],reopen_closed=false,cost_type=1)"'
|
394
|
+
when 'autotune12' then ' \
|
395
|
+
--heuristic "hFF=ff(cost_type=1)" \
|
396
|
+
--heuristic "hCea=cea(cost_type=0)" \
|
397
|
+
--heuristic "hCg=cg(cost_type=2)" \
|
398
|
+
--heuristic "hGoalCount=goalcount(cost_type=0)" \
|
399
|
+
--heuristic "hAdd=add(cost_type=0)" \
|
400
|
+
--search "lazy(alt([single(sum([g(),weight(hAdd, 7)])),
|
401
|
+
single(sum([g(),weight(hAdd, 7)]),pref_only=true),
|
402
|
+
single(sum([g(),weight(hCg, 7)])),
|
403
|
+
single(sum([g(),weight(hCg, 7)]),pref_only=true),
|
404
|
+
single(sum([g(),weight(hCea, 7)])),
|
405
|
+
single(sum([g(),weight(hCea, 7)]),pref_only=true),
|
406
|
+
single(sum([g(),weight(hGoalCount, 7)])),
|
407
|
+
single(sum([g(),weight(hGoalCount, 7)]),pref_only=true)],
|
408
|
+
boost=1000),
|
409
|
+
preferred=[hCea,hGoalCount],
|
410
|
+
reopen_closed=false,cost_type=1)"'
|
383
411
|
else '--search "lazy_greedy(ff(cost_type=0))"'
|
384
412
|
end
|
385
413
|
end
|
@@ -431,24 +459,26 @@ module Sfp
|
|
431
459
|
end
|
432
460
|
|
433
461
|
def solve
|
434
|
-
|
435
|
-
|
436
|
-
# 1a) solve with autotune (see fd-autotune-2)
|
437
|
-
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'autotune')
|
438
|
-
Kernel.system(planner)
|
462
|
+
optimize = true
|
439
463
|
|
440
|
-
# 1b) if not found, try mad
|
441
464
|
if not File.exist?(@plan_file)
|
442
|
-
|
465
|
+
#autotune12 (see fd-autotune-1)
|
466
|
+
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'autotune12')
|
467
|
+
Kernel.system(planner)
|
468
|
+
end
|
469
|
+
if not File.exist?(@plan_file)
|
470
|
+
#autotune22 (see fd-autotune-2)
|
471
|
+
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'autotune22')
|
472
|
+
Kernel.system(planner)
|
473
|
+
end
|
474
|
+
if not File.exists?(@plan_file)
|
475
|
+
# solve with cea2 (EHC+CEA: see fd-autotune-2)
|
476
|
+
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'cea2')
|
443
477
|
Kernel.system(planner)
|
444
478
|
end
|
445
|
-
# if not File.exist?(@plan_file)
|
446
|
-
# planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'ff')
|
447
|
-
# Kernel.system(planner)
|
448
|
-
# end
|
449
|
-
# 1c) if not found, try CEA
|
450
479
|
if not File.exists?(@plan_file)
|
451
|
-
|
480
|
+
# solve with ff2 (FF with boost: see fd-autotune-1)
|
481
|
+
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'ff2')
|
452
482
|
Kernel.system(planner)
|
453
483
|
end
|
454
484
|
|
@@ -460,12 +490,12 @@ module Sfp
|
|
460
490
|
#end
|
461
491
|
|
462
492
|
return false if not File.exist?(@plan_file)
|
463
|
-
|
493
|
+
optimize_plan if optimize
|
464
494
|
|
465
495
|
true
|
466
496
|
end
|
467
497
|
|
468
|
-
def
|
498
|
+
def optimize_plan
|
469
499
|
# 2) remove unselected operators
|
470
500
|
new_sas = @sas_file + '.2'
|
471
501
|
new_plan = @plan_file + '.2'
|
@@ -489,6 +519,7 @@ module Sfp
|
|
489
519
|
line.strip!
|
490
520
|
line = line[1, line.length-2]
|
491
521
|
selected << line.split(' ', 2)[0]
|
522
|
+
#'$.' + line[1, line.length-2].split(' ', 2)[0].split('$.')[1]
|
492
523
|
end
|
493
524
|
|
494
525
|
# remove unselected operators
|
data/lib/sfplanner.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# external dependencies
|
2
2
|
require 'rubygems'
|
3
3
|
require 'json'
|
4
|
-
|
4
|
+
require 'sfp'
|
5
5
|
|
6
6
|
# internal dependencies
|
7
7
|
libdir = File.expand_path(File.dirname(__FILE__))
|
8
8
|
|
9
|
-
require libdir + '/../../sfp-ruby/lib/sfp.rb'
|
10
9
|
require libdir + '/sfplanner/sas'
|
11
10
|
require libdir + '/sfplanner/planner'
|
data/sfplanner.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'sfplanner'
|
3
|
-
s.version = '0.1.
|
4
|
-
s.date = '2013-08-
|
3
|
+
s.version = '0.1.1'
|
4
|
+
s.date = '2013-08-13'
|
5
5
|
s.summary = 'SFPlanner'
|
6
6
|
s.description = 'A Ruby gem that provides a Ruby API and a script to the SFP planner. This planner can automatically generate a plan that solves a planning problem written in SFP language.'
|
7
7
|
s.authors = ['Herry']
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sfplanner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sfp
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirement: &21369160 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,12 +21,7 @@ dependencies:
|
|
21
21
|
version: 0.3.6
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 0.3.6
|
24
|
+
version_requirements: *21369160
|
30
25
|
description: A Ruby gem that provides a Ruby API and a script to the SFP planner.
|
31
26
|
This planner can automatically generate a plan that solves a planning problem written
|
32
27
|
in SFP language.
|
@@ -70,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
65
|
version: '0'
|
71
66
|
requirements: []
|
72
67
|
rubyforge_project: sfplanner
|
73
|
-
rubygems_version: 1.8.
|
68
|
+
rubygems_version: 1.8.11
|
74
69
|
signing_key:
|
75
70
|
specification_version: 3
|
76
71
|
summary: SFPlanner
|