Permalink
Browse files

Add second version of the general problem solver

  • Loading branch information...
1 parent fabedce commit dd27d9e75b62c4a7a613c855843195d821d1e455 @olabini olabini committed Sep 13, 2008
Showing with 79 additions and 0 deletions.
  1. +79 −0 lib/ch04/gps2.rb
View
79 lib/ch04/gps2.rb
@@ -0,0 +1,79 @@
+require 'gps'
+require 'gps_no_clobber'
+require 'dbg'
+
+module Enumerable
+ def some?
+ self.each do |v|
+ result = yield v
+ return result if result
+ end
+ end
+end
+
+class GPS::Op
+ def convert!
+ unless self.add_list.any? { |l| l.is_a?(Array) && l.first == :executing }
+ self.add_list << [:executing, self.action]
+ end
+ self
+ end
+end
+
+GPS::SCHOOL_OPS.each do |op|
+ op.convert!
+end
+
+class GPS2 < GPS
+ class << self
+ def op(action, parts = {})
+ GPS::Op.new(action,
+ parts[:preconds],
+ parts[:add_list],
+ parts[:del_list]).convert!
+ end
+ end
+
+ def solve(*goals)
+ achieve_all([[:start]] + @state, goals, []).grep(Array)
+ end
+
+ def achieve_all(state, goals, goal_stack)
+ current_state = goals.inject(state) do |current_state, g|
+ return [] if current_state.empty?
+ achieve(current_state, g, goal_stack)
+ end
+ if goals.subset_of?(current_state)
+ current_state
+ else
+ []
+ end
+ end
+
+ def achieve(state, goal, goal_stack)
+ dbg_indent(:gps, goal_stack.length, "Goal: %p", goal)
+
+ if state.include?(goal)
+ state
+ elsif goal_stack.include?(goal)
+ []
+ else
+ @ops.find_all do |op|
+ appropriate?(goal, op)
+ end.some? do |op|
+ apply(state, goal, op, goal_stack)
+ end || []
+ end
+ end
+
+ def apply(state, goal, op, goal_stack)
+ dbg_indent(:gps, goal_stack.length, "Consider: %p", op.action)
+
+ state2 = achieve_all(state, op.preconds, [goal] + goal_stack)
+
+ unless state2.empty?
+ dbg_indent(:gps, goal_stack.length, "Action: %p", op.action)
+ (state2 - op.del_list) + op.add_list
+ end
+ end
+end

0 comments on commit dd27d9e

Please sign in to comment.