sfplanner 0.1.5 → 0.2.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.
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.8.7)
29
+ - Ruby (>= 1.9.2)
32
30
  - Graphviz
33
31
  - Rubygems
34
- - sfp (>= 0.3.0)
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.5
1
+ 0.2.1
@@ -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_' + (rand * 100000).to_i.abs.to_s
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
- File.open(sas_file, 'w') do |f|
369
- #f.write(parser.to_sas)
370
- f.write(parser.sas)
371
- f.flush
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
- if Heuristic == 'mixed'
375
- mixed = MixedHeuristic.new(tmp_dir, sas_file, plan_file)
376
- mixed.solve
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 'autotune22' then ' \
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 'autotune12' then ' \
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', 'autotune12', 'autotune22']
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
- #autotune12 (see fd-autotune-1)
538
- planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'autotune12')
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
- #autotune22 (see fd-autotune-2)
543
- planner = Sfp::Planner.getcommand(@dir, @sas_file, @plan_file, 'autotune22')
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.expand_path(File.dirname(__FILE__))
8
-
9
- require libdir + '/sfplanner/sas'
10
- require libdir + '/sfplanner/graph.rb'
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 = 'sfplanner'
3
- s.version = File.read(File.join(File.dirname(__FILE__), 'VERSION')).sub(/\n/, '')
4
- s.date = '2013-08-13'
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'
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 << 'sfplanner'
11
- s.executables << 'sfw2graph'
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 = 'https://github.com/herry13/sfplanner'
18
- s.rubyforge_project = 'sfplanner'
16
+ s.homepage = 'https://github.com/herry13/sfplanner'
17
+ s.rubyforge_project = 'sfplanner'
19
18
 
20
- s.add_dependency 'sfp', '~> 0.3.17'
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
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-08-13 00:00:00.000000000 Z
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: &18815260 !ruby/object:Gem::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.17
19
+ version: 0.3.19
22
20
  type: :runtime
23
21
  prerelease: false
24
- version_requirements: *18815260
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: &18814780 !ruby/object:Gem::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: *18814780
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.8.11
98
+ rubygems_version: 2.1.10
96
99
  signing_key:
97
- specification_version: 3
100
+ specification_version: 4
98
101
  summary: SFPlanner
99
102
  test_files: []