summaryrefslogtreecommitdiff
path: root/src/omt/integer_optimizer.cpp
blob: 8fbfff1a2b475702863e310b507af9c190da6e7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/******************************************************************************
 * Top contributors (to current version):
 *   Yancheng Ou, Michael Chang
 *
 * This file is part of the cvc5 project.
 *
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
 * in the top-level source directory and their institutional affiliations.
 * All rights reserved.  See the file COPYING in the top-level source
 * directory for licensing information.
 * ****************************************************************************
 *
 * Optimizer for Integer type.
 */

#include "omt/integer_optimizer.h"

#include "options/smt_options.h"
#include "smt/smt_engine.h"

using namespace cvc5::smt;
namespace cvc5::omt {

OptimizationResult OMTOptimizerInteger::optimize(
    SmtEngine* parentSMTSolver,
    TNode target,
    OptimizationObjective::ObjectiveType objType)
{
  // linear search for integer goal
  // the smt engine to which we send intermediate queries
  // for the linear search.
  std::unique_ptr<SmtEngine> optChecker =
      OMTOptimizer::createOptCheckerWithTimeout(parentSMTSolver, false);
  NodeManager* nm = optChecker->getNodeManager();

  Result intermediateSatResult = optChecker->checkSat();
  // Model-value of objective (used in optimization loop)
  Node value;
  if (intermediateSatResult.isUnknown())
  {
    return OptimizationResult(OptimizationResult::UNKNOWN, value);
  }
  if (intermediateSatResult.isSat() == Result::UNSAT)
  {
    return OptimizationResult(OptimizationResult::UNSAT, value);
  }
  // asserts objective > old_value (used in optimization loop)
  Node increment;
  Kind incrementalOperator = kind::NULL_EXPR;
  if (objType == OptimizationObjective::MINIMIZE)
  {
    // if objective is MIN, then assert optimization_target <
    // current_model_value
    incrementalOperator = kind::LT;
  }
  else if (objType == OptimizationObjective::MAXIMIZE)
  {
    // if objective is MAX, then assert optimization_target >
    // current_model_value
    incrementalOperator = kind::GT;
  }
  // Workhorse of linear search:
  // This loop will keep incrmenting/decrementing the objective until unsat
  // When unsat is hit,
  // the optimized value is the model value just before the unsat call
  while (intermediateSatResult.isSat() == Result::SAT)
  {
    value = optChecker->getValue(target);
    Assert(!value.isNull());
    increment = nm->mkNode(incrementalOperator, target, value);
    optChecker->assertFormula(increment);
    intermediateSatResult = optChecker->checkSat();
  }
  return OptimizationResult(OptimizationResult::OPTIMAL, value);
}

OptimizationResult OMTOptimizerInteger::minimize(
    SmtEngine* parentSMTSolver, TNode target)
{
  return this->optimize(
      parentSMTSolver, target, OptimizationObjective::MINIMIZE);
}
OptimizationResult OMTOptimizerInteger::maximize(
    SmtEngine* parentSMTSolver, TNode target)
{
  return this->optimize(
      parentSMTSolver, target, OptimizationObjective::MAXIMIZE);
}

}  // namespace cvc5::omt
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback