summaryrefslogtreecommitdiff
path: root/src/theory/arith/dio_solver.cpp
blob: 151859f21b16e88bc482ba84f60f2f37f1532bf8 (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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*********************                                                        */
/*! \file dio_solver.cpp
 ** \verbatim
 ** Original author: mdeters
 ** Major contributors: none
 ** Minor contributors (to current version): none
 ** This file is part of the CVC4 prototype.
 ** Copyright (c) 2009, 2010, 2011  The Analysis of Computer Systems Group (ACSys)
 ** Courant Institute of Mathematical Sciences
 ** New York University
 ** See the file COPYING in the top-level source directory for licensing
 ** information.\endverbatim
 **
 ** \brief Diophantine equation solver
 **
 ** A Diophantine equation solver for the theory of arithmetic.
 **/

#include "theory/arith/dio_solver.h"

#include <iostream>

using namespace std;

namespace CVC4 {
namespace theory {
namespace arith {

/*
static void printEquation(vector<Rational>& coeffs,
                          vector<ArithVar>& variables,
                          ostream& out) {
  Assert(coeffs.size() == variables.size());
  vector<Rational>::const_iterator i = coeffs.begin();
  vector<ArithVar>::const_iterator j = variables.begin();
  while(i != coeffs.end()) {
    out << *i << "*" << *j;
    ++i;
    ++j;
    if(i != coeffs.end()) {
      out << " + ";
    }
  }
  out << " = 0";
}
*/

bool DioSolver::solve() {
  Trace("integers") << "DioSolver::solve()" << endl;
  if(Debug.isOn("integers")) {
    ScopedDebug dtab("tableau");
    d_tableau.printTableau();
  }
  for(ArithVarSet::const_iterator i = d_tableau.beginBasic();
      i != d_tableau.endBasic();
      ++i) {
    Debug("integers") << "going through row " << *i << endl;

    Integer m = 1;
    for(Tableau::RowIterator j = d_tableau.rowIterator(*i); !j.atEnd(); ++j) {
      Debug("integers") << "  column " << (*j).getCoefficient() << " * " << (*j).getColVar() << endl;
      m *= (*j).getCoefficient().getDenominator();
    }
    Assert(m >= 1);
    Debug("integers") << "final multiplier is " << m << endl;

    Integer gcd = 0;
    Rational c = 0;
    Debug("integers") << "going throw row " << *i << " to find gcd" << endl;
    for(Tableau::RowIterator j = d_tableau.rowIterator(*i); !j.atEnd(); ++j) {
      Rational r = (*j).getCoefficient();
      ArithVar v = (*j).getColVar();
      r *= m;
      Debug("integers") << "  column " << r << " * " << v << endl;
      Assert(r.getDenominator() == 1);
      bool foundConstant = false;
      // The tableau doesn't store constants.  Constants int he input
      // are mapped to slack variables that are constrained with
      // bounds in the partial model.  So we detect and accumulate all
      // variables whose upper bound equals their lower bound, which
      // catches these input constants as well as any (contextually)
      // eliminated variables.
      if(d_partialModel.hasUpperBound(v) && d_partialModel.hasLowerBound(v)) {
        DeltaRational b = d_partialModel.getLowerBound(v);
        if(b.getInfinitesimalPart() == 0 && b == d_partialModel.getUpperBound(v)) {
          r *= b.getNoninfinitesimalPart();
          Debug("integers") << "    var " << v << " == [" << b << "], so found a constant part " << r << endl;
          c += r;
          foundConstant = true;
        }
      }
      if(!foundConstant) {
        // calculate gcd of all (NON-constant) coefficients
        gcd = (gcd == 0) ? r.getNumerator().abs() : gcd.gcd(r.getNumerator());
        Debug("integers") << "    gcd now " << gcd << endl;
      }
    }
    Debug("integers") << "addEquation: gcd is " << gcd << ", c is " << c << endl;
    // The gcd must divide c for this equation to be satisfiable.
    // If c is not an integer, there's no way it can.
    if(c.getDenominator() == 1 && gcd == gcd.gcd(c.getNumerator())) {
      Trace("integers") << "addEquation: this eqn is fine" << endl;
    } else {
      Trace("integers") << "addEquation: eqn not satisfiable, returning false" << endl;
      return false;
    }
  }

  return true;
}

void DioSolver::getSolution() {
  Unimplemented();
}

}/* CVC4::theory::arith namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback