// 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_BOP_BOP_SOLUTION_H_ #define OR_TOOLS_BOP_BOP_SOLUTION_H_ #include "ortools/bop/bop_types.h" #include "ortools/sat/boolean_problem.h" #include "ortools/sat/boolean_problem.pb.h" namespace operations_research { namespace bop { // A Bop solution is a Boolean assignment for each variable of the problem. The // cost value associated to the solution is the instantiation of the objective // cost of the problem. // // Note that a solution might not be a feasible solution, i.e. might violate // some constraints of the problem. The IsFeasible() method can be used to test // the feasibility. class BopSolution { public: BopSolution(const sat::LinearBooleanProblem& problem, const std::string& name); void SetValue(VariableIndex var, bool value) { recompute_cost_ = true; recompute_is_feasible_ = true; values_[var] = value; } size_t Size() const { return values_.size(); } bool Value(VariableIndex var) const { return values_[var]; } const std::string& name() const { return name_; } void set_name(const std::string& name) { name_ = name; } // Returns the objective cost of the solution. // Note that this code is lazy but not incremental and might run in the // problem size. Use with care during search. int64 GetCost() const { if (recompute_cost_) { cost_ = ComputeCost(); } return cost_; } // Returns the objective cost of the solution taking into account the problem // cost scaling and offset. This is mainly useful for displaying the current // problem cost, while internally, the algorithm works directly with the // integer version of the cost returned by GetCost(). double GetScaledCost() const { return sat::AddOffsetAndScaleObjectiveValue(*problem_, sat::Coefficient(GetCost())); } // Returns true iff the solution is feasible. // Note that this code is lazy but not incremental and might run in the // problem size. Use with care during search. bool IsFeasible() const { if (recompute_is_feasible_) { is_feasible_ = ComputeIsFeasible(); } return is_feasible_; } // For range based iteration, i.e. for (const bool value : solution) {...}. gtl::ITIVector::const_iterator begin() const { return values_.begin(); } gtl::ITIVector::const_iterator end() const { return values_.end(); } // Returns true when the cost of the argument solution is strictly greater // than the cost of the object. // This is used to sort solutions. bool operator<(const BopSolution& solution) const { return IsFeasible() == solution.IsFeasible() ? GetCost() < solution.GetCost() : IsFeasible() > solution.IsFeasible(); } private: bool ComputeIsFeasible() const; int64 ComputeCost() const; const sat::LinearBooleanProblem* problem_; std::string name_; gtl::ITIVector values_; // Those are mutable because they behave as const values for a given solution // but for performance reasons we want to be lazy on their computation, // e.g. not compute the cost each time set_value() is called. mutable bool recompute_cost_; mutable bool recompute_is_feasible_; mutable int64 cost_; mutable bool is_feasible_; // Note that assign/copy are defined to allow usage of // STL collections / algorithms. }; } // namespace bop } // namespace operations_research #endif // OR_TOOLS_BOP_BOP_SOLUTION_H_