lib/gecoder/interface/search.rb in gecoder-0.5.0 vs lib/gecoder/interface/search.rb in gecoder-0.6.0
- old
+ new
@@ -34,22 +34,91 @@
yield self
end
self.reset!
end
+ # Finds the optimal solution. Optimality is defined by the provided block
+ # which is given one parameter, a solution to the problem. The block should
+ # constrain the solution so that that only "better" solutions can be new
+ # solutions. For instance if one wants to optimize a variable named price
+ # (accessible from the model) to be as low as possible then one should write
+ # the following.
+ #
+ # model.optimize! do |model, best_so_far|
+ # model.price.must < best_so_far.price.val
+ # end
+ #
+ # Returns nil if there is no solution.
+ def optimize!(&block)
+ next_space = nil
+ best_space = nil
+ bab = bab_engine
+
+ Model.constrain_proc = lambda do |home_space, best_space|
+ @active_space = best_space
+ yield(self, self)
+ @active_space = home_space
+ perform_queued_gecode_interactions
+ end
+
+ while not (next_space = bab.next).nil?
+ best_space = next_space
+ end
+ Model.constrain_proc = nil
+ return nil if best_space.nil?
+ return self
+ end
+
+ class <<self
+ def constrain_proc=(proc)
+ @constrain_proc = proc
+ end
+
+ def constrain(home, best)
+ if @constrain_proc.nil?
+ raise NotImplementedError, 'Constrain method not implemented.'
+ else
+ @constrain_proc.call(home, best)
+ end
+ end
+ end
+
private
- # Creates an DFS engine for the search, executing any unexecuted
- # constraints first.
+ # Creates a depth first search engine for search, executing any
+ # unexecuted constraints first.
def dfs_engine
# Execute constraints.
- constraints.each{ |con| con.post }
- constraints.clear # Empty the queue.
+ perform_queued_gecode_interactions
+
+ # Construct the engine.
+ stop = Gecode::Raw::Search::Stop.new
+ Gecode::Raw::DFS.new(selected_space,
+ Gecode::Raw::Search::Config::MINIMAL_DISTANCE,
+ Gecode::Raw::Search::Config::ADAPTIVE_DISTANCE,
+ stop)
+ end
+ # Creates a branch and bound engine for optimization search, executing any
+ # unexecuted constraints first.
+ def bab_engine
+ # Execute constraints.
+ perform_queued_gecode_interactions
+
+ # Construct the engine.
stop = Gecode::Raw::Search::Stop.new
- Gecode::Raw::DFS.new(active_space,
+ Gecode::Raw::BAB.new(selected_space,
Gecode::Raw::Search::Config::MINIMAL_DISTANCE,
Gecode::Raw::Search::Config::ADAPTIVE_DISTANCE,
stop)
+ end
+
+ # Executes any interactions with Gecode still waiting in the queue
+ # (emptying the queue) in the process.
+ def perform_queued_gecode_interactions
+ allow_space_access do
+ gecode_interaction_queue.each{ |con| con.call }
+ gecode_interaction_queue.clear # Empty the queue.
+ end
end
end
end