sfplanner 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|