module Gecode class Model # Finds the first solution to the modelled problem and updates the variables # to that solution. Returns the model if a solution was found, nil # otherwise. def solve! GC.disable space = dfs_engine.next GC.enable return nil if space.nil? @active_space = space return self end # Returns to the original state, before any search was made (but propagation # might have been performed). Returns the reset model. def reset! @active_space = base_space return self end # Yields the first solution (if any) to the block. If no solution is found # then the block is not used. Returns the result of the block (nil in case # the block wasn't run). def solution(&block) solution = self.solve! res = yield solution unless solution.nil? self.reset! return res end # Yields each solution that the model has. def each_solution(&block) dfs = dfs_engine GC.disable while not (@active_space = dfs.next).nil? yield self end GC.enable 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) # Execute constraints. perform_queued_gecode_interactions # Set the method used for constrain calls by the BAB-search. Model.constrain_proc = lambda do |home_space, best_space| @active_space = best_space @variable_creation_space = home_space yield(self, self) @active_space = home_space @variable_creation_space = nil perform_queued_gecode_interactions end # Perform the search. GC.disable result = Gecode::Raw::bab(selected_space, Gecode::Raw::Search::Config::MINIMAL_DISTANCE, Gecode::Raw::Search::Config::ADAPTIVE_DISTANCE, nil) GC.enable # Reset the method used constrain calls and return the result. Model.constrain_proc = nil return nil if result.nil? # Refresh the solution. result.refresh refresh_variables @active_space = result return self end class <