// Copyright 2010-2018 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OR_TOOLS_SAT_INTEGER_SEARCH_H_ #define OR_TOOLS_SAT_INTEGER_SEARCH_H_ #include #include "ortools/sat/integer.h" #include "ortools/sat/sat_solver.h" namespace operations_research { namespace sat { // Decision heuristic for SolveIntegerProblemWithLazyEncoding(). Returns a // function that will return the literal corresponding to the fact that the // first currently non-fixed variable value is <= its min. The function will // return kNoLiteralIndex if all the given variables are fixed. // // Note that this function will create the associated literal if needed. std::function FirstUnassignedVarAtItsMinHeuristic( const std::vector& vars, Model* model); // Decision heuristic for SolveIntegerProblemWithLazyEncoding(). Like // FirstUnassignedVarAtItsMinHeuristic() but the function will return the // literal corresponding to the fact that the currently non-assigned variable // with the lowest min has a value <= this min. std::function UnassignedVarWithLowestMinAtItsMinHeuristic( const std::vector& vars, Model* model); // Set the first unassigned Literal/Variable to its value. // // TODO(user): This is currently quadratic as we scan all variables to find the // first unassigned one. Fix. Note that this is also the case in many other // heuristics and should be fixed. struct BooleanOrIntegerVariable { BooleanVariable bool_var = kNoBooleanVariable; IntegerVariable int_var = kNoIntegerVariable; }; std::function FollowHint( const std::vector& vars, const std::vector& values, Model* model); // Combines search heuristics in order: if the i-th one returns kNoLiteralIndex, // ask the (i+1)-th. If every heuristic returned kNoLiteralIndex, // returns kNoLiteralIndex. std::function SequentialSearch( std::vector> heuristics); // Returns the LiteralIndex advised by the underliying SAT solver. std::function SatSolverHeuristic(Model* model); // Uses the given heuristics, but when the LP relaxation has an integer // solution, use it to change the polarity of the next decision so that the // solver will check if this integer LP solution satisfy all the constraints. std::function ExploitIntegerLpSolution( std::function heuristic, Model* model); // A restart policy that restarts every k failures. std::function RestartEveryKFailures(int k, SatSolver* solver); // A restart policy that uses the underlying sat solver's policy. std::function SatSolverRestartPolicy(Model* model); // Appends model-owned automatic heuristics to input_heuristics in a new vector. std::vector> AddModelHeuristics( const std::vector>& input_heuristics, Model* model); // Concatenates each input_heuristic with a default heuristic that instantiate // all the problem's Boolean variables, into a new vector. std::vector> CompleteHeuristics( const std::vector>& incomplete_heuristics, const std::function& completion_heuristic); // A wrapper around SatSolver::Solve that handles integer variable with lazy // encoding. Repeatedly calls SatSolver::Solve() on the model until the given // next_decision() function return kNoLiteralIndex or the model is proved to // be UNSAT. // // Returns the status of the last call to SatSolver::Solve(). // // Note that the next_decision() function must always return an unassigned // literal or kNoLiteralIndex to end the search. SatSolver::Status SolveIntegerProblemWithLazyEncoding( const std::vector& assumptions, const std::function& next_decision, Model* model); // Solves a problem with the given heuristics. // heuristics[i] will be used with restart_policies[i] only. SatSolver::Status SolveProblemWithPortfolioSearch( std::vector> decision_policies, std::vector> restart_policies, Model* model); // Shortcut for SolveIntegerProblemWithLazyEncoding() when there is no // assumption and we consider all variables in their index order for the next // search decision. SatSolver::Status SolveIntegerProblemWithLazyEncoding(Model* model); // Store relationship between the CpSolverResponse objective and the internal // IntegerVariable the solver tries to minimize. struct ObjectiveSynchronizationHelper { double scaling_factor = 1.0; double offset = 0.0; IntegerVariable objective_var = kNoIntegerVariable; std::function get_external_best_objective = nullptr; std::function get_external_best_bound = nullptr; bool broadcast_lower_bound = false; int64 UnscaledObjective(double value) const { return static_cast(std::round(value / scaling_factor - offset)); } }; // Callbacks that be called when the search goes back to level 0. // Callbacks should return false if the propagation fails. struct LevelZeroCallbackHelper { std::vector> callbacks; }; // Prints out a new solution in a fixed format. void LogNewSolution(const std::string& event_or_solution_count, double time_in_seconds, double obj_lb, double obj_ub, const std::string& solution_info); } // namespace sat } // namespace operations_research #endif // OR_TOOLS_SAT_INTEGER_SEARCH_H_