sfplanner 0.1.5 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +8 -4
- data/VERSION +1 -1
- data/lib/sfplanner/planner.rb +138 -19
- data/lib/sfplanner.rb +4 -5
- data/sfplanner.gemspec +12 -13
- metadata +21 -18
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7aea85679985ccc529011c6d8145f45bae74702a
|
4
|
+
data.tar.gz: e24e321da99e4eadb5b5e37ea6fdf435df71ce3c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 400496a44f31dcde8d7bd4fc47b1df632e6b916f9e09470cc1d02b6bbd5e032e0992bc5d1a1cf09dc5f71db8110d9c23e504cdf8644c75cd0fa3265413344ec1
|
7
|
+
data.tar.gz: 4faedc38ca1f6cbe29aab72a0ad1eaf52cc13dc70f11d0dd7a567e383267306ebe288190de4951cba367943a03d0450a1663c14d8b1ce5884efb62e07bbd409d
|
data/README.md
CHANGED
@@ -10,8 +10,6 @@ A Ruby script and library of SFP planner, which solves a planning task written i
|
|
10
10
|
|
11
11
|
Click [here](https://github.com/herry13/nuri/wiki/SFP-language), for more details about SFP language.
|
12
12
|
|
13
|
-
This is a spin-out project from [Nuri](https://github.com/herry13/nuri).
|
14
|
-
|
15
13
|
|
16
14
|
Features
|
17
15
|
--------
|
@@ -28,10 +26,10 @@ To install
|
|
28
26
|
|
29
27
|
Requirements
|
30
28
|
------------
|
31
|
-
- Ruby (>= 1.
|
29
|
+
- Ruby (>= 1.9.2)
|
32
30
|
- Graphviz
|
33
31
|
- Rubygems
|
34
|
-
- sfp
|
32
|
+
- sfp
|
35
33
|
|
36
34
|
Tested on:
|
37
35
|
- Ubuntu 12.04
|
@@ -222,3 +220,9 @@ You could set particular environment variable to change the planner settings:
|
|
222
220
|
$ export SFPLANNER_MIXED_HEURISTICS=ff2,cea2
|
223
221
|
|
224
222
|
|
223
|
+
Related Projects
|
224
|
+
----------------
|
225
|
+
- [Nuri](https://github.com/herry13/nuri)
|
226
|
+
- [Sfp-ruby](https://github.com/herry13/sfp-ruby)
|
227
|
+
- [Sfpagent](https://github.com/herry13/sfpagent)
|
228
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1
|
1
|
+
0.2.1
|
data/lib/sfplanner/planner.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'thread'
|
2
3
|
|
3
4
|
module Sfp
|
4
5
|
class Planner
|
@@ -346,7 +347,7 @@ module Sfp
|
|
346
347
|
def solve_sas(parser, p={})
|
347
348
|
return nil if parser.nil?
|
348
349
|
|
349
|
-
tmp_dir = '/tmp/nuri_' + (
|
350
|
+
tmp_dir = '/tmp/nuri_' + (Time.now.to_f * 1000000).to_i.to_s
|
350
351
|
begin
|
351
352
|
compile_time = Benchmark.measure do
|
352
353
|
parser.compile_step_1
|
@@ -361,23 +362,21 @@ module Sfp
|
|
361
362
|
|
362
363
|
benchmarks = parser.benchmarks
|
363
364
|
benchmarks['compile time'] = compile_time
|
364
|
-
File.open(tmp_dir + '/' + TranslatorBenchmarkFile, 'w') { |f| f.write(JSON.pretty_generate(benchmarks)) }
|
365
365
|
|
366
366
|
sas_file = tmp_dir + '/problem.sas'
|
367
367
|
plan_file = tmp_dir + '/out.plan'
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
368
|
+
benchmarks['generating sas'] = Benchmark.measure do
|
369
|
+
File.open(sas_file, 'w') do |f|
|
370
|
+
f.write(parser.sas)
|
371
|
+
f.flush
|
372
|
+
end
|
372
373
|
end
|
373
374
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
else
|
378
|
-
command = Sfp::Planner.getcommand(tmp_dir, sas_file, plan_file, Heuristic)
|
379
|
-
Kernel.system(command)
|
375
|
+
benchmarks['search_time'] = Benchmark.measure do
|
376
|
+
planner = ParallelHeuristic.new(tmp_dir, sas_file, plan_file)
|
377
|
+
planner.solve
|
380
378
|
end
|
379
|
+
|
381
380
|
plan = (File.exist?(plan_file) ? File.read(plan_file) : nil)
|
382
381
|
plan = plan_preprocessing(plan)
|
383
382
|
|
@@ -398,6 +397,8 @@ module Sfp
|
|
398
397
|
plan = tmp
|
399
398
|
end
|
400
399
|
|
400
|
+
File.open(tmp_dir + '/' + TranslatorBenchmarkFile, 'w') { |f| f.write(JSON.pretty_generate(benchmarks)) }
|
401
|
+
|
401
402
|
return plan, sas_task
|
402
403
|
rescue Exception => exp
|
403
404
|
raise exp
|
@@ -443,7 +444,7 @@ module Sfp
|
|
443
444
|
single(sum([g(),weight(hFF, 10)]),pref_only=true)],
|
444
445
|
boost=2000),
|
445
446
|
preferred=hFF,reopen_closed=false,cost_type=1)"'
|
446
|
-
when '
|
447
|
+
when 'fd-autotune-2' then ' \
|
447
448
|
--heuristic "hCea=cea(cost_type=2)" \
|
448
449
|
--heuristic "hCg=cg(cost_type=1)" \
|
449
450
|
--heuristic "hGoalCount=goalcount(cost_type=2)" \
|
@@ -458,7 +459,7 @@ module Sfp
|
|
458
459
|
single(sum([weight(g(), 2),weight(hGoalCount, 3)]),pref_only=true)],
|
459
460
|
boost=200),
|
460
461
|
preferred=[hCea,hGoalCount],reopen_closed=false,cost_type=1)"'
|
461
|
-
when '
|
462
|
+
when 'fd-autotune-1' then ' \
|
462
463
|
--heuristic "hFF=ff(cost_type=1)" \
|
463
464
|
--heuristic "hCea=cea(cost_type=0)" \
|
464
465
|
--heuristic "hCg=cg(cost_type=2)" \
|
@@ -514,6 +515,34 @@ module Sfp
|
|
514
515
|
command
|
515
516
|
end
|
516
517
|
|
518
|
+
def self.get_search_command(dir, plan_file, heuristic, timeout=nil)
|
519
|
+
planner = Sfp::Planner.path
|
520
|
+
params = Sfp::Planner.parameters(heuristic)
|
521
|
+
timeout = Sfp::Planner::Config.timeout if timeout.nil?
|
522
|
+
max_memory = Sfp::Planner::Config.max_memory
|
523
|
+
logfile = "search.log." + heuristic
|
524
|
+
|
525
|
+
case `uname -s`.downcase.strip
|
526
|
+
when 'linux'
|
527
|
+
"ulimit -Sv #{max_memory} && timeout #{timeout} nice #{planner}/downward #{params} \
|
528
|
+
--plan-file #{plan_file} < output 1>>#{logfile} 2>>#{logfile}"
|
529
|
+
when 'macos', 'darwin'
|
530
|
+
"ulimit -Sv #{max_memory} && nice #{planner}/downward #{params} \
|
531
|
+
--plan-file #{plan_file} < output 1>>#{logfile} 2>>#{logfile}"
|
532
|
+
else
|
533
|
+
'exit 1'
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
def self.get_preprocess_command(dir, sas_file)
|
538
|
+
case `uname -s`.downcase.strip
|
539
|
+
when 'linux', 'macos', 'darwin'
|
540
|
+
"cd #{dir} && #{Sfp::Planner.path}/preprocess < #{sas_file} 2>/dev/null 1>/dev/null"
|
541
|
+
else
|
542
|
+
"exit 1"
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
517
546
|
# Combination between two heuristic to obtain a suboptimal plan.
|
518
547
|
# 1) solve the problem with CG/CEA/FF, that will produce (usually) a non-optimal plan
|
519
548
|
# 2) remove actions which are not selected by previous step
|
@@ -525,7 +554,7 @@ module Sfp
|
|
525
554
|
@dir = dir
|
526
555
|
@sas_file = sas_file
|
527
556
|
@plan_file = plan_file
|
528
|
-
@heuristics_order = ['ff2', 'cea2', '
|
557
|
+
@heuristics_order = ['ff2', 'cea2', 'fd-autotune1', 'fd-autotune2']
|
529
558
|
@heuristics_order = ENV['SFPLANNER_MIXED_HEURISTICS'].split(',') if ENV['SFPLANNER_MIXED_HEURISTICS']
|
530
559
|
@continue = continue
|
531
560
|
@continue = true if ENV['SFPLANNER_MIXED_CONTINUE']
|
@@ -534,13 +563,13 @@ module Sfp
|
|
534
563
|
|
535
564
|
def solve2
|
536
565
|
if not File.exist?(@plan_file)
|
537
|
-
#
|
538
|
-
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, '
|
566
|
+
#fd-autotune-1
|
567
|
+
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'fd-autotune-1')
|
539
568
|
Kernel.system(planner)
|
540
569
|
end
|
541
570
|
if not File.exist?(@plan_file)
|
542
|
-
#
|
543
|
-
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, '
|
571
|
+
#fd-autotune-2
|
572
|
+
planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'fd-autotune-2')
|
544
573
|
Kernel.system(planner)
|
545
574
|
end
|
546
575
|
if not File.exists?(@plan_file)
|
@@ -664,6 +693,96 @@ module Sfp
|
|
664
693
|
end
|
665
694
|
end
|
666
695
|
|
696
|
+
|
697
|
+
class ParallelHeuristic < MixedHeuristic
|
698
|
+
def initialize(dir, sas_file, plan_file, optimize=false)
|
699
|
+
@dir = dir
|
700
|
+
@sas_file = sas_file
|
701
|
+
@plan_file = plan_file
|
702
|
+
if ENV['SFPLANNER_HEURISTICS']
|
703
|
+
@heuristics = ENV['SFPLANNER_HEURISTICS'].split(',')
|
704
|
+
else
|
705
|
+
@heuristics = ['ff2', 'cea2', 'fd-autotune-1', 'fd-autotune-2']
|
706
|
+
end
|
707
|
+
if ENV['SFPLANNER_OPTIMIZE']
|
708
|
+
@optimize = case ENV['SFPLANNER_OPTIMIZE']
|
709
|
+
when '1', 'true'
|
710
|
+
true
|
711
|
+
else
|
712
|
+
false
|
713
|
+
end
|
714
|
+
else
|
715
|
+
@optimize = optimize
|
716
|
+
end
|
717
|
+
@timeout = (ENV['SFPLANNER_TIMEOUT'] ? ENV['SFPLANNER_TIMEOUT'].to_i : Sfp::Planner::Config.timeout)
|
718
|
+
end
|
719
|
+
|
720
|
+
def solve
|
721
|
+
### run preprocessing
|
722
|
+
return false if not do_preprocess
|
723
|
+
|
724
|
+
### save current working dir
|
725
|
+
home = Dir.pwd
|
726
|
+
|
727
|
+
### change to temporary working dir
|
728
|
+
Dir.chdir @dir
|
729
|
+
|
730
|
+
### run a thread for each heuristic
|
731
|
+
files = []
|
732
|
+
@heuristics.each do |heuristic|
|
733
|
+
plan_file = @plan_file + '.' + heuristic
|
734
|
+
cmd = Sfp::Planner.get_search_command(@dir, plan_file, heuristic, @timeout)
|
735
|
+
pid = Process.spawn cmd
|
736
|
+
Process.detach pid
|
737
|
+
files << plan_file
|
738
|
+
end
|
739
|
+
|
740
|
+
def processes(dir)
|
741
|
+
`ps ax | grep -v grep | grep downward | grep sfplanner | grep '#{dir}' | awk '{print $1" "}'`.to_s.strip.split("\n")
|
742
|
+
end
|
743
|
+
|
744
|
+
loop do
|
745
|
+
list = processes(@dir)
|
746
|
+
break if list.length <= 0
|
747
|
+
finished = files.select { |f| File.exist?(f) }
|
748
|
+
break if finished.length > 0
|
749
|
+
sleep 0.2
|
750
|
+
end
|
751
|
+
|
752
|
+
system "kill -9 " + processes(@dir).join(" ") + " 1>/dev/null 2>/dev/null"
|
753
|
+
|
754
|
+
### select best plan
|
755
|
+
selected = nil
|
756
|
+
length = -1
|
757
|
+
files.each do |file|
|
758
|
+
if File.exist?(file)
|
759
|
+
len = File.read(file).split("\n").length
|
760
|
+
if length < 0 or len < length
|
761
|
+
length = len
|
762
|
+
selected = file
|
763
|
+
end
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
767
|
+
if not selected.nil?
|
768
|
+
FileUtils.copy(selected, @plan_file)
|
769
|
+
optimize_plan if @optimize
|
770
|
+
|
771
|
+
Dir.chdir home
|
772
|
+
true
|
773
|
+
else
|
774
|
+
Dir.chdir home
|
775
|
+
false
|
776
|
+
end
|
777
|
+
end
|
778
|
+
|
779
|
+
def do_preprocess
|
780
|
+
(!!system(Sfp::Planner.get_preprocess_command(@dir, @sas_file)) &&
|
781
|
+
File.exist?(@dir + '/output'))
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
|
667
786
|
class Action
|
668
787
|
attr_accessor :operator, :predecessor
|
669
788
|
|
data/lib/sfplanner.rb
CHANGED
@@ -4,8 +4,7 @@ require 'json'
|
|
4
4
|
require 'sfp'
|
5
5
|
|
6
6
|
# internal dependencies
|
7
|
-
libdir = File.
|
8
|
-
|
9
|
-
require libdir
|
10
|
-
|
11
|
-
require libdir + '/sfplanner/planner'
|
7
|
+
libdir = File.dirname(__FILE__) + '/sfplanner'
|
8
|
+
Dir.entries(libdir).each do |item|
|
9
|
+
require "#{libdir}/#{item}" if File.extname(item) == '.rb'
|
10
|
+
end
|
data/sfplanner.gemspec
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.name
|
3
|
-
s.version
|
4
|
-
s.date
|
5
|
-
s.summary
|
6
|
-
s.description
|
7
|
-
s.authors
|
8
|
-
s.email
|
2
|
+
s.name = 'sfplanner'
|
3
|
+
s.version = File.read(File.dirname(__FILE__) + '/VERSION').strip
|
4
|
+
s.date = File.atime(File.dirname(__FILE__) + '/VERSION').strftime("%Y-%m-%d").to_s
|
5
|
+
s.summary = 'SFPlanner'
|
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
|
+
s.authors = ['Herry']
|
8
|
+
s.email = 'herry13@gmail.com'
|
9
9
|
|
10
|
-
s.executables
|
11
|
-
s.
|
12
|
-
s.files = `git ls-files`.split("\n")
|
10
|
+
s.executables << 'sfplanner'
|
11
|
+
s.files = `git ls-files`.split("\n")
|
13
12
|
|
14
13
|
s.require_paths = ['lib']
|
15
14
|
s.license = 'BSD'
|
16
15
|
|
17
|
-
s.homepage
|
18
|
-
s.rubyforge_project
|
16
|
+
s.homepage = 'https://github.com/herry13/sfplanner'
|
17
|
+
s.rubyforge_project = 'sfplanner'
|
19
18
|
|
20
|
-
s.add_dependency
|
19
|
+
s.add_dependency 'sfp', '~> 0.3.19'
|
21
20
|
|
22
21
|
s.add_development_dependency 'rake'
|
23
22
|
end
|
metadata
CHANGED
@@ -1,45 +1,49 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sfplanner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Herry
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-11-20 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: sfp
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.3.
|
19
|
+
version: 0.3.19
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.19
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: rake
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
|
-
- -
|
31
|
+
- - '>='
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
36
41
|
description: A Ruby gem that provides a Ruby API and a script to the SFP planner.
|
37
42
|
This planner can automatically generate a plan that solves a planning problem written
|
38
43
|
in SFP language.
|
39
44
|
email: herry13@gmail.com
|
40
45
|
executables:
|
41
46
|
- sfplanner
|
42
|
-
- sfw2graph
|
43
47
|
extensions: []
|
44
48
|
extra_rdoc_files: []
|
45
49
|
files:
|
@@ -74,26 +78,25 @@ files:
|
|
74
78
|
homepage: https://github.com/herry13/sfplanner
|
75
79
|
licenses:
|
76
80
|
- BSD
|
81
|
+
metadata: {}
|
77
82
|
post_install_message:
|
78
83
|
rdoc_options: []
|
79
84
|
require_paths:
|
80
85
|
- lib
|
81
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
87
|
requirements:
|
84
|
-
- -
|
88
|
+
- - '>='
|
85
89
|
- !ruby/object:Gem::Version
|
86
90
|
version: '0'
|
87
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
-
none: false
|
89
92
|
requirements:
|
90
|
-
- -
|
93
|
+
- - '>='
|
91
94
|
- !ruby/object:Gem::Version
|
92
95
|
version: '0'
|
93
96
|
requirements: []
|
94
97
|
rubyforge_project: sfplanner
|
95
|
-
rubygems_version: 1.
|
98
|
+
rubygems_version: 2.1.10
|
96
99
|
signing_key:
|
97
|
-
specification_version:
|
100
|
+
specification_version: 4
|
98
101
|
summary: SFPlanner
|
99
102
|
test_files: []
|