SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
Optimization.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include <carl-formula/model/Model.h>
5 #include <smtrat-solver/Module.h>
6 
7 namespace smtrat {
8 
9 template<typename Solver>
10 class Optimization {
11 private:
12  Solver& mSolver;
13 
14  struct Objective {
15  Poly function;
16  bool minimize;
17  };
18  std::vector<Objective> mObjectives;
19 
20  const std::vector<Objective>& objectives() const {
21  return mObjectives;
22  }
23 
24  carl::Variable mOptimizationVarInt;
25  carl::Variable mOptimizationVarReal;
26 
27  const carl::Variable& objectiveVariable(const Objective& objective) const {
28  return objective.function.integer_valued() ? mOptimizationVarInt : mOptimizationVarReal;
29  }
30 
31 public:
32  Optimization(Solver& s) :
33  mSolver(s) ,
34  mOptimizationVarInt(carl::fresh_integer_variable("__opt_int")),
35  mOptimizationVarReal(carl::fresh_real_variable("__opt_real"))
36  {}
37 
38  void add_objective(const Poly& objective, bool minimize = true) {
39  mObjectives.push_back({ objective, minimize });
40  }
41 
42  void remove_objective(const Poly& objective) {
43  mObjectives.erase(std::remove_if(
44  mObjectives.begin(), mObjectives.end(),
45  [&objective](const auto& e) {
46  return e.function == objective;
47  }));
48  }
49 
50  void reset() {
51  mObjectives.clear();
52  }
53 
54  bool active() const {
55  return !mObjectives.empty();
56  }
57 
58  std::tuple<Answer,Model,ObjectiveValues> compute(bool full = true) {
59  SMTRAT_LOG_INFO("smtrat.optimization", "Running Optimization.");
60 
61  ObjectiveValues optimalValues;
62  mSolver.push();
63 
64  bool isOptimal = true;
65  Model model;
66  for (auto iter = objectives().begin(); iter != objectives().end(); iter++) {
67  const auto& objective = *iter;
68  SMTRAT_LOG_DEBUG("smtrat.optimization", "Optimizing objective " << objective.function << " (minimize=" << objective.minimize << ")");
69  FormulaT objectiveEquality( (objective.minimize ? objective.function : -(objective.function)) - objectiveVariable(objective), carl::Relation::EQ );
70 
71  SMTRAT_LOG_TRACE("smtrat.optimization", "Adding objective function " << objectiveEquality << " and set objective variable " << objectiveVariable(objective));
72  mSolver.setObjectiveVariable(objectiveVariable(objective));
73  mSolver.add(objectiveEquality);
74  Answer result = mSolver.check(full);
75  SMTRAT_LOG_TRACE("smtrat.optimization", "Got response " << result << ", cleaning up...");
76  mSolver.remove(objectiveEquality);
77  mSolver.setObjectiveVariable(carl::Variable::NO_VARIABLE);
78  if (!is_sat(result)) {
79  mSolver.pop();
80  return std::make_tuple(result, Model(), ObjectiveValues());
81  }
82  model = mSolver.model();
83  SMTRAT_LOG_TRACE("smtrat.optimization", "Got model " << model);
84  isOptimal = isOptimal && result == OPTIMAL;
85 
86  // get optimal value fur current variable
87  auto objModel = model.find(objectiveVariable(objective));
88  assert(objModel != model.end());
89  // TODO how to handle other types?:
90  ModelValue optVal;
91  if (objModel->second.isMinusInfinity()) {
92  optVal = objective.minimize ? objModel->second.asInfinity() : InfinityValue{true};
93  SMTRAT_LOG_TRACE("smtrat.optimization", "Found optimal value -oo resp. oo");
94  }
95  else {
96  assert(objModel->second.isRational());
97  optVal = (objective.minimize ? objModel->second.asRational() : -(objModel->second.asRational()));
98  SMTRAT_LOG_TRACE("smtrat.optimization", "Found optimal value " << optVal.asRational());
99  }
100  optimalValues.emplace_back(objective.function, optVal);
101 
102  // add bound
103  if (iter+1 != objectives().end()) {
104  assert(objModel->second.isRational());
105  FormulaT minimumUpperBound( (objective.minimize ? objective.function : -(objective.function)) - objModel->second.asRational(), carl::Relation::LEQ );
106  SMTRAT_LOG_TRACE("smtrat.optimization", "Adding minimum upper bound " << minimumUpperBound);
107  mSolver.add(minimumUpperBound);
108  }
109  }
110  mSolver.pop();
111  if (!isOptimal) {
112  SMTRAT_LOG_WARN("smtrat.optimization", "Answer not necessarily optimal!");
113  }
114  SMTRAT_LOG_TRACE("smtrat.optimization", "Removing optimization variables from model");
115  model.erase(mOptimizationVarInt);
116  model.erase(mOptimizationVarReal);
117  return std::make_tuple(isOptimal ? OPTIMAL : SAT, model, optimalValues);
118  }
119 };
120 
121 }
carl::Variable mOptimizationVarInt
Definition: Optimization.h:24
const carl::Variable & objectiveVariable(const Objective &objective) const
Definition: Optimization.h:27
Optimization(Solver &s)
Definition: Optimization.h:32
std::vector< Objective > mObjectives
Definition: Optimization.h:18
void add_objective(const Poly &objective, bool minimize=true)
Definition: Optimization.h:38
carl::Variable mOptimizationVarReal
Definition: Optimization.h:25
void remove_objective(const Poly &objective)
Definition: Optimization.h:42
const std::vector< Objective > & objectives() const
Definition: Optimization.h:20
std::tuple< Answer, Model, ObjectiveValues > compute(bool full=true)
Definition: Optimization.h:58
bool active() const
Definition: Optimization.h:54
Class to create the formulas for axioms.
carl::ModelValue< Rational, Poly > ModelValue
Definition: model.h:12
bool is_sat(Answer a)
Definition: types.h:58
carl::Formula< Poly > FormulaT
Definition: types.h:37
std::vector< std::pair< std::variant< Poly, std::string >, Model::mapped_type > > ObjectiveValues
Definition: model.h:32
carl::Model< Rational, Poly > Model
Definition: model.h:13
carl::MultivariatePolynomial< Rational > Poly
Definition: types.h:25
Answer
An enum with the possible answers a Module can give.
Definition: types.h:57
@ SAT
Definition: types.h:57
@ OPTIMAL
Definition: types.h:57
carl::InfinityValue InfinityValue
Definition: model.h:20
#define SMTRAT_LOG_TRACE(channel, msg)
Definition: logging.h:36
#define SMTRAT_LOG_WARN(channel, msg)
Definition: logging.h:33
#define SMTRAT_LOG_INFO(channel, msg)
Definition: logging.h:34
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35