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