1 
2 /*
3  * File Theory.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 Theory.hpp
21  * Defines class Theory.
22  */
23 
24 #ifndef __Theory__
25 #define __Theory__
26 
27 #include <math.h>
28 
29 #include "Forwards.hpp"
30 
31 #include "Lib/DHMap.hpp"
32 #include "Lib/Exception.hpp"
33 
34 #include "Shell/TermAlgebra.hpp"
35 
36 #include "Sorts.hpp"
37 #include "Term.hpp"
38 
39 namespace Kernel {
40 
41 /**
42  * Exception to be thrown when the requested operation cannot be performed,
43  * e.g. because of overflow of a native type.
44  */
45 class ArithmeticException : public ThrowableBase { };
46 
47 class MachineArithmeticException : public ArithmeticException {  };
48 class DivByZeroException  : public ArithmeticException {  };
49 
50 class IntegerConstantType
51 {
52 public:
getSort()53   static unsigned getSort() { return Sorts::SRT_INTEGER; }
54 
55   typedef int InnerType;
56 
IntegerConstantType()57   IntegerConstantType() {}
IntegerConstantType(InnerType v)58   constexpr IntegerConstantType(InnerType v) : _val(v) {}
59   explicit IntegerConstantType(const vstring& str);
60 
61   IntegerConstantType operator+(const IntegerConstantType& num) const;
62   IntegerConstantType operator-(const IntegerConstantType& num) const;
63   IntegerConstantType operator-() const;
64   IntegerConstantType operator*(const IntegerConstantType& num) const;
65 
66   // true if this divides num
67   bool divides(const IntegerConstantType& num) const ;
realDivide(const IntegerConstantType & num) const68   float realDivide(const IntegerConstantType& num) const {
69     if(num._val==0) throw DivByZeroException();
70     return ((float)_val)/num._val;
71   }
72   int intDivide(const IntegerConstantType& num) const ;
73   IntegerConstantType remainderE(const IntegerConstantType& num) const;
74   IntegerConstantType quotientE(const IntegerConstantType& num) const;
75   IntegerConstantType quotientT(const IntegerConstantType& num) const;
76   IntegerConstantType quotientF(const IntegerConstantType& num) const;
77 
78   bool operator==(const IntegerConstantType& num) const;
79   bool operator>(const IntegerConstantType& num) const;
80 
operator !=(const IntegerConstantType & num) const81   bool operator!=(const IntegerConstantType& num) const { return !((*this)==num); }
operator <(const IntegerConstantType & o) const82   bool operator<(const IntegerConstantType& o) const { return o>(*this); }
operator >=(const IntegerConstantType & o) const83   bool operator>=(const IntegerConstantType& o) const { return !(o>(*this)); }
operator <=(const IntegerConstantType & o) const84   bool operator<=(const IntegerConstantType& o) const { return !((*this)>o); }
85 
toInner() const86   InnerType toInner() const { return _val; }
87 
isZero()88   bool isZero(){ return _val==0; }
isNegative()89   bool isNegative(){ return _val<0; }
90 
91   static IntegerConstantType floor(RationalConstantType rat);
92   static IntegerConstantType ceiling(RationalConstantType rat);
93 
94   static Comparison comparePrecedence(IntegerConstantType n1, IntegerConstantType n2);
95 
96   vstring toString() const;
97 private:
98   InnerType _val;
99   IntegerConstantType operator/(const IntegerConstantType& num) const;
100   IntegerConstantType operator%(const IntegerConstantType& num) const;
101 };
102 
103 inline
operator <<(ostream & out,const IntegerConstantType & val)104 std::ostream& operator<< (ostream& out, const IntegerConstantType& val) {
105   return out << val.toInner();
106 }
107 
108 /**
109  * A class for representing rational numbers
110  *
111  * The class uses IntegerConstantType to store the numerator and denominator.
112  * This ensures that if there is an overflow in the operations, an exception
113  * will be raised by the IntegerConstantType methods.
114  */
115 struct RationalConstantType {
116   typedef IntegerConstantType InnerType;
117 
getSortKernel::RationalConstantType118   static unsigned getSort() { return Sorts::SRT_RATIONAL; }
119 
RationalConstantTypeKernel::RationalConstantType120   RationalConstantType() {}
121 
122   RationalConstantType(InnerType num, InnerType den);
123   RationalConstantType(const vstring& num, const vstring& den);
RationalConstantTypeKernel::RationalConstantType124   constexpr RationalConstantType(InnerType num) : _num(num), _den(1) {} //assuming den=1
125 
126   RationalConstantType operator+(const RationalConstantType& num) const;
127   RationalConstantType operator-(const RationalConstantType& num) const;
128   RationalConstantType operator-() const;
129   RationalConstantType operator*(const RationalConstantType& num) const;
130   RationalConstantType operator/(const RationalConstantType& num) const;
131 
floorKernel::RationalConstantType132   RationalConstantType floor() const {
133     return RationalConstantType(IntegerConstantType::floor(*this));
134   }
ceilingKernel::RationalConstantType135   RationalConstantType ceiling() const {
136     return RationalConstantType(IntegerConstantType::ceiling(*this));
137   }
truncateKernel::RationalConstantType138   RationalConstantType truncate() const {
139     return RationalConstantType(_num.quotientT(_den));
140   }
141 
142   bool isInt() const;
143 
144   bool operator==(const RationalConstantType& num) const;
145   bool operator>(const RationalConstantType& num) const;
146 
operator !=Kernel::RationalConstantType147   bool operator!=(const RationalConstantType& num) const { return !((*this)==num); }
operator <Kernel::RationalConstantType148   bool operator<(const RationalConstantType& o) const { return o>(*this); }
operator >=Kernel::RationalConstantType149   bool operator>=(const RationalConstantType& o) const { return !(o>(*this)); }
operator <=Kernel::RationalConstantType150   bool operator<=(const RationalConstantType& o) const { return !((*this)>o); }
151 
isZeroKernel::RationalConstantType152   bool isZero(){ return _num.toInner()==0; }
153   // relies on the fact that cannonize ensures that _den>=0
isNegativeKernel::RationalConstantType154   bool isNegative(){ ASS(_den>=0); return _num.toInner() < 0; }
155 
quotientEKernel::RationalConstantType156   RationalConstantType quotientE(const RationalConstantType& num) const {
157     if(_num.toInner()>0 && _den.toInner()>0){
158        return ((*this)/num).floor();
159     }
160     else return ((*this)/num).ceiling();
161   }
quotientTKernel::RationalConstantType162   RationalConstantType quotientT(const RationalConstantType& num) const {
163     return ((*this)/num).truncate();
164   }
quotientFKernel::RationalConstantType165   RationalConstantType quotientF(const RationalConstantType& num) const {
166     return ((*this)/num).floor();
167   }
168 
169 
170   vstring toString() const;
171 
numeratorKernel::RationalConstantType172   const InnerType& numerator() const { return _num; }
denominatorKernel::RationalConstantType173   const InnerType& denominator() const { return _den; }
174 
175   static Comparison comparePrecedence(RationalConstantType n1, RationalConstantType n2);
176 
177 protected:
178   void init(InnerType num, InnerType den);
179 
180 private:
181   void cannonize();
182 
183   InnerType _num;
184   InnerType _den;
185 };
186 
187 inline
operator <<(ostream & out,const RationalConstantType & val)188 std::ostream& operator<< (ostream& out, const RationalConstantType& val) {
189   return out << val.toString();
190 }
191 
192 
193 class RealConstantType : public RationalConstantType
194 {
195 public:
getSort()196   static unsigned getSort() { return Sorts::SRT_REAL; }
197 
RealConstantType()198   RealConstantType() {}
199   explicit RealConstantType(const vstring& number);
RealConstantType(const RationalConstantType & rat)200   explicit constexpr RealConstantType(const RationalConstantType& rat) : RationalConstantType(rat) {}
RealConstantType(typename IntegerConstantType::InnerType number)201   explicit constexpr RealConstantType(typename IntegerConstantType::InnerType number) : RealConstantType(RationalConstantType(number)) {}
202 
operator +(const RealConstantType & num) const203   RealConstantType operator+(const RealConstantType& num) const
204   { return RealConstantType(RationalConstantType::operator+(num)); }
operator -(const RealConstantType & num) const205   RealConstantType operator-(const RealConstantType& num) const
206   { return RealConstantType(RationalConstantType::operator-(num)); }
operator -() const207   RealConstantType operator-() const
208   { return RealConstantType(RationalConstantType::operator-()); }
operator *(const RealConstantType & num) const209   RealConstantType operator*(const RealConstantType& num) const
210   { return RealConstantType(RationalConstantType::operator*(num)); }
operator /(const RealConstantType & num) const211   RealConstantType operator/(const RealConstantType& num) const
212   { return RealConstantType(RationalConstantType::operator/(num)); }
213 
floor() const214   RealConstantType floor() const { return RealConstantType(RationalConstantType::floor()); }
truncate() const215   RealConstantType truncate() const { return RealConstantType(RationalConstantType::truncate()); }
ceiling() const216   RealConstantType ceiling() const { return RealConstantType(RationalConstantType::ceiling()); }
217 
quotientE(const RealConstantType & num) const218   RealConstantType quotientE(const RealConstantType& num) const
219     { return RealConstantType(RationalConstantType::quotientE(num)); }
quotientT(const RealConstantType & num) const220   RealConstantType quotientT(const RealConstantType& num) const
221     { return RealConstantType(RationalConstantType::quotientT(num)); }
quotientF(const RealConstantType & num) const222   RealConstantType quotientF(const RealConstantType& num) const
223     { return RealConstantType(RationalConstantType::quotientF(num)); }
224 
225   vstring toNiceString() const;
226 
227   static Comparison comparePrecedence(RealConstantType n1, RealConstantType n2);
228 private:
229   static bool parseDouble(const vstring& num, RationalConstantType& res);
230 
231 };
232 
233 inline
operator <<(ostream & out,const RealConstantType & val)234 std::ostream& operator<< (ostream& out, const RealConstantType& val) {
235   return out << val.toString();
236 }
237 
238 
239 /**
240  * A singleton class handling tasks related to theory symbols in Vampire
241  */
242 class Theory
243 {
244 public:
245   /**
246    * Interpreted symbols and predicates
247    *
248    * If interpreted_evaluation is enabled, predicates GREATER_EQUAL,
249    * LESS and LESS_EQUAL should not appear in the run of the
250    * SaturationAlgorithm (they'll be immediately simplified by the
251    * InterpretedEvaluation simplification).
252    */
253   enum Interpretation
254   {
255     //predicates
256     EQUAL,
257 
258     INT_IS_INT,
259     INT_IS_RAT,
260     INT_IS_REAL,
261     INT_GREATER,
262     INT_GREATER_EQUAL,
263     INT_LESS,
264     INT_LESS_EQUAL,
265     INT_DIVIDES,
266 
267     RAT_IS_INT,
268     RAT_IS_RAT,
269     RAT_IS_REAL,
270     RAT_GREATER,
271     RAT_GREATER_EQUAL,
272     RAT_LESS,
273     RAT_LESS_EQUAL,
274 
275     REAL_IS_INT,
276     REAL_IS_RAT,
277     REAL_IS_REAL,
278     REAL_GREATER,
279     REAL_GREATER_EQUAL,
280     REAL_LESS,
281     REAL_LESS_EQUAL,
282 
283     //numeric functions
284 
285     INT_SUCCESSOR,
286     INT_UNARY_MINUS,
287     INT_PLUS,  // sum in TPTP
288     INT_MINUS, // difference in TPTP
289     INT_MULTIPLY,
290     INT_QUOTIENT_E,
291     INT_QUOTIENT_T,
292     INT_QUOTIENT_F,
293     INT_REMAINDER_E,
294     INT_REMAINDER_T,
295     INT_REMAINDER_F,
296     INT_FLOOR,
297     INT_CEILING,
298     INT_TRUNCATE,
299     INT_ROUND,
300     INT_ABS,
301 
302     RAT_UNARY_MINUS,
303     RAT_PLUS, // sum in TPTP
304     RAT_MINUS,// difference in TPTP
305     RAT_MULTIPLY,
306     RAT_QUOTIENT,
307     RAT_QUOTIENT_E,
308     RAT_QUOTIENT_T,
309     RAT_QUOTIENT_F,
310     RAT_REMAINDER_E,
311     RAT_REMAINDER_T,
312     RAT_REMAINDER_F,
313     RAT_FLOOR,
314     RAT_CEILING,
315     RAT_TRUNCATE,
316     RAT_ROUND,
317 
318     REAL_UNARY_MINUS,
319     REAL_PLUS,  // plus in TPTP
320     REAL_MINUS, // difference in TPTP
321     REAL_MULTIPLY,
322     REAL_QUOTIENT,
323     REAL_QUOTIENT_E,
324     REAL_QUOTIENT_T,
325     REAL_QUOTIENT_F,
326     REAL_REMAINDER_E,
327     REAL_REMAINDER_T,
328     REAL_REMAINDER_F,
329     REAL_FLOOR,
330     REAL_CEILING,
331     REAL_TRUNCATE,
332     REAL_ROUND,
333 
334     //conversion functions
335     INT_TO_INT,
336     INT_TO_RAT,
337     INT_TO_REAL,
338     RAT_TO_INT,
339     RAT_TO_RAT,
340     RAT_TO_REAL,
341     REAL_TO_INT,
342     REAL_TO_RAT,
343     REAL_TO_REAL,
344 
345     // array functions
346     ARRAY_SELECT,
347     ARRAY_BOOL_SELECT,
348     ARRAY_STORE,
349 
350     INVALID_INTERPRETATION // LEAVE THIS AS THE LAST ELEMENT OF THE ENUM
351   };
352 
353   enum IndexedInterpretation {
354     FOR_NOW_EMPTY
355   };
356 
357   typedef std::pair<IndexedInterpretation, unsigned> ConcreteIndexedInterpretation;
358 
359   /**
360    * Interpretations represent the abstract concept of an interpreted operation vampire knows about.
361    *
362    * Some of them are polymorphic, such the ones for ARRAYs, and only become a concrete operation when supplied with OperatorType*.
363    * To identify these, MonomorphisedInterpretation (see below) can be used. However, notice that the appropriate Symbol always carries
364    * an Interpretation (if interpreted) and an OperatorType*.
365    *
366    * Other operations might be, in fact, indexed families of operations, and need an additional index (unsigned) to be specified.
367    * To keep the Symbol structure from growing for their sake, these IndexedInterpretations are instantiated to a concrete member of a family on demand
368    * and we keep track of this instantiation in _indexedInterpretations (see below). Members of _indexedInterpretations
369    * implicitly "inhabit" a range of values in Interpretation after INVALID_INTERPRETATION, so that again an
370    * Interpretation (this time >= INVALID_INTERPRETATION) and an OperatorType* are enough to identify a member of an indexed family.
371    */
372 
373   typedef std::pair<Interpretation, OperatorType*> MonomorphisedInterpretation;
374 
375 private:
376   DHMap<ConcreteIndexedInterpretation,Interpretation> _indexedInterpretations;
377 
378 public:
379 
numberOfFixedInterpretations()380   static unsigned numberOfFixedInterpretations() {
381     return INVALID_INTERPRETATION;
382   }
383 
interpretationFromIndexedInterpretation(IndexedInterpretation ii,unsigned index)384   Interpretation interpretationFromIndexedInterpretation(IndexedInterpretation ii, unsigned index)
385   {
386     CALL("inpretationFromIndexedInterpretation");
387 
388     ConcreteIndexedInterpretation cii = std::make_pair(ii,index);
389 
390     Interpretation res;
391     if (!_indexedInterpretations.find(cii, res)) {
392       res = static_cast<Interpretation>(numberOfFixedInterpretations() + _indexedInterpretations.size());
393       _indexedInterpretations.insert(cii, res);
394     }
395     return res;
396   }
397 
isPlus(Interpretation i)398   static bool isPlus(Interpretation i){
399     return i == INT_PLUS || i == RAT_PLUS || i == REAL_PLUS;
400   }
401 
402   static vstring getInterpretationName(Interpretation i);
403   static unsigned getArity(Interpretation i);
404   static bool isFunction(Interpretation i);
405   static bool isInequality(Interpretation i);
406   static OperatorType* getNonpolymorphicOperatorType(Interpretation i);
407 
408   static OperatorType* getArrayOperatorType(unsigned arraySort, Interpretation i);
409 
410   static bool hasSingleSort(Interpretation i);
411   static unsigned getOperationSort(Interpretation i);
412   static bool isConversionOperation(Interpretation i);
413   static bool isLinearOperation(Interpretation i);
414   static bool isNonLinearOperation(Interpretation i);
415   static bool isPartialFunction(Interpretation i);
416 
417   static bool isPolymorphic(Interpretation i);
418 
419   unsigned getArrayExtSkolemFunction(unsigned i);
420 
421   static Theory theory_obj;
422   static Theory* instance();
423 
424   void defineTupleTermAlgebra(unsigned arity, unsigned* sorts);
425 
426   /** Returns true if the argument is an interpreted constant
427    */
428   bool isInterpretedConstant(unsigned func);
429   bool isInterpretedConstant(Term* t);
430   bool isInterpretedConstant(TermList t);
431   /** Returns true if the argument is an interpreted number
432    */
433   bool isInterpretedNumber(Term* t);
434   bool isInterpretedNumber(TermList t);
435 
436   /** Returns false if pred is equality.  Returns true if the argument is any
437       other interpreted predicate.
438    */
439   bool isInterpretedPredicate(unsigned pred);
440   /** Returns true if the argument is any interpreted predicate (including
441       equality).
442    */
443   bool isInterpretedPredicate(Literal* lit);
444   bool isInterpretedPredicate(Literal* lit, Interpretation itp);
445 
446   bool isInterpretedFunction(unsigned func);
447   bool isInterpretedFunction(Term* t);
448   bool isInterpretedFunction(TermList t);
449   bool isInterpretedFunction(Term* t, Interpretation itp);
450   bool isInterpretedFunction(TermList t, Interpretation itp);
451 
452   bool isInterpretedPartialFunction(unsigned func);
453   bool isZero(TermList t);
454 
455   Interpretation interpretFunction(unsigned func);
456   Interpretation interpretFunction(Term* t);
457   Interpretation interpretFunction(TermList t);
458   Interpretation interpretPredicate(unsigned pred);
459   Interpretation interpretPredicate(Literal* t);
460 
461   void registerLaTeXPredName(unsigned func, bool polarity, vstring temp);
462   void registerLaTeXFuncName(unsigned func, vstring temp);
463   vstring tryGetInterpretedLaTeXName(unsigned func, bool pred,bool polarity=true);
464 
465 private:
466   // For recording the templates for predicate and function symbols
467   DHMap<unsigned,vstring> _predLaTeXnamesPos;
468   DHMap<unsigned,vstring> _predLaTeXnamesNeg;
469   DHMap<unsigned,vstring> _funcLaTeXnames;
470 
471 public:
472 
473   /**
474    * Try to interpret the term list as an integer constant. If it is an
475    * integer constant, return true and save the constant in @c res, otherwise
476    * return false.
477    */
tryInterpretConstant(TermList trm,IntegerConstantType & res)478   bool tryInterpretConstant(TermList trm, IntegerConstantType& res)
479   {
480     CALL("Theory::tryInterpretConstant(TermList,IntegerConstantType)");
481     if (!trm.isTerm()) {
482       return false;
483     }
484     return tryInterpretConstant(trm.term(),res);
485   }
486   bool tryInterpretConstant(const Term* t, IntegerConstantType& res);
487   /**
488    * Try to interpret the term list as an rational constant. If it is an
489    * rational constant, return true and save the constant in @c res, otherwise
490    * return false.
491    */
tryInterpretConstant(TermList trm,RationalConstantType & res)492   bool tryInterpretConstant(TermList trm, RationalConstantType& res)
493   {
494     CALL("Theory::tryInterpretConstant(TermList,RationalConstantType)");
495     if (!trm.isTerm()) {
496       return false;
497     }
498     return tryInterpretConstant(trm.term(),res);
499   }
500   bool tryInterpretConstant(const Term* t, RationalConstantType& res);
501   /**
502    * Try to interpret the term list as an real constant. If it is an
503    * real constant, return true and save the constant in @c res, otherwise
504    * return false.
505    */
tryInterpretConstant(TermList trm,RealConstantType & res)506   bool tryInterpretConstant(TermList trm, RealConstantType& res)
507   {
508     CALL("Theory::tryInterpretConstant(TermList,RealConstantType)");
509     if (!trm.isTerm()) {
510       return false;
511     }
512     return tryInterpretConstant(trm.term(),res);
513   }
514   bool tryInterpretConstant(const Term* t, RealConstantType& res);
515 
516   Term* representConstant(const IntegerConstantType& num);
517   Term* representConstant(const RationalConstantType& num);
518   Term* representConstant(const RealConstantType& num);
519 
520   Term* representIntegerConstant(vstring str);
521   Term* representRealConstant(vstring str);
522 private:
523   Theory();
524   static OperatorType* getConversionOperationType(Interpretation i);
525 
526   DHMap<unsigned,unsigned> _arraySkolemFunctions;
527 
528 public:
529   class Tuples {
530   public:
531     bool isFunctor(unsigned functor);
532     unsigned getFunctor(unsigned arity, unsigned sorts[]);
533     unsigned getFunctor(unsigned tupleSort);
534     unsigned getProjectionFunctor(unsigned proj, unsigned tupleSort);
535     bool findProjection(unsigned projFunctor, bool isPredicate, unsigned &proj);
536   };
537 
538   static Theory::Tuples tuples_obj;
539   static Theory::Tuples* tuples();
540 };
541 
542 typedef Theory::Interpretation Interpretation;
543 
544 /**
545  * Pointer to the singleton Theory instance
546  */
547 extern Theory* theory;
548 
549 }
550 
551 #endif // __Theory__
552