GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/attempt_solution_simplex.cpp Lines: 12 77 15.6 %
Date: 2021-09-15 Branches: 10 286 3.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Aina Niemetz, Mathias Preiner
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * [[ Add one-line brief description here ]]
14
 *
15
 * [[ Add lengthier description here ]]
16
 * \todo document this file
17
 */
18
#include "theory/arith/attempt_solution_simplex.h"
19
20
#include "base/output.h"
21
#include "options/arith_options.h"
22
#include "smt/smt_statistics_registry.h"
23
#include "theory/arith/constraint.h"
24
#include "theory/arith/error_set.h"
25
#include "theory/arith/linear_equality.h"
26
#include "theory/arith/tableau.h"
27
28
using namespace std;
29
30
namespace cvc5 {
31
namespace theory {
32
namespace arith {
33
34
9942
AttemptSolutionSDP::AttemptSolutionSDP(LinearEqualityModule& linEq, ErrorSet& errors, RaiseConflict conflictChannel, TempVarMalloc tvmalloc)
35
  : SimplexDecisionProcedure(linEq, errors, conflictChannel, tvmalloc)
36
9942
  , d_statistics()
37
9942
{ }
38
39
9942
AttemptSolutionSDP::Statistics::Statistics()
40
9942
    : d_searchTime(smtStatisticsRegistry().registerTimer(
41
19884
        "theory::arith::attempt::searchTime")),
42
9942
      d_queueTime(smtStatisticsRegistry().registerTimer(
43
19884
          "theory::arith::attempt::queueTime")),
44
9942
      d_conflicts(smtStatisticsRegistry().registerInt(
45
29826
          "theory::arith::attempt::conflicts"))
46
{
47
9942
}
48
49
bool AttemptSolutionSDP::matchesNewValue(const DenseMap<DeltaRational>& nv, ArithVar v) const{
50
  return nv[v] == d_variables.getAssignment(v);
51
}
52
53
Result::Sat AttemptSolutionSDP::attempt(const ApproximateSimplex::Solution& sol){
54
  const DenseSet& newBasis = sol.newBasis;
55
  const DenseMap<DeltaRational>& newValues = sol.newValues;
56
57
  DenseSet needsToBeAdded;
58
  for(DenseSet::const_iterator i = newBasis.begin(), i_end = newBasis.end(); i != i_end; ++i){
59
    ArithVar b = *i;
60
    if(!d_tableau.isBasic(b)){
61
      needsToBeAdded.add(b);
62
    }
63
  }
64
  DenseMap<DeltaRational>::const_iterator nvi = newValues.begin(), nvi_end = newValues.end();
65
  for(; nvi != nvi_end; ++nvi){
66
    ArithVar currentlyNb = *nvi;
67
    if(!d_tableau.isBasic(currentlyNb)){
68
      if(!matchesNewValue(newValues, currentlyNb)){
69
        const DeltaRational& newValue = newValues[currentlyNb];
70
        Trace("arith::updateMany")
71
          << "updateMany:" << currentlyNb << " "
72
          << d_variables.getAssignment(currentlyNb) << " to "<< newValue << endl;
73
        d_linEq.update(currentlyNb, newValue);
74
        Assert(d_variables.assignmentIsConsistent(currentlyNb));
75
      }
76
    }
77
  }
78
  d_errorSet.reduceToSignals();
79
  d_errorSet.setSelectionRule(options::ErrorSelectionRule::VAR_ORDER);
80
81
  static int instance = 0;
82
  ++instance;
83
84
  if(processSignals()){
85
    Debug("arith::findModel") << "attemptSolution("<< instance <<") early conflict" << endl;
86
    d_conflictVariables.purge();
87
    return Result::UNSAT;
88
  }else if(d_errorSet.errorEmpty()){
89
    Debug("arith::findModel") << "attemptSolution("<< instance <<") fixed itself" << endl;
90
    return Result::SAT;
91
  }
92
93
  while(!needsToBeAdded.empty() && !d_errorSet.errorEmpty()){
94
    ArithVar toRemove = ARITHVAR_SENTINEL;
95
    ArithVar toAdd = ARITHVAR_SENTINEL;
96
    DenseSet::const_iterator i = needsToBeAdded.begin(), i_end = needsToBeAdded.end();
97
    for(; toAdd == ARITHVAR_SENTINEL && i != i_end; ++i){
98
      ArithVar v = *i;
99
100
      Tableau::ColIterator colIter = d_tableau.colIterator(v);
101
      for(; !colIter.atEnd(); ++colIter){
102
        const Tableau::Entry& entry = *colIter;
103
        Assert(entry.getColVar() == v);
104
        ArithVar b = d_tableau.rowIndexToBasic(entry.getRowIndex());
105
        if(!newBasis.isMember(b)){
106
          toAdd = v;
107
108
          bool favorBOverToRemove =
109
            (toRemove == ARITHVAR_SENTINEL) ||
110
            (matchesNewValue(newValues, toRemove) && !matchesNewValue(newValues, b)) ||
111
            (d_tableau.basicRowLength(toRemove) > d_tableau.basicRowLength(b));
112
113
          if(favorBOverToRemove){
114
            toRemove = b;
115
          }
116
        }
117
      }
118
    }
119
    Assert(toRemove != ARITHVAR_SENTINEL);
120
    Assert(toAdd != ARITHVAR_SENTINEL);
121
122
    Trace("arith::forceNewBasis") << toRemove << " " << toAdd << endl;
123
    // CVC5Message() << toRemove << " " << toAdd << endl;
124
125
    d_linEq.pivotAndUpdate(toRemove, toAdd, newValues[toRemove]);
126
127
    Trace("arith::forceNewBasis") << needsToBeAdded.size() << "to go" << endl;
128
    // CVC5Message() << needsToBeAdded.size() << "to go" << endl;
129
    needsToBeAdded.remove(toAdd);
130
131
    bool conflict = processSignals();
132
    if(conflict){
133
      d_errorSet.reduceToSignals();
134
      d_conflictVariables.purge();
135
136
      return Result::UNSAT;
137
    }
138
  }
139
  Assert(d_conflictVariables.empty());
140
141
  if(d_errorSet.errorEmpty()){
142
    return Result::SAT;
143
  }else{
144
    d_errorSet.reduceToSignals();
145
    return Result::SAT_UNKNOWN;
146
  }
147
}
148
149
}  // namespace arith
150
}  // namespace theory
151
29577
}  // namespace cvc5