summaryrefslogtreecommitdiff
path: root/src/omt/integer_optimizer.cpp
blob: 379b0cd43e5657d8fa5861d65eabd4451bff0587 (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
/******************************************************************************
 * Top contributors (to current version):
 *   Michael Chang, Yancheng Ou
 *
 * 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* optChecker,
                                                 TNode target,
                                                 bool isMinimize)
{
  // linear search for integer goal
  // the smt engine to which we send intermediate queries
  // for the linear search.
  NodeManager* nm = optChecker->getNodeManager();
  optChecker->push();
  Result intermediateSatResult = optChecker->checkSat();
  // Model-value of objective (used in optimization loop)
  Node value;
  if (intermediateSatResult.isUnknown()
      || intermediateSatResult.isSat() == Result::UNSAT)
  {
    return OptimizationResult(intermediateSatResult, value);
  }
  // node storing target > old_value (used in optimization loop)
  Node increment;
  Kind incrementalOperator = kind::NULL_EXPR;
  if (isMinimize)
  {
    // if objective is minimize,
    // then assert optimization_target < current_model_value
    incrementalOperator = kind::LT;
  }
  else
  {
    // if objective is maximize,
    // then assert optimization_target > current_model_value
    incrementalOperator = kind::GT;
  }
  Result lastSatResult = intermediateSatResult;
  // 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)
  {
    lastSatResult = intermediateSatResult;
    value = optChecker->getValue(target);
    Assert(!value.isNull());
    increment = nm->mkNode(incrementalOperator, target, value);
    optChecker->assertFormula(increment);
    intermediateSatResult = optChecker->checkSat();
  }
  optChecker->pop();
  return OptimizationResult(lastSatResult, value);
}

OptimizationResult OMTOptimizerInteger::minimize(SmtEngine* optChecker,
                                                 TNode target)
{
  return this->optimize(optChecker, target, true);
}
OptimizationResult OMTOptimizerInteger::maximize(SmtEngine* optChecker,
                                                 TNode target)
{
  return this->optimize(optChecker, target, false);
}

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