1 
2 /*
3  * File Constraint.hpp.
4  *
5  * This file is part of the source code of the software program
6  * Vampire. It is protected by applicable
7  * copyright laws.
8  *
9  * This source code is distributed under the licence found here
10  * https://vprover.github.io/license.html
11  * and in the source directory
12  *
13  * In summary, you are allowed to use Vampire for non-commercial
14  * purposes but not allowed to distribute, modify, copy, create derivatives,
15  * or use in competitions.
16  * For other uses of Vampire please contact developers for a different
17  * licence, which we will make an effort to provide.
18  */
19 /**
20  * @file Kernel/Constraint.hpp
21  * Defines class Constraint.
22  */
23 
24 #ifndef __Constraint__
25 #define __Constraint__
26 #if GNUMP
27 
28 #include "Forwards.hpp"
29 
30 #include "Lib/Allocator.hpp"
31 #include "Lib/DArray.hpp"
32 
33 #include "Number.hpp"
34 
35 namespace Kernel {
36 
37 enum ConstraintType {
38   CT_GR,
39   CT_GREQ,
40   CT_EQ
41 };
42 
43 /**
44  * Constraint object
45  *
46  * Object represents a constraint
47  *
48  * c0*x0 + ... + cN*xN # C
49  *
50  * where c0,x0,...cN,xN come from the @c _coeffs array, C is equal to @c _constVat
51  * and # is either >, >= or =, depending on @c _type.
52  *
53  * The coefficients are sorted in ascending order by variable number.
54  */
55 class Constraint {
56 public:
57 
58   struct Coeff {
CoeffKernel::Constraint::Coeff59     Coeff() {}
CoeffKernel::Constraint::Coeff60     Coeff(Var var, const CoeffNumber& value) : var(var), value(value) {}
61 
isPositiveKernel::Constraint::Coeff62     bool isPositive() const { return value.isPositiveAssumingNonzero(); }
isNegativeKernel::Constraint::Coeff63     bool isNegative() const { return value.isNegativeAssumingNonzero(); }
64 
operator ==Kernel::Constraint::Coeff65     bool operator==(const Coeff& o) const
66     { return var==o.var && value==o.value; }
operator !=Kernel::Constraint::Coeff67     bool operator!=(const Coeff& o) const
68     { return !(*this==o); }
69 
70     static unsigned hash(const Coeff& c);
71 
72     Var var;
73     CoeffNumber value;
74   };
75   typedef DArray<Coeff> CoeffArray;
76   typedef DArray<Coeff>::Iterator CoeffIterator;
77 
freeCoeff() const78   const CoeffNumber& freeCoeff() const { return _freeCoeff; }
type() const79   ConstraintType type() const { return _type; }
setType(ConstraintType t)80   void setType(ConstraintType t) { _type = t; }
81 
82   /**
83    * Return true if constraint was generated as a collapsing constraint.
84    *
85    * Input constraints can too appear as collapsing constraints, but
86    * for those the mark is not set.
87    */
collapsing() const88   bool collapsing() const { return _collapsing; }
markCollapsing()89   void markCollapsing() { ASS(!_collapsing); _collapsing = true; }
90 
coeffCnt() const91   size_t coeffCnt() const { return _coeffs.size(); }
92   CoeffIterator coeffs() const;
coeffArray() const93   const CoeffArray& coeffArray() const { return _coeffs; }
operator [](unsigned i) const94   const Coeff& operator[](unsigned i) const { return _coeffs[i]; }
95   int getVarIdx(Var v) const;
96   bool hasVar(Var v) const;
97   const Coeff& getCoeff(Var v) const;
98 
99   void multiplyCoeffs(CoeffNumber num);
100   void reduce(bool allowDecimals=true);
101 
isEquality() const102   bool isEquality() const { return type()==CT_EQ; }
103 
isTautology() const104   bool isTautology() const {
105     ASS(!isEquality());
106     return coeffCnt()==0
107 	&& (freeCoeff().isNegative() || (freeCoeff().isZero() && type()==CT_GREQ));
108   }
109 
isRefutation() const110   bool isRefutation() const {
111     ASS(!isEquality());
112     return coeffCnt()==0
113 	&& (freeCoeff().isPositive() || (freeCoeff().isZero() && type()==CT_GR));
114   }
115 
116   vstring toString() const;
117 
incRefCnt()118   void incRefCnt() { _refCnt++; }
decRefCnt()119   void decRefCnt() {
120     _refCnt--;
121     if(_refCnt==0) {
122       delete this;
123     }
124   }
125 
126   bool operator==(const Constraint& o) const;
operator !=(const Constraint & o) const127   bool operator!=(const Constraint& o) const
128   { return !(*this==o); }
129 private:
130   /**
131    * Comparator that allows to order coeffitients by their variable
132    * number (in ascending number)
133    */
134   struct CoeffComparator {
compareKernel::Constraint::CoeffComparator135     Comparison compare(Coeff& c1, Coeff& c2) {
136       return DefaultComparatorTKV::compare(c1.var, c2.var);
137     }
138   };
139 public:
140 
141   /**
142    * Create a constraint of type @c t, with coefficients from @c coeffIterator and with
143    * the constant value @c constVal. Each variable can appear only once among the
144    * coefficients. Coefficients must be non-zero.
145    */
146   template<class Iter>
fromIterator(ConstraintType t,Iter coeffIterator,const CoeffNumber & freeCoeff)147   static Constraint* fromIterator(ConstraintType t, Iter coeffIterator, const CoeffNumber& freeCoeff)
148   {
149     CALL("Constraint::fromIterator");
150 
151     Constraint* res = new Constraint();
152     res->_coeffs.initFromIterator(coeffIterator);
153     res->_freeCoeff = freeCoeff;
154     res->_type = t;
155 
156     res->_coeffs.sort(CoeffComparator());
157 
158 #if VDEBUG
159     for(size_t i=0; i<res->_coeffs.size(); i++) {
160       if(i>0) {
161           ASS_G(res->_coeffs[i].var,res->_coeffs[i-1].var);
162       }
163       ASS_REP2(!res->_coeffs[i].value.isZero(), res->toString(), i);
164     }
165 #endif
166 
167     return res;
168   }
169 
170   /**
171    * Create a constraint of type @c t, with coeffitients from @c coeffIterator and with
172    * the constant value @c constVal. Variables are allowed to appear multiple times among
173    * the coeffitients.
174    */
175   template<class Iter>
fromBagIterator(ConstraintType t,Iter coeffIterator,const CoeffNumber & freeCoeff)176   static Constraint* fromBagIterator(ConstraintType t, Iter coeffIterator, const CoeffNumber& freeCoeff)
177   {
178     CALL("Constraint::fromBagIterator");
179 
180     static CoeffArray bag;
181     bag.initFromIterator(coeffIterator);
182     bag.sort(CoeffComparator());
183 
184     unsigned bagSize = bag.size();
185     unsigned rIdx = 1;
186     unsigned wIdx = 0;
187     while(rIdx<bagSize) {
188       ASS_L(wIdx, rIdx);
189       if(bag[wIdx].var==bag[rIdx].var) {
190 	bag[wIdx].value+=bag[rIdx].value;
191       }
192       else {
193 	ASS_L(bag[wIdx].var,bag[rIdx].var);
194 	if(!bag[wIdx].value.isZero()) {
195 	  wIdx++;
196 	}
197 	if(wIdx!=rIdx) {
198 	  bag[wIdx]=bag[rIdx];
199 	}
200       }
201       rIdx++;
202     }
203     if(bag[wIdx].value.isZero()) {
204       bag.shrink(wIdx);
205     }
206     else {
207       bag.shrink(wIdx+1);
208     }
209     return fromSortedIterator(t, CoeffArray::Iterator(bag), freeCoeff);
210   }
211 
212   /**
213    * Create a constraint of type @c t, with coeffitients from @c coeffIterator and with
214    * the constant value @c constVal. The coeffitients in @c coeffIterator must be in
215    * ascending order. Each variable can appear only once among the coeffitients.
216    * Coeffitients must be non-zero.
217    */
218   template<class Iter>
fromSortedIterator(ConstraintType t,Iter coeffIterator,const CoeffNumber & freeCoeff)219   static Constraint* fromSortedIterator(ConstraintType t, Iter coeffIterator, const CoeffNumber& freeCoeff)
220   {
221     CALL("Constraint::fromSortedIterator");
222 
223     Constraint* res = new Constraint();
224     res->_coeffs.initFromIterator(coeffIterator);
225     res->_freeCoeff = freeCoeff;
226     res->_type = t;
227 
228 #if VDEBUG
229     for(size_t i=0; i<res->_coeffs.size(); i++) {
230       if(i>0) {
231 	ASS_G(res->_coeffs[i].var, res->_coeffs[i-1].var);
232       }
233       ASS_REP2(!res->_coeffs[i].value.isZero(), res->toString(), i);
234     }
235 #endif
236 
237     return res;
238   }
239 
240   static Constraint* resolve(Var resolvedVar, Constraint& c1, Constraint& c2,
241       bool allowDecimalCoeffitiets=true);
242   static Constraint* clone(Constraint& c);
243 
244   CLASS_NAME("Constraint");
245   USE_ALLOCATOR(Constraint);
246 private:
Constraint()247   Constraint() : _collapsing(false), _refCnt(0) {}
248 
249   /** Coeffitients with variables in ascending order */
250   CoeffArray _coeffs;
251   CoeffNumber _freeCoeff;
252   ConstraintType _type;
253   /**
254    * @see collapsing()
255    */
256   bool _collapsing;
257   unsigned _refCnt;
258 };
259 
260 }
261 #endif //GNUMP
262 #endif // __Constraint__
263