longjing 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,138 @@
1
+ require 'set'
2
+ require 'longjing/search/base'
3
+ require 'longjing/ff/preprocess'
4
+ require 'longjing/ff/connectivity_graph'
5
+ require 'longjing/ff/ordering'
6
+ require 'longjing/ff/relaxed_graph_plan'
7
+
8
+ module Longjing
9
+ module PDDL
10
+ class Literal
11
+ attr_accessor :ff_neg_goal
12
+ end
13
+ end
14
+
15
+ module Search
16
+ def self.ff
17
+ FF
18
+ end
19
+
20
+ class FF < Base
21
+ include Longjing::FF
22
+
23
+ def init(problem)
24
+ log { 'Preprocess' }
25
+ @problem = Preprocess.new.execute(problem)
26
+ log { 'Propositionalized problem:' }
27
+ log { "# actions: #{@problem.all_actions.size}" }
28
+ log { 'Initialize graphs' }
29
+ cg = ConnectivityGraph.new(@problem)
30
+ @h = RelaxedGraphPlan.new(cg)
31
+ @ordering = Ordering.new(cg)
32
+ end
33
+
34
+ def search(problem)
35
+ log { 'FF search starts' }
36
+ init(problem)
37
+ log { "Build goal agenda" }
38
+ agenda = @ordering.goal_agenda(@problem)
39
+ log { "Goal agenda:" }
40
+ log(:facts, agenda)
41
+ goal = []
42
+ state = @problem.initial
43
+ agenda.each do |g|
44
+ goal << g
45
+ unless state = hill_climbing(state, goal)
46
+ return greedy_search
47
+ end
48
+ end
49
+ solution(state)
50
+ end
51
+
52
+ def hill_climbing(state, goal_list)
53
+ log { "Hill climbing, goal:" }
54
+ log(:facts, goal_list)
55
+ reset_best_heuristic
56
+
57
+ best = if relaxed_solution = @h.extract(goal_list, state)
58
+ distance(relaxed_solution)
59
+ end
60
+ logger.debug { "Initial cost: #{best}" }
61
+ return unless best
62
+ state.cost = best
63
+ helpful_actions = relaxed_solution[1]
64
+ goal_set = goal_list.to_set
65
+ until best == 0 do
66
+ state, best, helpful_actions = breadth_first([state],
67
+ best,
68
+ helpful_actions,
69
+ goal_set,
70
+ goal_list)
71
+ return unless state
72
+ logger.debug { "----\nState: #{state}\nCost: #{best}\nPath: #{state.path.map(&:signature).join("\n")}" }
73
+ end
74
+ state
75
+ end
76
+
77
+ def breadth_first(frontier, best, helpful_actions,
78
+ goal_set, goal_list)
79
+ known = Hash[frontier.map{|f| [f, true]}]
80
+ until frontier.empty? do
81
+ state = frontier.shift
82
+ statistics.expanded += 1
83
+
84
+ log(:exploring, state)
85
+ log_progress(state)
86
+
87
+ actions = helpful_actions || @problem.actions(state)
88
+ helpful_actions = nil
89
+ actions.each do |action|
90
+ new_state = @problem.result(action, state)
91
+ statistics.generated += 1
92
+ log(:action, action, new_state)
93
+ if known.include?(new_state)
94
+ logger.debug { "Known state" }
95
+ next
96
+ end
97
+
98
+ added_goals = Hash[action.effect.to_a.select{|lit| goal_set.include?(lit)}.map{|k| [k, true]}]
99
+ if solution = @h.extract(goal_list, new_state, added_goals)
100
+ dist = distance(solution)
101
+ new_state.cost = dist
102
+ log(:heuristic, new_state, solution, dist, best)
103
+ if dist < best
104
+ return [new_state, dist, solution[1]]
105
+ else
106
+ known[new_state] = true
107
+ frontier << new_state
108
+ end
109
+ else
110
+ # ignore infinite heuristic state
111
+ logger.debug { "No relaxed solution" }
112
+ end
113
+ statistics.evaluated += 1
114
+ end
115
+ end
116
+ return nil
117
+ end
118
+
119
+ def greedy_search
120
+ reset_best_heuristic
121
+ goal_list = @problem.goal.to_a
122
+ greedy = Greedy.new
123
+ heuristic = lambda {|state| distance(@h.extract(goal_list, state))}
124
+ greedy.search(@problem, heuristic)
125
+ end
126
+
127
+
128
+ def distance(relaxed)
129
+ return Float::INFINITY if relaxed.nil?
130
+ if relaxed[0].empty?
131
+ 0
132
+ else
133
+ relaxed[0].map(&:size).reduce(:+)
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,28 @@
1
+ require 'set'
2
+ require 'longjing/search/base'
3
+ require 'longjing/ff/preprocess'
4
+ require 'longjing/ff/connectivity_graph'
5
+ require 'longjing/ff/ordering'
6
+ require 'longjing/ff/relaxed_graph_plan'
7
+
8
+ module Longjing
9
+ module PDDL
10
+ class Literal
11
+ attr_accessor :ff_neg_goal
12
+ end
13
+ end
14
+
15
+ module Search
16
+ def self.ff_greedy
17
+ FFGreedy
18
+ end
19
+
20
+ class FFGreedy < FF
21
+ def search(problem)
22
+ log { 'FF greedy search starts' }
23
+ init(problem)
24
+ greedy_search
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,43 @@
1
+ require 'set'
2
+ require 'longjing/search/base'
3
+
4
+ module Longjing
5
+ module Search
6
+ class Greedy < Base
7
+ def search(problem, heuristic)
8
+ log { "Greedy search" }
9
+ initial = problem.initial
10
+ if problem.goal?(initial)
11
+ return solution(initial)
12
+ end
13
+ initial.cost = heuristic.call(initial)
14
+ frontier = SortedSet.new([initial])
15
+ known = {initial => true}
16
+ until frontier.empty? do
17
+ state = frontier.first
18
+ statistics.expanded += 1
19
+ frontier.delete(state)
20
+ log(:exploring, state)
21
+ log_progress(state)
22
+ problem.actions(state).each do |action|
23
+ new_state = problem.result(action, state)
24
+ statistics.generated += 1
25
+ log(:action, action, new_state)
26
+ if known.include?(new_state)
27
+ logger.debug { "Known state" }
28
+ next
29
+ end
30
+ if problem.goal?(new_state)
31
+ return solution(new_state)
32
+ end
33
+ new_state.cost = heuristic.call(new_state)
34
+ statistics.evaluated += 1
35
+ known[new_state] = true
36
+ frontier << new_state
37
+ end
38
+ end
39
+ no_solution
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ module Longjing
2
+ module Search
3
+ class Statistics
4
+ attr_accessor :generated, :expanded, :evaluated
5
+ def initialize
6
+ @generated, @expanded, @evaluated = 0, 0, 0
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ module Longjing
2
+ class State
3
+ attr_reader :raw, :path, :hash
4
+ attr_accessor :cost
5
+
6
+ def initialize(raw, path=[])
7
+ @raw = raw
8
+ @path = path
9
+ @hash = @raw.hash
10
+ @cost = 0
11
+ end
12
+
13
+ def ==(state)
14
+ return true if state.object_id == self.object_id
15
+ @raw == state.raw
16
+ end
17
+ alias :eql? :==
18
+
19
+ def to_s
20
+ "{#{@raw.to_a.join(" ")}}"
21
+ end
22
+
23
+ def <=>(s)
24
+ @cost <=> s.cost
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Longjing
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'longjing/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "longjing"
8
+ spec.version = Longjing::VERSION
9
+ spec.authors = ["Xiao Li"]
10
+ spec.email = ["swing1979@gmail.com"]
11
+
12
+ spec.summary = %q{Longjing is classical planner.}
13
+ spec.description = %q{Longjing is classical planner for learning classical planning algorithms.}
14
+ spec.homepage = "https://github.com/xli/longjing"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "ruby-prof"
24
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: longjing
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Xiao Li
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-08-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ruby-prof
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Longjing is classical planner for learning classical planning algorithms.
56
+ email:
57
+ - swing1979@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".ruby-version"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - README.md
67
+ - Rakefile
68
+ - TODO
69
+ - benchmark.log
70
+ - bin/console
71
+ - bin/longjing
72
+ - bin/setup
73
+ - lib/longjing.rb
74
+ - lib/longjing/ff/action.rb
75
+ - lib/longjing/ff/connectivity_graph.rb
76
+ - lib/longjing/ff/ordering.rb
77
+ - lib/longjing/ff/preprocess.rb
78
+ - lib/longjing/ff/relaxed_graph_plan.rb
79
+ - lib/longjing/logging.rb
80
+ - lib/longjing/parameters.rb
81
+ - lib/longjing/pddl.rb
82
+ - lib/longjing/pddl/action.rb
83
+ - lib/longjing/pddl/literal.rb
84
+ - lib/longjing/pddl/obj.rb
85
+ - lib/longjing/pddl/parser.tab.rb
86
+ - lib/longjing/pddl/parser.y
87
+ - lib/longjing/pddl/predicate.rb
88
+ - lib/longjing/pddl/type.rb
89
+ - lib/longjing/pddl/var.rb
90
+ - lib/longjing/problem.rb
91
+ - lib/longjing/search.rb
92
+ - lib/longjing/search/base.rb
93
+ - lib/longjing/search/ff.rb
94
+ - lib/longjing/search/ff_greedy.rb
95
+ - lib/longjing/search/greedy.rb
96
+ - lib/longjing/search/statistics.rb
97
+ - lib/longjing/state.rb
98
+ - lib/longjing/version.rb
99
+ - longjing.gemspec
100
+ homepage: https://github.com/xli/longjing
101
+ licenses: []
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.4.5
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Longjing is classical planner.
123
+ test_files: []