Change name of Python API's package from pycvc5 to cvc5. (#7953)
[cvc5.git] / src / api / python / cvc5.pxi
1 from collections import defaultdict
2 from fractions import Fraction
3 from functools import wraps
4 import sys
5
6 from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t
7 from libc.stddef cimport wchar_t
8
9 from libcpp.pair cimport pair
10 from libcpp.set cimport set as c_set
11 from libcpp.string cimport string
12 from libcpp.vector cimport vector
13
14 from cvc5 cimport cout
15 from cvc5 cimport Datatype as c_Datatype
16 from cvc5 cimport DatatypeConstructor as c_DatatypeConstructor
17 from cvc5 cimport DatatypeConstructorDecl as c_DatatypeConstructorDecl
18 from cvc5 cimport DatatypeDecl as c_DatatypeDecl
19 from cvc5 cimport DatatypeSelector as c_DatatypeSelector
20 from cvc5 cimport Result as c_Result
21 from cvc5 cimport RoundingMode as c_RoundingMode
22 from cvc5 cimport UnknownExplanation as c_UnknownExplanation
23 from cvc5 cimport Op as c_Op
24 from cvc5 cimport Solver as c_Solver
25 from cvc5 cimport Grammar as c_Grammar
26 from cvc5 cimport Sort as c_Sort
27 from cvc5 cimport ROUND_NEAREST_TIES_TO_EVEN, ROUND_TOWARD_POSITIVE
28 from cvc5 cimport ROUND_TOWARD_NEGATIVE, ROUND_TOWARD_ZERO
29 from cvc5 cimport ROUND_NEAREST_TIES_TO_AWAY
30 from cvc5 cimport REQUIRES_FULL_CHECK, INCOMPLETE, TIMEOUT
31 from cvc5 cimport RESOURCEOUT, MEMOUT, INTERRUPTED
32 from cvc5 cimport NO_STATUS, UNSUPPORTED, UNKNOWN_REASON
33 from cvc5 cimport OTHER
34 from cvc5 cimport Term as c_Term
35 from cvc5 cimport hash as c_hash
36 from cvc5 cimport wstring as c_wstring
37 from cvc5 cimport tuple as c_tuple
38 from cvc5 cimport get0, get1, get2
39 from cvc5kinds cimport Kind as c_Kind
40
41 cdef extern from "Python.h":
42 wchar_t* PyUnicode_AsWideCharString(object, Py_ssize_t *)
43 object PyUnicode_FromWideChar(const wchar_t*, Py_ssize_t)
44 void PyMem_Free(void*)
45
46 ################################## DECORATORS #################################
47 def expand_list_arg(num_req_args=0):
48 """
49 Creates a decorator that looks at index num_req_args of the args,
50 if it's a list, it expands it before calling the function.
51 """
52 def decorator(func):
53 @wraps(func)
54 def wrapper(owner, *args):
55 if len(args) == num_req_args + 1 and \
56 isinstance(args[num_req_args], list):
57 args = list(args[:num_req_args]) + args[num_req_args]
58 return func(owner, *args)
59 return wrapper
60 return decorator
61 ###############################################################################
62
63 # Style Guidelines
64 ### Using PEP-8 spacing recommendations
65 ### Limit linewidth to 79 characters
66 ### Break before binary operators
67 ### surround top level functions and classes with two spaces
68 ### separate methods by one space
69 ### use spaces in functions sparingly to separate logical blocks
70 ### can omit spaces between unrelated oneliners
71 ### always use c++ default arguments
72 #### only use default args of None at python level
73
74 # References and pointers
75 # The Solver object holds a pointer to a c_Solver.
76 # This is because the assignment operator is deleted in the C++ API for solvers.
77 # Cython has a limitation where you can't stack allocate objects
78 # that have constructors with arguments:
79 # https://groups.google.com/forum/#!topic/cython-users/fuKd-nQLpBs.
80 # To get around that you can either have a nullary constructor and assignment
81 # or, use a pointer (which is what we chose).
82 # An additional complication of this is that to free up resources, you must
83 # know when to delete the object.
84 # Python will not follow the same scoping rules as in C++, so it must be
85 # able to reference count. To do this correctly, the solver must be a
86 # reference in the Python class for any class that keeps a pointer to
87 # the solver in C++ (to ensure the solver is not deleted before something
88 # that depends on it).
89
90
91 ## Objects for hashing
92 cdef c_hash[c_Op] cophash = c_hash[c_Op]()
93 cdef c_hash[c_Sort] csorthash = c_hash[c_Sort]()
94 cdef c_hash[c_Term] ctermhash = c_hash[c_Term]()
95
96
97 cdef class Datatype:
98 """
99 A cvc5 datatype.
100 Wrapper class for :cpp:class:`cvc5::api::Datatype`.
101 """
102 cdef c_Datatype cd
103 cdef Solver solver
104 def __cinit__(self, Solver solver):
105 self.solver = solver
106
107 def __getitem__(self, index):
108 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
109 if isinstance(index, int) and index >= 0:
110 dc.cdc = self.cd[(<int?> index)]
111 elif isinstance(index, str):
112 dc.cdc = self.cd[(<const string &> index.encode())]
113 else:
114 raise ValueError("Expecting a non-negative integer or string")
115 return dc
116
117 def getConstructor(self, str name):
118 """
119 :param name: the name of the constructor.
120 :return: a constructor by name.
121 """
122 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
123 dc.cdc = self.cd.getConstructor(name.encode())
124 return dc
125
126 def getConstructorTerm(self, str name):
127 """
128 :param name: the name of the constructor.
129 :return: the term representing the datatype constructor with the given name (see :cpp:func:`Datatype::getConstructorTerm() <cvc5::api::Datatype::getConstructorTerm>`).
130 """
131 cdef Term term = Term(self.solver)
132 term.cterm = self.cd.getConstructorTerm(name.encode())
133 return term
134
135 def getSelector(self, str name):
136 """
137 :param name: the name of the selector..
138 :return: a selector by name.
139 """
140 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
141 ds.cds = self.cd.getSelector(name.encode())
142 return ds
143
144 def getName(self):
145 """
146 :return: the name of the datatype.
147 """
148 return self.cd.getName().decode()
149
150 def getNumConstructors(self):
151 """
152 :return: number of constructors in this datatype.
153 """
154 return self.cd.getNumConstructors()
155
156 def getParameters(self):
157 """
158 :return: the parameters of this datatype, if it is parametric. An
159 exception is thrown if this datatype is not parametric.
160 """
161 param_sorts = []
162 for s in self.cd.getParameters():
163 sort = Sort(self.solver)
164 sort.csort = s
165 param_sorts.append(sort)
166 return param_sorts
167
168 def isParametric(self):
169 """:return: True if this datatype is parametric."""
170 return self.cd.isParametric()
171
172 def isCodatatype(self):
173 """:return: True if this datatype corresponds to a co-datatype."""
174 return self.cd.isCodatatype()
175
176 def isTuple(self):
177 """:return: True if this datatype corresponds to a tuple."""
178 return self.cd.isTuple()
179
180 def isRecord(self):
181 """:return: True if this datatype corresponds to a record."""
182 return self.cd.isRecord()
183
184 def isFinite(self):
185 """:return: True if this datatype is finite."""
186 return self.cd.isFinite()
187
188 def isWellFounded(self):
189 """:return: True if this datatype is well-founded (see :cpp:func:`Datatype::isWellFounded() <cvc5::api::Datatype::isWellFounded>`)."""
190 return self.cd.isWellFounded()
191
192 def isNull(self):
193 """:return: True if this Datatype is a null object."""
194 return self.cd.isNull()
195
196 def __str__(self):
197 return self.cd.toString().decode()
198
199 def __repr__(self):
200 return self.cd.toString().decode()
201
202 def __iter__(self):
203 for ci in self.cd:
204 dc = DatatypeConstructor(self.solver)
205 dc.cdc = ci
206 yield dc
207
208
209 cdef class DatatypeConstructor:
210 """
211 A cvc5 datatype constructor.
212 Wrapper class for :cpp:class:`cvc5::api::DatatypeConstructor`.
213 """
214 cdef c_DatatypeConstructor cdc
215 cdef Solver solver
216 def __cinit__(self, Solver solver):
217 self.cdc = c_DatatypeConstructor()
218 self.solver = solver
219
220 def __getitem__(self, index):
221 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
222 if isinstance(index, int) and index >= 0:
223 ds.cds = self.cdc[(<int?> index)]
224 elif isinstance(index, str):
225 ds.cds = self.cdc[(<const string &> index.encode())]
226 else:
227 raise ValueError("Expecting a non-negative integer or string")
228 return ds
229
230 def getName(self):
231 """
232 :return: the name of the constructor.
233 """
234 return self.cdc.getName().decode()
235
236 def getConstructorTerm(self):
237 """
238 :return: the constructor operator as a term.
239 """
240 cdef Term term = Term(self.solver)
241 term.cterm = self.cdc.getConstructorTerm()
242 return term
243
244 def getInstantiatedConstructorTerm(self, Sort retSort):
245 """
246 Specialized method for parametric datatypes (see
247 :cpp:func:`DatatypeConstructor::getInstantiatedConstructorTerm()
248 <cvc5::api::DatatypeConstructor::getInstantiatedConstructorTerm>`).
249
250 :param retSort: the desired return sort of the constructor
251 :return: the constructor operator as a term.
252 """
253 cdef Term term = Term(self.solver)
254 term.cterm = self.cdc.getInstantiatedConstructorTerm(retSort.csort)
255 return term
256
257 def getTesterTerm(self):
258 """
259 :return: the tester operator that is related to this constructor, as a term.
260 """
261 cdef Term term = Term(self.solver)
262 term.cterm = self.cdc.getTesterTerm()
263 return term
264
265 def getNumSelectors(self):
266 """
267 :return: the number of selecters (so far) of this Datatype constructor.
268 """
269 return self.cdc.getNumSelectors()
270
271 def getSelector(self, str name):
272 """
273 :param name: the name of the datatype selector.
274 :return: the first datatype selector with the given name
275 """
276 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
277 ds.cds = self.cdc.getSelector(name.encode())
278 return ds
279
280 def getSelectorTerm(self, str name):
281 """
282 :param name: the name of the datatype selector.
283 :return: a term representing the firstdatatype selector with the given name.
284 """
285 cdef Term term = Term(self.solver)
286 term.cterm = self.cdc.getSelectorTerm(name.encode())
287 return term
288
289 def isNull(self):
290 """:return: True if this DatatypeConstructor is a null object."""
291 return self.cdc.isNull()
292
293 def __str__(self):
294 return self.cdc.toString().decode()
295
296 def __repr__(self):
297 return self.cdc.toString().decode()
298
299 def __iter__(self):
300 for ci in self.cdc:
301 ds = DatatypeSelector(self.solver)
302 ds.cds = ci
303 yield ds
304
305
306 cdef class DatatypeConstructorDecl:
307 """
308 A cvc5 datatype constructor declaration.
309 Wrapper class for :cpp:class:`cvc5::api::DatatypeConstructorDecl`.
310 """
311 cdef c_DatatypeConstructorDecl cddc
312 cdef Solver solver
313
314 def __cinit__(self, Solver solver):
315 self.solver = solver
316
317 def addSelector(self, str name, Sort sort):
318 """
319 Add datatype selector declaration.
320
321 :param name: the name of the datatype selector declaration to add.
322 :param sort: the codomain sort of the datatype selector declaration
323 to add.
324 """
325 self.cddc.addSelector(name.encode(), sort.csort)
326
327 def addSelectorSelf(self, str name):
328 """
329 Add datatype selector declaration whose codomain sort is the
330 datatype itself.
331
332 :param name: the name of the datatype selector declaration to add.
333 """
334 self.cddc.addSelectorSelf(name.encode())
335
336 def isNull(self):
337 """:return: True if this DatatypeConstructorDecl is a null object."""
338 return self.cddc.isNull()
339
340 def __str__(self):
341 return self.cddc.toString().decode()
342
343 def __repr__(self):
344 return self.cddc.toString().decode()
345
346
347 cdef class DatatypeDecl:
348 """
349 A cvc5 datatype declaration.
350 Wrapper class for :cpp:class:`cvc5::api::DatatypeDecl`.
351 """
352 cdef c_DatatypeDecl cdd
353 cdef Solver solver
354 def __cinit__(self, Solver solver):
355 self.solver = solver
356
357 def addConstructor(self, DatatypeConstructorDecl ctor):
358 """
359 Add a datatype constructor declaration.
360
361 :param ctor: the datatype constructor declaration to add.
362 """
363 self.cdd.addConstructor(ctor.cddc)
364
365 def getNumConstructors(self):
366 """
367 :return: number of constructors (so far) for this datatype declaration.
368 """
369 return self.cdd.getNumConstructors()
370
371 def isParametric(self):
372 """
373 :return: is this datatype declaration parametric?
374 """
375 return self.cdd.isParametric()
376
377 def getName(self):
378 """
379 :return: the name of this datatype declaration.
380 """
381 return self.cdd.getName().decode()
382
383 def isNull(self):
384 """:return: True if this DatatypeDecl is a null object."""
385 return self.cdd.isNull()
386
387 def __str__(self):
388 return self.cdd.toString().decode()
389
390 def __repr__(self):
391 return self.cdd.toString().decode()
392
393
394 cdef class DatatypeSelector:
395 """
396 A cvc5 datatype selector.
397 Wrapper class for :cpp:class:`cvc5::api::DatatypeSelector`.
398 """
399 cdef c_DatatypeSelector cds
400 cdef Solver solver
401 def __cinit__(self, Solver solver):
402 self.cds = c_DatatypeSelector()
403 self.solver = solver
404
405 def getName(self):
406 """
407 :return: the name of this datatype selector.
408 """
409 return self.cds.getName().decode()
410
411 def getSelectorTerm(self):
412 """
413 :return: the selector opeartor of this datatype selector as a term.
414 """
415 cdef Term term = Term(self.solver)
416 term.cterm = self.cds.getSelectorTerm()
417 return term
418
419 def getUpdaterTerm(self):
420 """
421 :return: the updater opeartor of this datatype selector as a term.
422 """
423 cdef Term term = Term(self.solver)
424 term.cterm = self.cds.getUpdaterTerm()
425 return term
426
427 def getCodomainSort(self):
428 """
429 :return: the codomain sort of this selector.
430 """
431 cdef Sort sort = Sort(self.solver)
432 sort.csort = self.cds.getCodomainSort()
433 return sort
434
435 def isNull(self):
436 """:return: True if this DatatypeSelector is a null object."""
437 return self.cds.isNull()
438
439 def __str__(self):
440 return self.cds.toString().decode()
441
442 def __repr__(self):
443 return self.cds.toString().decode()
444
445
446 cdef class Op:
447 """
448 A cvc5 operator.
449 An operator is a term that represents certain operators,
450 instantiated with its required parameters, e.g.,
451 a term of kind :cpp:enumerator:`BITVECTOR_EXTRACT`.
452 Wrapper class for :cpp:class:`cvc5::api::Op`.
453 """
454 cdef c_Op cop
455 cdef Solver solver
456 def __cinit__(self, Solver solver):
457 self.cop = c_Op()
458 self.solver = solver
459
460 def __eq__(self, Op other):
461 return self.cop == other.cop
462
463 def __ne__(self, Op other):
464 return self.cop != other.cop
465
466 def __str__(self):
467 return self.cop.toString().decode()
468
469 def __repr__(self):
470 return self.cop.toString().decode()
471
472 def __hash__(self):
473 return cophash(self.cop)
474
475 def getKind(self):
476 """
477 :return: the kind of this operator.
478 """
479 return Kind(<int> self.cop.getKind())
480
481 def isIndexed(self):
482 """
483 :return: True iff this operator is indexed.
484 """
485 return self.cop.isIndexed()
486
487 def isNull(self):
488 """
489 :return: True iff this operator is a null term.
490 """
491 return self.cop.isNull()
492
493 def getNumIndices(self):
494 """
495 :return: number of indices of this op.
496 """
497 return self.cop.getNumIndices()
498
499 def getIndices(self):
500 """
501 :return: the indices used to create this Op (see :cpp:func:`Op::getIndices() <cvc5::api::Op::getIndices>`).
502 """
503 indices = None
504 try:
505 indices = self.cop.getIndices[string]().decode()
506 except:
507 pass
508
509 try:
510 indices = self.cop.getIndices[uint32_t]()
511 except:
512 pass
513
514 try:
515 indices = self.cop.getIndices[pair[uint32_t, uint32_t]]()
516 except:
517 pass
518
519 if indices is None:
520 raise RuntimeError("Unable to retrieve indices from {}".format(self))
521
522 return indices
523
524 cdef class Grammar:
525 """
526 A Sygus Grammar.
527 Wrapper class for :cpp:class:`cvc5::api::Grammar`.
528 """
529 cdef c_Grammar cgrammar
530 cdef Solver solver
531 def __cinit__(self, Solver solver):
532 self.solver = solver
533 self.cgrammar = c_Grammar()
534
535 def addRule(self, Term ntSymbol, Term rule):
536 """
537 Add ``rule`` to the set of rules corresponding to ``ntSymbol``.
538
539 :param ntSymbol: the non-terminal to which the rule is added.
540 :param rule: the rule to add.
541 """
542 self.cgrammar.addRule(ntSymbol.cterm, rule.cterm)
543
544 def addAnyConstant(self, Term ntSymbol):
545 """
546 Allow ``ntSymbol`` to be an arbitrary constant.
547
548 :param ntSymbol: the non-terminal allowed to be constant.
549 """
550 self.cgrammar.addAnyConstant(ntSymbol.cterm)
551
552 def addAnyVariable(self, Term ntSymbol):
553 """
554 Allow ``ntSymbol`` to be any input variable to corresponding synth-fun/synth-inv with the same sort as ``ntSymbol``.
555
556 :param ntSymbol: the non-terminal allowed to be any input variable.
557 """
558 self.cgrammar.addAnyVariable(ntSymbol.cterm)
559
560 def addRules(self, Term ntSymbol, rules):
561 """
562 Add ``ntSymbol`` to the set of rules corresponding to ``ntSymbol``.
563
564 :param ntSymbol: the non-terminal to which the rules are added.
565 :param rules: the rules to add.
566 """
567 cdef vector[c_Term] crules
568 for r in rules:
569 crules.push_back((<Term?> r).cterm)
570 self.cgrammar.addRules(ntSymbol.cterm, crules)
571
572 cdef class Result:
573 """
574 Encapsulation of a three-valued solver result, with explanations.
575 Wrapper class for :cpp:class:`cvc5::api::Result`.
576 """
577 cdef c_Result cr
578 def __cinit__(self):
579 # gets populated by solver
580 self.cr = c_Result()
581
582 def isNull(self):
583 """
584 :return: True if Result is empty, i.e., a nullary Result, and not an actual result returned from a
585 :cpp:func:`Solver::checkSat() <cvc5::api::Solver::checkSat>` (and friends) query.
586 """
587 return self.cr.isNull()
588
589 def isSat(self):
590 """
591 :return: True if query was a satisfiable :cpp:func:`Solver::checkSat() <cvc5::api::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::api::Solver::checkSatAssuming>` query.
592 """
593 return self.cr.isSat()
594
595 def isUnsat(self):
596 """
597 :return: True if query was an usatisfiable :cpp:func:`Solver::checkSat() <cvc5::api::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::api::Solver::checkSatAssuming>` query.
598 """
599 return self.cr.isUnsat()
600
601 def isSatUnknown(self):
602 """
603 :return: True if query was a :cpp:func:`Solver::checkSat() <cvc5::api::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::api::Solver::checkSatAssuming>` query and cvc5 was not able to determine (un)satisfiability.
604 """
605 return self.cr.isSatUnknown()
606
607 def isEntailed(self):
608 """
609 :return: True if corresponding query was an entailed :cpp:func:`Solver::checkEntailed() <cvc5::api::Solver::checkEntailed>` query.
610 """
611 return self.cr.isEntailed()
612
613 def isNotEntailed(self):
614 """
615 :return: True if corresponding query was a :cpp:func:`Solver::checkEntailed() <cvc5::api::Solver::checkEntailed>` query that is not entailed.
616 """
617 return self.cr.isNotEntailed()
618
619 def isEntailmentUnknown(self):
620 """
621 :return: True if query was a :cpp:func:`Solver::checkEntailed() <cvc5::api::Solver::checkEntailed>` query query and cvc5 was not able to determine if it is entailed.
622 """
623 return self.cr.isEntailmentUnknown()
624
625 def getUnknownExplanation(self):
626 """
627 :return: an explanation for an unknown query result.
628 """
629 return UnknownExplanation(<int> self.cr.getUnknownExplanation())
630
631 def __eq__(self, Result other):
632 return self.cr == other.cr
633
634 def __ne__(self, Result other):
635 return self.cr != other.cr
636
637 def __str__(self):
638 return self.cr.toString().decode()
639
640 def __repr__(self):
641 return self.cr.toString().decode()
642
643
644 cdef class RoundingMode:
645 """
646 Rounding modes for floating-point numbers.
647
648 For many floating-point operations, infinitely precise results may not be
649 representable with the number of available bits. Thus, the results are
650 rounded in a certain way to one of the representable floating-point numbers.
651
652 These rounding modes directly follow the SMT-LIB theory for floating-point
653 arithmetic, which in turn is based on IEEE Standard 754 :cite:`IEEE754`.
654 The rounding modes are specified in Sections 4.3.1 and 4.3.2 of the IEEE
655 Standard 754.
656
657 Wrapper class for :cpp:enum:`cvc5::api::RoundingMode`.
658 """
659 cdef c_RoundingMode crm
660 cdef str name
661 def __cinit__(self, int rm):
662 # crm always assigned externally
663 self.crm = <c_RoundingMode> rm
664 self.name = __rounding_modes[rm]
665
666 def __eq__(self, RoundingMode other):
667 return (<int> self.crm) == (<int> other.crm)
668
669 def __ne__(self, RoundingMode other):
670 return not self.__eq__(other)
671
672 def __hash__(self):
673 return hash((<int> self.crm, self.name))
674
675 def __str__(self):
676 return self.name
677
678 def __repr__(self):
679 return self.name
680
681
682 cdef class UnknownExplanation:
683 """
684 Wrapper class for :cpp:enum:`cvc5::api::Result::UnknownExplanation`.
685 """
686 cdef c_UnknownExplanation cue
687 cdef str name
688 def __cinit__(self, int ue):
689 # crm always assigned externally
690 self.cue = <c_UnknownExplanation> ue
691 self.name = __unknown_explanations[ue]
692
693 def __eq__(self, UnknownExplanation other):
694 return (<int> self.cue) == (<int> other.cue)
695
696 def __ne__(self, UnknownExplanation other):
697 return not self.__eq__(other)
698
699 def __hash__(self):
700 return hash((<int> self.crm, self.name))
701
702 def __str__(self):
703 return self.name
704
705 def __repr__(self):
706 return self.name
707
708
709 cdef class Solver:
710 """Wrapper class for :cpp:class:`cvc5::api::Solver`."""
711 cdef c_Solver* csolver
712
713 def __cinit__(self):
714 self.csolver = new c_Solver()
715
716 def __dealloc__(self):
717 del self.csolver
718
719 def getBooleanSort(self):
720 """:return: sort Boolean
721 """
722 cdef Sort sort = Sort(self)
723 sort.csort = self.csolver.getBooleanSort()
724 return sort
725
726 def getIntegerSort(self):
727 """:return: sort Integer
728 """
729 cdef Sort sort = Sort(self)
730 sort.csort = self.csolver.getIntegerSort()
731 return sort
732
733 def getNullSort(self):
734 """:return: sort null
735 """
736 cdef Sort sort = Sort(self)
737 sort.csort = self.csolver.getNullSort()
738 return sort
739
740 def getRealSort(self):
741 """:return: sort Real
742 """
743 cdef Sort sort = Sort(self)
744 sort.csort = self.csolver.getRealSort()
745 return sort
746
747 def getRegExpSort(self):
748 """:return: sort of RegExp
749 """
750 cdef Sort sort = Sort(self)
751 sort.csort = self.csolver.getRegExpSort()
752 return sort
753
754 def getRoundingModeSort(self):
755 """:return: sort RoundingMode
756 """
757 cdef Sort sort = Sort(self)
758 sort.csort = self.csolver.getRoundingModeSort()
759 return sort
760
761 def getStringSort(self):
762 """:return: sort String
763 """
764 cdef Sort sort = Sort(self)
765 sort.csort = self.csolver.getStringSort()
766 return sort
767
768 def mkArraySort(self, Sort indexSort, Sort elemSort):
769 """Create an array sort.
770
771 :param indexSort: the array index sort
772 :param elemSort: the array element sort
773 :return: the array sort
774 """
775 cdef Sort sort = Sort(self)
776 sort.csort = self.csolver.mkArraySort(indexSort.csort, elemSort.csort)
777 return sort
778
779 def mkBitVectorSort(self, uint32_t size):
780 """Create a bit-vector sort.
781
782 :param size: the bit-width of the bit-vector sort
783 :return: the bit-vector sort
784 """
785 cdef Sort sort = Sort(self)
786 sort.csort = self.csolver.mkBitVectorSort(size)
787 return sort
788
789 def mkFloatingPointSort(self, uint32_t exp, uint32_t sig):
790 """Create a floating-point sort.
791
792 :param exp: the bit-width of the exponent of the floating-point sort.
793 :param sig: the bit-width of the significand of the floating-point sort.
794 """
795 cdef Sort sort = Sort(self)
796 sort.csort = self.csolver.mkFloatingPointSort(exp, sig)
797 return sort
798
799 def mkDatatypeSort(self, DatatypeDecl dtypedecl):
800 """Create a datatype sort.
801
802 :param dtypedecl: the datatype declaration from which the sort is created
803 :return: the datatype sort
804 """
805 cdef Sort sort = Sort(self)
806 sort.csort = self.csolver.mkDatatypeSort(dtypedecl.cdd)
807 return sort
808
809 def mkDatatypeSorts(self, list dtypedecls, unresolvedSorts = None):
810 """
811 Create a vector of datatype sorts using unresolved sorts. The names of
812 the datatype declarations in dtypedecls must be distinct.
813
814 This method is called when the DatatypeDecl objects dtypedecls have been
815 built using "unresolved" sorts.
816
817 We associate each sort in unresolvedSorts with exacly one datatype from
818 dtypedecls. In particular, it must have the same name as exactly one
819 datatype declaration in dtypedecls.
820
821 When constructing datatypes, unresolved sorts are replaced by the datatype
822 sort constructed for the datatype declaration it is associated with.
823
824 :param dtypedecls: the datatype declarations from which the sort is created
825 :param unresolvedSorts: the list of unresolved sorts
826 :return: the datatype sorts
827 """
828 if unresolvedSorts == None:
829 unresolvedSorts = set([])
830 else:
831 assert isinstance(unresolvedSorts, set)
832
833 sorts = []
834 cdef vector[c_DatatypeDecl] decls
835 for decl in dtypedecls:
836 decls.push_back((<DatatypeDecl?> decl).cdd)
837
838 cdef c_set[c_Sort] usorts
839 for usort in unresolvedSorts:
840 usorts.insert((<Sort?> usort).csort)
841
842 csorts = self.csolver.mkDatatypeSorts(
843 <const vector[c_DatatypeDecl]&> decls, <const c_set[c_Sort]&> usorts)
844 for csort in csorts:
845 sort = Sort(self)
846 sort.csort = csort
847 sorts.append(sort)
848
849 return sorts
850
851 def mkFunctionSort(self, sorts, Sort codomain):
852 """ Create function sort.
853
854 :param sorts: the sort of the function arguments
855 :param codomain: the sort of the function return value
856 :return: the function sort
857 """
858
859 cdef Sort sort = Sort(self)
860 # populate a vector with dereferenced c_Sorts
861 cdef vector[c_Sort] v
862
863 if isinstance(sorts, Sort):
864 sort.csort = self.csolver.mkFunctionSort((<Sort?> sorts).csort,
865 codomain.csort)
866 elif isinstance(sorts, list):
867 for s in sorts:
868 v.push_back((<Sort?>s).csort)
869
870 sort.csort = self.csolver.mkFunctionSort(<const vector[c_Sort]&> v,
871 codomain.csort)
872 return sort
873
874 def mkParamSort(self, symbolname):
875 """ Create a sort parameter.
876
877 :param symbol: the name of the sort
878 :return: the sort parameter
879 """
880 cdef Sort sort = Sort(self)
881 sort.csort = self.csolver.mkParamSort(symbolname.encode())
882 return sort
883
884 @expand_list_arg(num_req_args=0)
885 def mkPredicateSort(self, *sorts):
886 """Create a predicate sort.
887
888 :param sorts: the list of sorts of the predicate, as a list or as distinct arguments.
889 :return: the predicate sort
890 """
891 cdef Sort sort = Sort(self)
892 cdef vector[c_Sort] v
893 for s in sorts:
894 v.push_back((<Sort?> s).csort)
895 sort.csort = self.csolver.mkPredicateSort(<const vector[c_Sort]&> v)
896 return sort
897
898 @expand_list_arg(num_req_args=0)
899 def mkRecordSort(self, *fields):
900 """Create a record sort
901
902 :param fields: the list of fields of the record, as a list or as distinct arguments
903 :return: the record sort
904 """
905 cdef Sort sort = Sort(self)
906 cdef vector[pair[string, c_Sort]] v
907 cdef pair[string, c_Sort] p
908 for f in fields:
909 name, sortarg = f
910 name = name.encode()
911 p = pair[string, c_Sort](<string?> name, (<Sort?> sortarg).csort)
912 v.push_back(p)
913 sort.csort = self.csolver.mkRecordSort(
914 <const vector[pair[string, c_Sort]] &> v)
915 return sort
916
917 def mkSetSort(self, Sort elemSort):
918 """Create a set sort.
919
920 :param elemSort: the sort of the set elements
921 :return: the set sort
922 """
923 cdef Sort sort = Sort(self)
924 sort.csort = self.csolver.mkSetSort(elemSort.csort)
925 return sort
926
927 def mkBagSort(self, Sort elemSort):
928 """Create a bag sort.
929
930 :param elemSort: the sort of the bag elements
931 :return: the bag sort
932 """
933 cdef Sort sort = Sort(self)
934 sort.csort = self.csolver.mkBagSort(elemSort.csort)
935 return sort
936
937 def mkSequenceSort(self, Sort elemSort):
938 """Create a sequence sort.
939
940 :param elemSort: the sort of the sequence elements
941 :return: the sequence sort
942 """
943 cdef Sort sort = Sort(self)
944 sort.csort = self.csolver.mkSequenceSort(elemSort.csort)
945 return sort
946
947 def mkUninterpretedSort(self, str name):
948 """Create an uninterpreted sort.
949
950 :param symbol: the name of the sort
951 :return: the uninterpreted sort
952 """
953 cdef Sort sort = Sort(self)
954 sort.csort = self.csolver.mkUninterpretedSort(name.encode())
955 return sort
956
957 def mkUnresolvedSort(self, str name, size_t arity = 0):
958 """Create an unresolved sort.
959
960 This is for creating yet unresolved sort placeholders for mutually
961 recursive datatypes.
962
963 :param symbol: the name of the sort
964 :param arity: the number of sort parameters of the sort
965 :return: the unresolved sort
966 """
967 cdef Sort sort = Sort(self)
968 sort.csort = self.csolver.mkUnresolvedSort(name.encode(), arity)
969 return sort
970
971 def mkSortConstructorSort(self, str symbol, size_t arity):
972 """Create a sort constructor sort.
973
974 :param symbol: the symbol of the sort
975 :param arity: the arity of the sort
976 :return: the sort constructor sort
977 """
978 cdef Sort sort = Sort(self)
979 sort.csort =self.csolver.mkSortConstructorSort(symbol.encode(), arity)
980 return sort
981
982 @expand_list_arg(num_req_args=0)
983 def mkTupleSort(self, *sorts):
984 """Create a tuple sort.
985
986 :param sorts: of the elements of the tuple, as a list or as distinct arguments
987 :return: the tuple sort
988 """
989 cdef Sort sort = Sort(self)
990 cdef vector[c_Sort] v
991 for s in sorts:
992 v.push_back((<Sort?> s).csort)
993 sort.csort = self.csolver.mkTupleSort(v)
994 return sort
995
996 @expand_list_arg(num_req_args=1)
997 def mkTerm(self, kind_or_op, *args):
998 """
999 Supports the following arguments:
1000
1001 - ``Term mkTerm(Kind kind)``
1002 - ``Term mkTerm(Kind kind, Op child1, List[Term] children)``
1003 - ``Term mkTerm(Kind kind, List[Term] children)``
1004
1005 where ``List[Term]`` can also be comma-separated arguments
1006 """
1007 cdef Term term = Term(self)
1008 cdef vector[c_Term] v
1009
1010 op = kind_or_op
1011 if isinstance(kind_or_op, Kind):
1012 op = self.mkOp(kind_or_op)
1013
1014 if len(args) == 0:
1015 term.cterm = self.csolver.mkTerm((<Op?> op).cop)
1016 else:
1017 for a in args:
1018 v.push_back((<Term?> a).cterm)
1019 term.cterm = self.csolver.mkTerm((<Op?> op).cop, v)
1020 return term
1021
1022 def mkTuple(self, sorts, terms):
1023 """Create a tuple term. Terms are automatically converted if sorts are compatible.
1024
1025 :param sorts: The sorts of the elements in the tuple
1026 :param terms: The elements in the tuple
1027 :return: the tuple Term
1028 """
1029 cdef vector[c_Sort] csorts
1030 cdef vector[c_Term] cterms
1031
1032 for s in sorts:
1033 csorts.push_back((<Sort?> s).csort)
1034 for s in terms:
1035 cterms.push_back((<Term?> s).cterm)
1036 cdef Term result = Term(self)
1037 result.cterm = self.csolver.mkTuple(csorts, cterms)
1038 return result
1039
1040 @expand_list_arg(num_req_args=0)
1041 def mkOp(self, k, *args):
1042 """
1043 Supports the following uses:
1044
1045 - ``Op mkOp(Kind kind)``
1046 - ``Op mkOp(Kind kind, Kind k)``
1047 - ``Op mkOp(Kind kind, const string& arg)``
1048 - ``Op mkOp(Kind kind, uint32_t arg)``
1049 - ``Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1)``
1050 - ``Op mkOp(Kind kind, [uint32_t arg0, ...])`` (used for the TupleProject kind)
1051 """
1052 cdef Op op = Op(self)
1053 cdef vector[uint32_t] v
1054
1055 if len(args) == 0:
1056 op.cop = self.csolver.mkOp(<c_Kind> k.value)
1057 elif len(args) == 1:
1058 if isinstance(args[0], str):
1059 op.cop = self.csolver.mkOp(<c_Kind> k.value,
1060 <const string &>
1061 args[0].encode())
1062 elif isinstance(args[0], int):
1063 op.cop = self.csolver.mkOp(<c_Kind> k.value, <int?> args[0])
1064 elif isinstance(args[0], list):
1065 for a in args[0]:
1066 if a < 0 or a >= 2 ** 31:
1067 raise ValueError("Argument {} must fit in a uint32_t".format(a))
1068
1069 v.push_back((<uint32_t?> a))
1070 op.cop = self.csolver.mkOp(<c_Kind> k.value, <const vector[uint32_t]&> v)
1071 else:
1072 raise ValueError("Unsupported signature"
1073 " mkOp: {}".format(" X ".join([str(k), str(args[0])])))
1074 elif len(args) == 2:
1075 if isinstance(args[0], int) and isinstance(args[1], int):
1076 op.cop = self.csolver.mkOp(<c_Kind> k.value, <int> args[0], <int> args[1])
1077 else:
1078 raise ValueError("Unsupported signature"
1079 " mkOp: {}".format(" X ".join([k, args[0], args[1]])))
1080 return op
1081
1082 def mkTrue(self):
1083 """Create a Boolean true constant.
1084
1085 :return: the true constant
1086 """
1087 cdef Term term = Term(self)
1088 term.cterm = self.csolver.mkTrue()
1089 return term
1090
1091 def mkFalse(self):
1092 """Create a Boolean false constant.
1093
1094 :return: the false constant
1095 """
1096 cdef Term term = Term(self)
1097 term.cterm = self.csolver.mkFalse()
1098 return term
1099
1100 def mkBoolean(self, bint val):
1101 """Create a Boolean constant.
1102
1103 :return: the Boolean constant
1104 :param val: the value of the constant
1105 """
1106 cdef Term term = Term(self)
1107 term.cterm = self.csolver.mkBoolean(val)
1108 return term
1109
1110 def mkPi(self):
1111 """Create a constant representing the number Pi.
1112
1113 :return: a constant representing Pi
1114 """
1115 cdef Term term = Term(self)
1116 term.cterm = self.csolver.mkPi()
1117 return term
1118
1119 def mkInteger(self, val):
1120 """Create an integer constant.
1121
1122 :param val: representation of the constant: either a string or integer
1123 :return: a constant of sort Integer
1124 """
1125 cdef Term term = Term(self)
1126 if isinstance(val, str):
1127 term.cterm = self.csolver.mkInteger(<const string &> str(val).encode())
1128 else:
1129 assert(isinstance(val, int))
1130 term.cterm = self.csolver.mkInteger((<int?> val))
1131 return term
1132
1133 def mkReal(self, val, den=None):
1134 """Create a real constant.
1135
1136 :param val: the value of the term. Can be an integer, float, or string. It will be formatted as a string before the term is built.
1137 :param den: if not None, the value is `val`/`den`
1138 :return: a real term with literal value
1139
1140 Can be used in various forms:
1141
1142 - Given a string ``"N/D"`` constructs the corresponding rational.
1143 - Given a string ``"W.D"`` constructs the reduction of ``(W * P + D)/P``, where ``P`` is the appropriate power of 10.
1144 - Given a float ``f``, constructs the rational matching ``f``'s string representation. This means that ``mkReal(0.3)`` gives ``3/10`` and not the IEEE-754 approximation of ``3/10``.
1145 - Given a string ``"W"`` or an integer, constructs that integer.
1146 - Given two strings and/or integers ``N`` and ``D``, constructs ``N/D``.
1147 """
1148 cdef Term term = Term(self)
1149 if den is None:
1150 term.cterm = self.csolver.mkReal(str(val).encode())
1151 else:
1152 if not isinstance(val, int) or not isinstance(den, int):
1153 raise ValueError("Expecting integers when"
1154 " constructing a rational"
1155 " but got: {}".format((val, den)))
1156 term.cterm = self.csolver.mkReal("{}/{}".format(val, den).encode())
1157 return term
1158
1159 def mkRegexpAll(self):
1160 """Create a regular expression all (re.all) term.
1161
1162 :return: the all term
1163 """
1164 cdef Term term = Term(self)
1165 term.cterm = self.csolver.mkRegexpAll()
1166 return term
1167
1168 def mkRegexpAllchar(self):
1169 """Create a regular expression allchar (re.allchar) term.
1170
1171 :return: the allchar term
1172 """
1173 cdef Term term = Term(self)
1174 term.cterm = self.csolver.mkRegexpAllchar()
1175 return term
1176
1177 def mkRegexpNone(self):
1178 """Create a regular expression none (re.none) term.
1179
1180 :return: the none term
1181 """
1182 cdef Term term = Term(self)
1183 term.cterm = self.csolver.mkRegexpNone()
1184 return term
1185
1186 def mkEmptySet(self, Sort s):
1187 """Create a constant representing an empty set of the given sort.
1188
1189 :param sort: the sort of the set elements.
1190 :return: the empty set constant
1191 """
1192 cdef Term term = Term(self)
1193 term.cterm = self.csolver.mkEmptySet(s.csort)
1194 return term
1195
1196 def mkEmptyBag(self, Sort s):
1197 """Create a constant representing an empty bag of the given sort.
1198
1199 :param sort: the sort of the bag elements.
1200 :return: the empty bag constant
1201 """
1202 cdef Term term = Term(self)
1203 term.cterm = self.csolver.mkEmptyBag(s.csort)
1204 return term
1205
1206 def mkSepEmp(self):
1207 """Create a separation logic empty term.
1208
1209 :return: the separation logic empty term
1210 """
1211 cdef Term term = Term(self)
1212 term.cterm = self.csolver.mkSepEmp()
1213 return term
1214
1215 def mkSepNil(self, Sort sort):
1216 """Create a separation logic nil term.
1217
1218 :param sort: the sort of the nil term
1219 :return: the separation logic nil term
1220 """
1221 cdef Term term = Term(self)
1222 term.cterm = self.csolver.mkSepNil(sort.csort)
1223 return term
1224
1225 def mkString(self, str s, useEscSequences = None):
1226 """
1227 Create a String constant from a `str` which may contain SMT-LIB
1228 compatible escape sequences like ``\\u1234`` to encode unicode characters.
1229
1230 :param s: the string this constant represents
1231 :param useEscSequences: determines whether escape sequences in `s` should be converted to the corresponding unicode character
1232 :return: the String constant
1233 """
1234 cdef Term term = Term(self)
1235 cdef Py_ssize_t size
1236 cdef wchar_t* tmp = PyUnicode_AsWideCharString(s, &size)
1237 if isinstance(useEscSequences, bool):
1238 term.cterm = self.csolver.mkString(
1239 s.encode(), <bint> useEscSequences)
1240 else:
1241 term.cterm = self.csolver.mkString(c_wstring(tmp, size))
1242 PyMem_Free(tmp)
1243 return term
1244
1245 def mkEmptySequence(self, Sort sort):
1246 """Create an empty sequence of the given element sort.
1247
1248 :param sort: The element sort of the sequence.
1249 :return: the empty sequence with given element sort.
1250 """
1251 cdef Term term = Term(self)
1252 term.cterm = self.csolver.mkEmptySequence(sort.csort)
1253 return term
1254
1255 def mkUniverseSet(self, Sort sort):
1256 """Create a universe set of the given sort.
1257
1258 :param sort: the sort of the set elements
1259 :return: the universe set constant
1260 """
1261 cdef Term term = Term(self)
1262 term.cterm = self.csolver.mkUniverseSet(sort.csort)
1263 return term
1264
1265 @expand_list_arg(num_req_args=0)
1266 def mkBitVector(self, *args):
1267 """
1268 Supports the following arguments:
1269
1270 - ``Term mkBitVector(int size, int val=0)``
1271 - ``Term mkBitVector(int size, string val, int base)``
1272
1273 :return: a bit-vector literal term
1274 :param size: an integer size.
1275 :param val: an integer representating the value, in the first form. In the second form, a string representing the value.
1276 :param base: the base of the string representation (second form only)
1277 """
1278 cdef Term term = Term(self)
1279 if len(args) == 0:
1280 raise ValueError("Missing arguments to mkBitVector")
1281 size = args[0]
1282 if not isinstance(size, int):
1283 raise ValueError(
1284 "Invalid first argument to mkBitVector '{}', "
1285 "expected bit-vector size".format(size))
1286 if len(args) == 1:
1287 term.cterm = self.csolver.mkBitVector(<uint32_t> size)
1288 elif len(args) == 2:
1289 val = args[1]
1290 if not isinstance(val, int):
1291 raise ValueError(
1292 "Invalid second argument to mkBitVector '{}', "
1293 "expected integer value".format(size))
1294 term.cterm = self.csolver.mkBitVector(
1295 <uint32_t> size, <uint32_t> val)
1296 elif len(args) == 3:
1297 val = args[1]
1298 base = args[2]
1299 if not isinstance(val, str):
1300 raise ValueError(
1301 "Invalid second argument to mkBitVector '{}', "
1302 "expected value string".format(size))
1303 if not isinstance(base, int):
1304 raise ValueError(
1305 "Invalid third argument to mkBitVector '{}', "
1306 "expected base given as integer".format(size))
1307 term.cterm = self.csolver.mkBitVector(
1308 <uint32_t> size,
1309 <const string&> str(val).encode(),
1310 <uint32_t> base)
1311 else:
1312 raise ValueError("Unexpected inputs to mkBitVector")
1313 return term
1314
1315 def mkConstArray(self, Sort sort, Term val):
1316 """
1317 Create a constant array with the provided constant value stored at every
1318 index
1319
1320 :param sort: the sort of the constant array (must be an array sort)
1321 :param val: the constant value to store (must match the sort's element sort)
1322 :return: the constant array term
1323 """
1324 cdef Term term = Term(self)
1325 term.cterm = self.csolver.mkConstArray(sort.csort, val.cterm)
1326 return term
1327
1328 def mkFloatingPointPosInf(self, int exp, int sig):
1329 """Create a positive infinity floating-point constant.
1330
1331 :param exp: Number of bits in the exponent
1332 :param sig: Number of bits in the significand
1333 :return: the floating-point constant
1334 """
1335 cdef Term term = Term(self)
1336 term.cterm = self.csolver.mkFloatingPointPosInf(exp, sig)
1337 return term
1338
1339 def mkFloatingPointNegInf(self, int exp, int sig):
1340 """Create a negative infinity floating-point constant.
1341
1342 :param exp: Number of bits in the exponent
1343 :param sig: Number of bits in the significand
1344 :return: the floating-point constant
1345 """
1346 cdef Term term = Term(self)
1347 term.cterm = self.csolver.mkFloatingPointNegInf(exp, sig)
1348 return term
1349
1350 def mkFloatingPointNaN(self, int exp, int sig):
1351 """Create a not-a-number (NaN) floating-point constant.
1352
1353 :param exp: Number of bits in the exponent
1354 :param sig: Number of bits in the significand
1355 :return: the floating-point constant
1356 """
1357 cdef Term term = Term(self)
1358 term.cterm = self.csolver.mkFloatingPointNaN(exp, sig)
1359 return term
1360
1361 def mkFloatingPointPosZero(self, int exp, int sig):
1362 """Create a positive zero (+0.0) floating-point constant.
1363
1364 :param exp: Number of bits in the exponent
1365 :param sig: Number of bits in the significand
1366 :return: the floating-point constant
1367 """
1368 cdef Term term = Term(self)
1369 term.cterm = self.csolver.mkFloatingPointPosZero(exp, sig)
1370 return term
1371
1372 def mkFloatingPointNegZero(self, int exp, int sig):
1373 """Create a negative zero (+0.0) floating-point constant.
1374
1375 :param exp: Number of bits in the exponent
1376 :param sig: Number of bits in the significand
1377 :return: the floating-point constant
1378 """
1379 cdef Term term = Term(self)
1380 term.cterm = self.csolver.mkFloatingPointNegZero(exp, sig)
1381 return term
1382
1383 def mkRoundingMode(self, RoundingMode rm):
1384 """Create a roundingmode constant.
1385
1386 :param rm: the floating point rounding mode this constant represents
1387 """
1388 cdef Term term = Term(self)
1389 term.cterm = self.csolver.mkRoundingMode(<c_RoundingMode> rm.crm)
1390 return term
1391
1392 def mkFloatingPoint(self, int exp, int sig, Term val):
1393 """Create a floating-point constant.
1394
1395 :param exp: Size of the exponent
1396 :param sig: Size of the significand
1397 :param val: Value of the floating-point constant as a bit-vector term
1398 """
1399 cdef Term term = Term(self)
1400 term.cterm = self.csolver.mkFloatingPoint(exp, sig, val.cterm)
1401 return term
1402
1403 def mkCardinalityConstraint(self, Sort sort, int index):
1404 """Create cardinality constraint.
1405
1406 :param sort: Sort of the constraint
1407 :param index: The upper bound for the cardinality of the sort
1408 """
1409 cdef Term term = Term(self)
1410 term.cterm = self.csolver.mkCardinalityConstraint(sort.csort, index)
1411 return term
1412
1413 def mkConst(self, Sort sort, symbol=None):
1414 """
1415 Create (first-order) constant (0-arity function symbol).
1416
1417 SMT-LIB:
1418
1419 .. code-block:: smtlib
1420
1421 ( declare-const <symbol> <sort> )
1422 ( declare-fun <symbol> ( ) <sort> )
1423
1424 :param sort: the sort of the constant
1425 :param symbol: the name of the constant. If None, a default symbol is used.
1426 :return: the first-order constant
1427 """
1428 cdef Term term = Term(self)
1429 if symbol is None:
1430 term.cterm = self.csolver.mkConst(sort.csort)
1431 else:
1432 term.cterm = self.csolver.mkConst(sort.csort,
1433 (<str?> symbol).encode())
1434 return term
1435
1436 def mkVar(self, Sort sort, symbol=None):
1437 """
1438 Create a bound variable to be used in a binder (i.e. a quantifier, a
1439 lambda, or a witness binder).
1440
1441 :param sort: the sort of the variable
1442 :param symbol: the name of the variable
1443 :return: the variable
1444 """
1445 cdef Term term = Term(self)
1446 if symbol is None:
1447 term.cterm = self.csolver.mkVar(sort.csort)
1448 else:
1449 term.cterm = self.csolver.mkVar(sort.csort,
1450 (<str?> symbol).encode())
1451 return term
1452
1453 def mkDatatypeConstructorDecl(self, str name):
1454 """
1455 :return: a datatype constructor declaration
1456 :param name: the constructor's name
1457 """
1458 cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl(self)
1459 ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
1460 return ddc
1461
1462 def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
1463 """Create a datatype declaration.
1464
1465 :param name: the name of the datatype
1466 :param isCoDatatype: true if a codatatype is to be constructed
1467 :return: the DatatypeDecl
1468 """
1469 cdef DatatypeDecl dd = DatatypeDecl(self)
1470 cdef vector[c_Sort] v
1471
1472 # argument cases
1473 if sorts_or_bool is None and isCoDatatype is None:
1474 dd.cdd = self.csolver.mkDatatypeDecl(name.encode())
1475 elif sorts_or_bool is not None and isCoDatatype is None:
1476 if isinstance(sorts_or_bool, bool):
1477 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1478 <bint> sorts_or_bool)
1479 elif isinstance(sorts_or_bool, Sort):
1480 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1481 (<Sort> sorts_or_bool).csort)
1482 elif isinstance(sorts_or_bool, list):
1483 for s in sorts_or_bool:
1484 v.push_back((<Sort?> s).csort)
1485 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1486 <const vector[c_Sort]&> v)
1487 else:
1488 raise ValueError("Unhandled second argument type {}"
1489 .format(type(sorts_or_bool)))
1490 elif sorts_or_bool is not None and isCoDatatype is not None:
1491 if isinstance(sorts_or_bool, Sort):
1492 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1493 (<Sort> sorts_or_bool).csort,
1494 <bint> isCoDatatype)
1495 elif isinstance(sorts_or_bool, list):
1496 for s in sorts_or_bool:
1497 v.push_back((<Sort?> s).csort)
1498 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1499 <const vector[c_Sort]&> v,
1500 <bint> isCoDatatype)
1501 else:
1502 raise ValueError("Unhandled second argument type {}"
1503 .format(type(sorts_or_bool)))
1504 else:
1505 raise ValueError("Can't create DatatypeDecl with {}".format([type(a)
1506 for a in [name,
1507 sorts_or_bool,
1508 isCoDatatype]]))
1509
1510 return dd
1511
1512 def simplify(self, Term t):
1513 """
1514 Simplify a formula without doing "much" work. Does not involve the
1515 SAT Engine in the simplification, but uses the current definitions,
1516 assertions, and the current partial model, if one has been constructed.
1517 It also involves theory normalization.
1518
1519 :param t: the formula to simplify
1520 :return: the simplified formula
1521 """
1522 cdef Term term = Term(self)
1523 term.cterm = self.csolver.simplify(t.cterm)
1524 return term
1525
1526 def assertFormula(self, Term term):
1527 """ Assert a formula
1528
1529 SMT-LIB:
1530
1531 .. code-block:: smtlib
1532
1533 ( assert <term> )
1534
1535 :param term: the formula to assert
1536 """
1537 self.csolver.assertFormula(term.cterm)
1538
1539 def checkSat(self):
1540 """
1541 Check satisfiability.
1542
1543 SMT-LIB:
1544
1545 .. code-block:: smtlib
1546
1547 ( check-sat )
1548
1549 :return: the result of the satisfiability check.
1550 """
1551 cdef Result r = Result()
1552 r.cr = self.csolver.checkSat()
1553 return r
1554
1555 def mkSygusGrammar(self, boundVars, ntSymbols):
1556 """
1557 Create a SyGuS grammar. The first non-terminal is treated as the
1558 starting non-terminal, so the order of non-terminals matters.
1559
1560 :param boundVars: the parameters to corresponding synth-fun/synth-inv
1561 :param ntSymbols: the pre-declaration of the non-terminal symbols
1562 :return: the grammar
1563 """
1564 cdef Grammar grammar = Grammar(self)
1565 cdef vector[c_Term] bvc
1566 cdef vector[c_Term] ntc
1567 for bv in boundVars:
1568 bvc.push_back((<Term?> bv).cterm)
1569 for nt in ntSymbols:
1570 ntc.push_back((<Term?> nt).cterm)
1571 grammar.cgrammar = self.csolver.mkSygusGrammar(<const vector[c_Term]&> bvc, <const vector[c_Term]&> ntc)
1572 return grammar
1573
1574 def mkSygusVar(self, Sort sort, str symbol=""):
1575 """Append symbol to the current list of universal variables.
1576
1577 SyGuS v2:
1578
1579 .. code-block:: smtlib
1580
1581 ( declare-var <symbol> <sort> )
1582
1583 :param sort: the sort of the universal variable
1584 :param symbol: the name of the universal variable
1585 :return: the universal variable
1586 """
1587 cdef Term term = Term(self)
1588 term.cterm = self.csolver.mkSygusVar(sort.csort, symbol.encode())
1589 return term
1590
1591 def addSygusConstraint(self, Term t):
1592 """
1593 Add a formula to the set of SyGuS constraints.
1594
1595 SyGuS v2:
1596
1597 .. code-block:: smtlib
1598
1599 ( constraint <term> )
1600
1601 :param term: the formula to add as a constraint
1602 """
1603 self.csolver.addSygusConstraint(t.cterm)
1604
1605 def addSygusInvConstraint(self, Term inv_f, Term pre_f, Term trans_f, Term post_f):
1606 """
1607 Add a set of SyGuS constraints to the current state that correspond to an
1608 invariant synthesis problem.
1609
1610 SyGuS v2:
1611
1612 .. code-block:: smtlib
1613
1614 ( inv-constraint <inv> <pre> <trans> <post> )
1615
1616 :param inv: the function-to-synthesize
1617 :param pre: the pre-condition
1618 :param trans: the transition relation
1619 :param post: the post-condition
1620 """
1621 self.csolver.addSygusInvConstraint(inv_f.cterm, pre_f.cterm, trans_f.cterm, post_f.cterm)
1622
1623 def synthFun(self, str symbol, bound_vars, Sort sort, Grammar grammar=None):
1624 """
1625 Synthesize n-ary function following specified syntactic constraints.
1626
1627 SyGuS v2:
1628
1629 .. code-block:: smtlib
1630
1631 ( synth-fun <symbol> ( <boundVars>* ) <sort> <g> )
1632
1633 :param symbol: the name of the function
1634 :param boundVars: the parameters to this function
1635 :param sort: the sort of the return value of this function
1636 :param grammar: the syntactic constraints
1637 :return: the function
1638 """
1639 cdef Term term = Term(self)
1640 cdef vector[c_Term] v
1641 for bv in bound_vars:
1642 v.push_back((<Term?> bv).cterm)
1643 if grammar is None:
1644 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort)
1645 else:
1646 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort, grammar.cgrammar)
1647 return term
1648
1649 def checkSynth(self):
1650 """
1651 Try to find a solution for the synthesis conjecture corresponding to the
1652 current list of functions-to-synthesize, universal variables and
1653 constraints.
1654
1655 SyGuS v2:
1656
1657 .. code-block:: smtlib
1658
1659 ( check-synth )
1660
1661 :return: the result of the synthesis conjecture.
1662 """
1663 cdef Result r = Result()
1664 r.cr = self.csolver.checkSynth()
1665 return r
1666
1667 def checkSynthNext(self):
1668 """
1669 Try to find a next solution for the synthesis conjecture corresponding
1670 to the current list of functions-to-synthesize, universal variables and
1671 constraints. Must be called immediately after a successful call to
1672 check-synth or check-synth-next. Requires incremental mode.
1673
1674 SyGuS v2:
1675
1676 .. code-block:: smtlib
1677
1678 ( check-synth )
1679
1680 :return: the result of the check, which is unsat if the check succeeded,
1681 in which case solutions are available via getSynthSolutions.
1682 """
1683 cdef Result r = Result()
1684 r.cr = self.csolver.checkSynthNext()
1685 return r
1686
1687 def getSynthSolution(self, Term term):
1688 """
1689 Get the synthesis solution of the given term. This method should be
1690 called immediately after the solver answers unsat for sygus input.
1691
1692 :param term: the term for which the synthesis solution is queried
1693 :return: the synthesis solution of the given term
1694 """
1695 cdef Term t = Term(self)
1696 t.cterm = self.csolver.getSynthSolution(term.cterm)
1697 return t
1698
1699 def getSynthSolutions(self, list terms):
1700 """
1701 Get the synthesis solutions of the given terms. This method should be
1702 called immediately after the solver answers unsat for sygus input.
1703
1704 :param terms: the terms for which the synthesis solutions is queried
1705 :return: the synthesis solutions of the given terms
1706 """
1707 result = []
1708 cdef vector[c_Term] vec
1709 for t in terms:
1710 vec.push_back((<Term?> t).cterm)
1711 cresult = self.csolver.getSynthSolutions(vec)
1712 for s in cresult:
1713 term = Term(self)
1714 term.cterm = s
1715 result.append(term)
1716 return result
1717
1718
1719 def synthInv(self, symbol, bound_vars, Grammar grammar=None):
1720 """
1721 Synthesize invariant.
1722
1723 SyGuS v2:
1724
1725 .. code-block:: smtlib
1726
1727 ( synth-inv <symbol> ( <boundVars>* ) <grammar> )
1728
1729 :param symbol: the name of the invariant
1730 :param boundVars: the parameters to this invariant
1731 :param grammar: the syntactic constraints
1732 :return: the invariant
1733 """
1734 cdef Term term = Term(self)
1735 cdef vector[c_Term] v
1736 for bv in bound_vars:
1737 v.push_back((<Term?> bv).cterm)
1738 if grammar is None:
1739 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v)
1740 else:
1741 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v, grammar.cgrammar)
1742 return term
1743
1744 @expand_list_arg(num_req_args=0)
1745 def checkSatAssuming(self, *assumptions):
1746 """ Check satisfiability assuming the given formula.
1747
1748 SMT-LIB:
1749
1750 .. code-block:: smtlib
1751
1752 ( check-sat-assuming ( <prop_literal> ) )
1753
1754 :param assumptions: the formulas to assume, as a list or as distinct arguments
1755 :return: the result of the satisfiability check.
1756 """
1757 cdef Result r = Result()
1758 # used if assumptions is a list of terms
1759 cdef vector[c_Term] v
1760 for a in assumptions:
1761 v.push_back((<Term?> a).cterm)
1762 r.cr = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
1763 return r
1764
1765 @expand_list_arg(num_req_args=0)
1766 def checkEntailed(self, *assumptions):
1767 """Check entailment of the given formula w.r.t. the current set of assertions.
1768
1769 :param terms: the formulas to check entailment for, as a list or as distinct arguments
1770 :return: the result of the entailment check.
1771 """
1772 cdef Result r = Result()
1773 # used if assumptions is a list of terms
1774 cdef vector[c_Term] v
1775 for a in assumptions:
1776 v.push_back((<Term?> a).cterm)
1777 r.cr = self.csolver.checkEntailed(<const vector[c_Term]&> v)
1778 return r
1779
1780 @expand_list_arg(num_req_args=1)
1781 def declareDatatype(self, str symbol, *ctors):
1782 """
1783 Create datatype sort.
1784
1785 SMT-LIB:
1786
1787 .. code-block:: smtlib
1788
1789 ( declare-datatype <symbol> <datatype_decl> )
1790
1791 :param symbol: the name of the datatype sort
1792 :param ctors: the constructor declarations of the datatype sort, as a list or as distinct arguments
1793 :return: the datatype sort
1794 """
1795 cdef Sort sort = Sort(self)
1796 cdef vector[c_DatatypeConstructorDecl] v
1797
1798 for c in ctors:
1799 v.push_back((<DatatypeConstructorDecl?> c).cddc)
1800 sort.csort = self.csolver.declareDatatype(symbol.encode(), v)
1801 return sort
1802
1803 def declareFun(self, str symbol, list sorts, Sort sort):
1804 """Declare n-ary function symbol.
1805
1806 SMT-LIB:
1807
1808 .. code-block:: smtlib
1809
1810 ( declare-fun <symbol> ( <sort>* ) <sort> )
1811
1812 :param symbol: the name of the function
1813 :param sorts: the sorts of the parameters to this function
1814 :param sort: the sort of the return value of this function
1815 :return: the function
1816 """
1817 cdef Term term = Term(self)
1818 cdef vector[c_Sort] v
1819 for s in sorts:
1820 v.push_back((<Sort?> s).csort)
1821 term.cterm = self.csolver.declareFun(symbol.encode(),
1822 <const vector[c_Sort]&> v,
1823 sort.csort)
1824 return term
1825
1826 def declareSort(self, str symbol, int arity):
1827 """Declare uninterpreted sort.
1828
1829 SMT-LIB:
1830
1831 .. code-block:: smtlib
1832
1833 ( declare-sort <symbol> <numeral> )
1834
1835 :param symbol: the name of the sort
1836 :param arity: the arity of the sort
1837 :return: the sort
1838 """
1839 cdef Sort sort = Sort(self)
1840 sort.csort = self.csolver.declareSort(symbol.encode(), arity)
1841 return sort
1842
1843 def defineFun(self, str symbol, list bound_vars, Sort sort, Term term, glbl=False):
1844 """Define n-ary function.
1845
1846 SMT-LIB:
1847
1848 .. code-block:: smtlib
1849
1850 ( define-fun <function_def> )
1851
1852 :param symbol: the name of the function
1853 :param bound_vars: the parameters to this function
1854 :param sort: the sort of the return value of this function
1855 :param term: the function body
1856 :param glbl: determines whether this definition is global (i.e. persists when popping the context)
1857 :return: the function
1858 """
1859 cdef Term fun = Term(self)
1860 cdef vector[c_Term] v
1861 for bv in bound_vars:
1862 v.push_back((<Term?> bv).cterm)
1863
1864 fun.cterm = self.csolver.defineFun(symbol.encode(),
1865 <const vector[c_Term] &> v,
1866 sort.csort,
1867 term.cterm,
1868 <bint> glbl)
1869 return fun
1870
1871 def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1872 """Define recursive functions.
1873
1874 Supports two uses:
1875
1876 - ``Term defineFunRec(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1877 - ``Term defineFunRec(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1878
1879
1880 SMT-LIB:
1881
1882 .. code-block:: smtlib
1883
1884 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1885
1886 Create elements of parameter ``funs`` with mkConst().
1887
1888 :param funs: the sorted functions
1889 :param bound_vars: the list of parameters to the functions
1890 :param terms: the list of function bodies of the functions
1891 :param global: determines whether this definition is global (i.e. persists when popping the context)
1892 :return: the function
1893 """
1894 cdef Term term = Term(self)
1895 cdef vector[c_Term] v
1896 for bv in bound_vars:
1897 v.push_back((<Term?> bv).cterm)
1898
1899 if t is not None:
1900 term.cterm = self.csolver.defineFunRec((<str?> sym_or_fun).encode(),
1901 <const vector[c_Term] &> v,
1902 (<Sort?> sort_or_term).csort,
1903 (<Term?> t).cterm,
1904 <bint> glbl)
1905 else:
1906 term.cterm = self.csolver.defineFunRec((<Term?> sym_or_fun).cterm,
1907 <const vector[c_Term]&> v,
1908 (<Term?> sort_or_term).cterm,
1909 <bint> glbl)
1910
1911 return term
1912
1913 def defineFunsRec(self, funs, bound_vars, terms):
1914 """Define recursive functions.
1915
1916 SMT-LIB:
1917
1918 .. code-block:: smtlib
1919
1920 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1921
1922 Create elements of parameter ``funs`` with mkConst().
1923
1924 :param funs: the sorted functions
1925 :param bound_vars: the list of parameters to the functions
1926 :param terms: the list of function bodies of the functions
1927 :param global: determines whether this definition is global (i.e. persists when popping the context)
1928 :return: the function
1929 """
1930 cdef vector[c_Term] vf
1931 cdef vector[vector[c_Term]] vbv
1932 cdef vector[c_Term] vt
1933
1934 for f in funs:
1935 vf.push_back((<Term?> f).cterm)
1936
1937 cdef vector[c_Term] temp
1938 for v in bound_vars:
1939 for t in v:
1940 temp.push_back((<Term?> t).cterm)
1941 vbv.push_back(temp)
1942 temp.clear()
1943
1944 for t in terms:
1945 vf.push_back((<Term?> t).cterm)
1946
1947 def getAssertions(self):
1948 """Get the list of asserted formulas.
1949
1950 SMT-LIB:
1951
1952 .. code-block:: smtlib
1953
1954 ( get-assertions )
1955
1956 :return: the list of asserted formulas
1957 """
1958 assertions = []
1959 for a in self.csolver.getAssertions():
1960 term = Term(self)
1961 term.cterm = a
1962 assertions.append(term)
1963 return assertions
1964
1965 def getInfo(self, str flag):
1966 """Get info from the solver.
1967
1968 SMT-LIB:
1969
1970 .. code-block:: smtlib
1971
1972 ( get-info <info_flag> )
1973
1974 :param flag: the info flag
1975 :return: the info
1976 """
1977 return self.csolver.getInfo(flag.encode())
1978
1979 def getOption(self, str option):
1980 """Get the value of a given option.
1981
1982 SMT-LIB:
1983
1984 .. code-block:: smtlib
1985
1986 ( get-option <keyword> )
1987
1988 :param option: the option for which the value is queried
1989 :return: a string representation of the option value
1990 """
1991 return self.csolver.getOption(option.encode())
1992
1993 def getUnsatAssumptions(self):
1994 """
1995 Get the set of unsat ("failed") assumptions.
1996
1997 SMT-LIB:
1998
1999 .. code-block:: smtlib
2000
2001 ( get-unsat-assumptions )
2002
2003 Requires to enable option :ref:`produce-unsat-assumptions <lbl-option-produce-unsat-assumptions>`.
2004
2005 :return: the set of unsat assumptions.
2006 """
2007 assumptions = []
2008 for a in self.csolver.getUnsatAssumptions():
2009 term = Term(self)
2010 term.cterm = a
2011 assumptions.append(term)
2012 return assumptions
2013
2014 def getUnsatCore(self):
2015 """Get the unsatisfiable core.
2016
2017 SMT-LIB:
2018
2019 .. code-block:: smtlib
2020
2021 ( get-unsat-core )
2022
2023 Requires to enable option :ref:`produce-unsat-cores <lbl-option-produce-unsat-cores>`.
2024
2025 :return: a set of terms representing the unsatisfiable core
2026 """
2027 core = []
2028 for a in self.csolver.getUnsatCore():
2029 term = Term(self)
2030 term.cterm = a
2031 core.append(term)
2032 return core
2033
2034 def getValue(self, Term t):
2035 """Get the value of the given term in the current model.
2036
2037 SMT-LIB:
2038
2039 .. code-block:: smtlib
2040
2041 ( get-value ( <term> ) )
2042
2043 :param term: the term for which the value is queried
2044 :return: the value of the given term
2045 """
2046 cdef Term term = Term(self)
2047 term.cterm = self.csolver.getValue(t.cterm)
2048 return term
2049
2050 def getModelDomainElements(self, Sort s):
2051 """
2052 Get the domain elements of uninterpreted sort s in the current model. The
2053 current model interprets s as the finite sort whose domain elements are
2054 given in the return value of this method.
2055
2056 :param s: The uninterpreted sort in question
2057 :return: the domain elements of s in the current model
2058 """
2059 result = []
2060 cresult = self.csolver.getModelDomainElements(s.csort)
2061 for e in cresult:
2062 term = Term(self)
2063 term.cterm = e
2064 result.append(term)
2065 return result
2066
2067 def isModelCoreSymbol(self, Term v):
2068 """
2069 This returns false if the model value of free constant v was not
2070 essential for showing the satisfiability of the last call to checkSat
2071 using the current model. This method will only return false (for any v)
2072 if the model-cores option has been set.
2073
2074 :param v: The term in question
2075 :return: true if v is a model core symbol
2076 """
2077 return self.csolver.isModelCoreSymbol(v.cterm)
2078
2079 def getValueSepHeap(self):
2080 """When using separation logic, obtain the term for the heap.
2081
2082 :return: The term for the heap
2083 """
2084 cdef Term term = Term(self)
2085 term.cterm = self.csolver.getValueSepHeap()
2086 return term
2087
2088 def getValueSepNil(self):
2089 """When using separation logic, obtain the term for nil.
2090
2091 :return: The term for nil
2092 """
2093 cdef Term term = Term(self)
2094 term.cterm = self.csolver.getValueSepNil()
2095 return term
2096
2097 def declareSepHeap(self, Sort locType, Sort dataType):
2098 """
2099 When using separation logic, this sets the location sort and the
2100 datatype sort to the given ones. This method should be invoked exactly
2101 once, before any separation logic constraints are provided.
2102
2103 :param locSort: The location sort of the heap
2104 :param dataSort: The data sort of the heap
2105 """
2106 self.csolver.declareSepHeap(locType.csort, dataType.csort)
2107
2108 def declarePool(self, str symbol, Sort sort, initValue):
2109 """Declare a symbolic pool of terms with the given initial value.
2110
2111 SMT-LIB:
2112
2113 .. code-block:: smtlib
2114
2115 ( declare-pool <symbol> <sort> ( <term>* ) )
2116
2117 :param symbol: The name of the pool
2118 :param sort: The sort of the elements of the pool.
2119 :param initValue: The initial value of the pool
2120 """
2121 cdef Term term = Term(self)
2122 cdef vector[c_Term] niv
2123 for v in initValue:
2124 niv.push_back((<Term?> v).cterm)
2125 term.cterm = self.csolver.declarePool(symbol.encode(), sort.csort, niv)
2126 return term
2127
2128 def pop(self, nscopes=1):
2129 """Pop ``nscopes`` level(s) from the assertion stack.
2130
2131 SMT-LIB:
2132
2133 .. code-block:: smtlib
2134
2135 ( pop <numeral> )
2136
2137 :param nscopes: the number of levels to pop
2138 """
2139 self.csolver.pop(nscopes)
2140
2141 def push(self, nscopes=1):
2142 """ Push ``nscopes`` level(s) to the assertion stack.
2143
2144 SMT-LIB:
2145
2146 .. code-block:: smtlib
2147
2148 ( push <numeral> )
2149
2150 :param nscopes: the number of levels to push
2151 """
2152 self.csolver.push(nscopes)
2153
2154 def resetAssertions(self):
2155 """
2156 Remove all assertions.
2157
2158 SMT-LIB:
2159
2160 .. code-block:: smtlib
2161
2162 ( reset-assertions )
2163
2164 """
2165 self.csolver.resetAssertions()
2166
2167 def setInfo(self, str keyword, str value):
2168 """Set info.
2169
2170 SMT-LIB:
2171
2172 .. code-block:: smtlib
2173
2174 ( set-info <attribute> )
2175
2176 :param keyword: the info flag
2177 :param value: the value of the info flag
2178 """
2179 self.csolver.setInfo(keyword.encode(), value.encode())
2180
2181 def setLogic(self, str logic):
2182 """Set logic.
2183
2184 SMT-LIB:
2185
2186 .. code-block:: smtlib
2187
2188 ( set-logic <symbol> )
2189
2190 :param logic: the logic to set
2191 """
2192 self.csolver.setLogic(logic.encode())
2193
2194 def setOption(self, str option, str value):
2195 """Set option.
2196
2197 SMT-LIB:
2198
2199 .. code-block:: smtlib
2200
2201 ( set-option <option> )
2202
2203 :param option: the option name
2204 :param value: the option value
2205 """
2206 self.csolver.setOption(option.encode(), value.encode())
2207
2208 def getInterpolant(self, Term conj, *args):
2209 """Get an interpolant.
2210
2211 SMT-LIB:
2212
2213 .. code-block:: smtlib
2214
2215 ( get-interpol <conj> )
2216 ( get-interpol <conj> <grammar> )
2217
2218 Requires option :ref:`produce-interpols <lbl-option-produce-interpols>` to be set to a mode different from `none`.
2219
2220 Supports the following variants:
2221
2222 - ``bool getInteprolant(Term conj, Term output)``
2223 - ``bool getInteprolant(Term conj, Grammar grammar, Term output)``
2224
2225 :param conj: the conjecture term
2226 :param output: the term where the result will be stored
2227 :param grammar: a grammar for the inteprolant
2228 :return: True iff an interpolant was found
2229 """
2230 result = False
2231 if len(args) == 1:
2232 assert isinstance(args[0], Term)
2233 result = self.csolver.getInterpolant(conj.cterm, (<Term ?> args[0]).cterm)
2234 else:
2235 assert len(args) == 2
2236 assert isinstance(args[0], Grammar)
2237 assert isinstance(args[1], Term)
2238 result = self.csolver.getInterpolant(conj.cterm, (<Grammar ?> args[0]).cgrammar, (<Term ?> args[1]).cterm)
2239 return result
2240
2241
2242 def getInterpolantNext(self, Term output):
2243 """
2244 Get the next interpolant. Can only be called immediately after
2245 a succesful call to get-interpol or get-interpol-next.
2246 Is guaranteed to produce a syntactically different interpolant wrt the
2247 last returned interpolant if successful.
2248
2249 SMT-LIB:
2250
2251 .. code-block:: smtlib
2252
2253 ( get-interpol-next )
2254
2255 Requires to enable incremental mode, and
2256 option :ref:`produce-interpols <lbl-option-produce-interpols>` to be set to a mode different from `none`.
2257
2258 :param output: the term where the result will be stored
2259 :return: True iff an interpolant was found
2260 """
2261 result = self.csolver.getInterpolantNext(output.cterm)
2262 return result
2263
2264 def getAbduct(self, Term conj, *args):
2265 """Get an abduct.
2266
2267 SMT-LIB:
2268
2269 .. code-block:: smtlib
2270
2271 ( get-abduct <conj> )
2272 ( get-abduct <conj> <grammar> )
2273
2274 Requires to enable option :ref:`produce-abducts <lbl-option-produce-abducts>`.
2275
2276 Supports the following variants:
2277
2278 - ``bool getAbduct(Term conj, Term output)``
2279 - ``bool getAbduct(Term conj, Grammar grammar, Term output)``
2280
2281 :param conj: the conjecture term
2282 :param output: the term where the result will be stored
2283 :param grammar: a grammar for the abduct
2284 :return: True iff an abduct was found
2285 """
2286 result = False
2287 if len(args) == 1:
2288 assert isinstance(args[0], Term)
2289 result = self.csolver.getAbduct(conj.cterm, (<Term ?> args[0]).cterm)
2290 else:
2291 assert len(args) == 2
2292 assert isinstance(args[0], Grammar)
2293 assert isinstance(args[1], Term)
2294 result = self.csolver.getAbduct(conj.cterm, (<Grammar ?> args[0]).cgrammar, (<Term ?> args[1]).cterm)
2295 return result
2296
2297 def getAbductNext(self, Term output):
2298 """
2299 Get the next abduct. Can only be called immediately after
2300 a succesful call to get-abduct or get-abduct-next.
2301 Is guaranteed to produce a syntactically different abduct wrt the
2302 last returned abduct if successful.
2303
2304 SMT-LIB:
2305
2306 .. code-block:: smtlib
2307
2308 ( get-abduct-next )
2309
2310 Requires to enable incremental mode, and
2311 option :ref:`produce-abducts <lbl-option-produce-abducts>`.
2312 :param output: the term where the result will be stored
2313 :return: True iff an abduct was found
2314 """
2315 result = self.csolver.getAbductNext(output.cterm)
2316 return result
2317
2318
2319
2320 cdef class Sort:
2321 """
2322 The sort of a cvc5 term.
2323 """
2324 cdef c_Sort csort
2325 cdef Solver solver
2326 def __cinit__(self, Solver solver):
2327 # csort always set by Solver
2328 self.solver = solver
2329
2330 def __eq__(self, Sort other):
2331 return self.csort == other.csort
2332
2333 def __ne__(self, Sort other):
2334 return self.csort != other.csort
2335
2336 def __lt__(self, Sort other):
2337 return self.csort < other.csort
2338
2339 def __gt__(self, Sort other):
2340 return self.csort > other.csort
2341
2342 def __le__(self, Sort other):
2343 return self.csort <= other.csort
2344
2345 def __ge__(self, Sort other):
2346 return self.csort >= other.csort
2347
2348 def __str__(self):
2349 return self.csort.toString().decode()
2350
2351 def __repr__(self):
2352 return self.csort.toString().decode()
2353
2354 def __hash__(self):
2355 return csorthash(self.csort)
2356
2357 def hasSymbol(self):
2358 """:return: True iff this sort has a symbol."""
2359 return self.csort.hasSymbol()
2360
2361 def getSymbol(self):
2362 """
2363 Asserts :py:meth:`hasSymbol()`.
2364
2365 :return: the raw symbol of the sort.
2366 """
2367 return self.csort.getSymbol().decode()
2368
2369 def isNull(self):
2370 """:return: True if this Sort is a null sort."""
2371 return self.csort.isNull()
2372
2373 def isBoolean(self):
2374 """
2375 Is this a Boolean sort?
2376
2377 :return: True if the sort is the Boolean sort.
2378 """
2379 return self.csort.isBoolean()
2380
2381 def isInteger(self):
2382 """
2383 Is this an integer sort?
2384
2385 :return: True if the sort is the integer sort.
2386 """
2387 return self.csort.isInteger()
2388
2389 def isReal(self):
2390 """
2391 Is this a real sort?
2392
2393 :return: True if the sort is the real sort.
2394 """
2395 return self.csort.isReal()
2396
2397 def isString(self):
2398 """
2399 Is this a string sort?
2400
2401 :return: True if the sort is the string sort.
2402 """
2403 return self.csort.isString()
2404
2405 def isRegExp(self):
2406 """
2407 Is this a regexp sort?
2408
2409 :return: True if the sort is the regexp sort.
2410 """
2411 return self.csort.isRegExp()
2412
2413 def isRoundingMode(self):
2414 """
2415 Is this a rounding mode sort?
2416
2417 :return: True if the sort is the rounding mode sort.
2418 """
2419 return self.csort.isRoundingMode()
2420
2421 def isBitVector(self):
2422 """
2423 Is this a bit-vector sort?
2424
2425 :return: True if the sort is a bit-vector sort.
2426 """
2427 return self.csort.isBitVector()
2428
2429 def isFloatingPoint(self):
2430 """
2431 Is this a floating-point sort?
2432
2433 :return: True if the sort is a bit-vector sort.
2434 """
2435 return self.csort.isFloatingPoint()
2436
2437 def isDatatype(self):
2438 """
2439 Is this a datatype sort?
2440
2441 :return: True if the sort is a datatype sort.
2442 """
2443 return self.csort.isDatatype()
2444
2445 def isParametricDatatype(self):
2446 """
2447 Is this a parametric datatype sort?
2448
2449 :return: True if the sort is a parametric datatype sort.
2450 """
2451 return self.csort.isParametricDatatype()
2452
2453 def isConstructor(self):
2454 """
2455 Is this a constructor sort?
2456
2457 :return: True if the sort is a constructor sort.
2458 """
2459 return self.csort.isConstructor()
2460
2461 def isSelector(self):
2462 """
2463 Is this a selector sort?
2464
2465 :return: True if the sort is a selector sort.
2466 """
2467 return self.csort.isSelector()
2468
2469 def isTester(self):
2470 """
2471 Is this a tester sort?
2472
2473 :return: True if the sort is a selector sort.
2474 """
2475 return self.csort.isTester()
2476
2477 def isUpdater(self):
2478 """
2479 Is this a datatype updater sort?
2480
2481 :return: True if the sort is a datatype updater sort.
2482 """
2483 return self.csort.isUpdater()
2484
2485 def isFunction(self):
2486 """
2487 Is this a function sort?
2488
2489 :return: True if the sort is a function sort.
2490 """
2491 return self.csort.isFunction()
2492
2493 def isPredicate(self):
2494 """
2495 Is this a predicate sort?
2496 That is, is this a function sort mapping to Boolean? All predicate
2497 sorts are also function sorts.
2498
2499 :return: True if the sort is a predicate sort.
2500 """
2501 return self.csort.isPredicate()
2502
2503 def isTuple(self):
2504 """
2505 Is this a tuple sort?
2506
2507 :return: True if the sort is a tuple sort.
2508 """
2509 return self.csort.isTuple()
2510
2511 def isRecord(self):
2512 """
2513 Is this a record sort?
2514
2515 :return: True if the sort is a record sort.
2516 """
2517 return self.csort.isRecord()
2518
2519 def isArray(self):
2520 """
2521 Is this an array sort?
2522
2523 :return: True if the sort is an array sort.
2524 """
2525 return self.csort.isArray()
2526
2527 def isSet(self):
2528 """
2529 Is this a set sort?
2530
2531 :return: True if the sort is a set sort.
2532 """
2533 return self.csort.isSet()
2534
2535 def isBag(self):
2536 """
2537 Is this a bag sort?
2538
2539 :return: True if the sort is a bag sort.
2540 """
2541 return self.csort.isBag()
2542
2543 def isSequence(self):
2544 """
2545 Is this a sequence sort?
2546
2547 :return: True if the sort is a sequence sort.
2548 """
2549 return self.csort.isSequence()
2550
2551 def isUninterpretedSort(self):
2552 """
2553 Is this a sort uninterpreted?
2554
2555 :return: True if the sort is uninterpreted.
2556 """
2557 return self.csort.isUninterpretedSort()
2558
2559 def isSortConstructor(self):
2560 """
2561 Is this a sort constructor kind?
2562
2563 :return: True if this a sort constructor kind.
2564 """
2565 return self.csort.isSortConstructor()
2566
2567 def isFirstClass(self):
2568 """
2569 Is this a first-class sort?
2570 First-class sorts are sorts for which:
2571
2572 1. we handle equalities between terms of that type, and
2573 2. they are allowed to be parameters of parametric sorts
2574 (e.g. index or element sorts of arrays).
2575
2576 Examples of sorts that are not first-class include sort constructor
2577 sorts and regular expression sorts.
2578
2579 :return: True if the sort is a first-class sort.
2580 """
2581 return self.csort.isFirstClass()
2582
2583 def isFunctionLike(self):
2584 """
2585 Is this a function-LIKE sort?
2586
2587 Anything function-like except arrays (e.g., datatype selectors) is
2588 considered a function here. Function-like terms can not be the argument
2589 or return value for any term that is function-like.
2590 This is mainly to avoid higher order.
2591
2592 .. note:: Arrays are explicitly not considered function-like here.
2593
2594 :return: True if this is a function-like sort
2595 """
2596 return self.csort.isFunctionLike()
2597
2598 def isSubsortOf(self, Sort sort):
2599 """
2600 Is this sort a subsort of the given sort?
2601
2602 :return: True if this sort is a subsort of s
2603 """
2604 return self.csort.isSubsortOf(sort.csort)
2605
2606 def getDatatype(self):
2607 """
2608 :return: the underlying datatype of a datatype sort
2609 """
2610 cdef Datatype d = Datatype(self.solver)
2611 d.cd = self.csort.getDatatype()
2612 return d
2613
2614 def instantiate(self, params):
2615 """
2616 Instantiate a parameterized datatype/sort sort.
2617 Create sorts parameter with :py:meth:`Solver.mkParamSort()`
2618
2619 :param params: the list of sort parameters to instantiate with
2620 """
2621 cdef Sort sort = Sort(self.solver)
2622 cdef vector[c_Sort] v
2623 for s in params:
2624 v.push_back((<Sort?> s).csort)
2625 sort.csort = self.csort.instantiate(v)
2626 return sort
2627
2628 def substitute(self, sort_or_list_1, sort_or_list_2):
2629 """
2630 Substitution of Sorts.
2631
2632 :param sort_or_list_1: the subsort or subsorts to be substituted within this sort.
2633 :param sort_or_list_2: the sort or list of sorts replacing the substituted subsort.
2634
2635 Note that this replacement is applied during a pre-order traversal and
2636 only once to the sort. It is not run until fix point. In the case that
2637 sort_or_list_1 contains duplicates, the replacement earliest in the list
2638 takes priority.
2639
2640 For example,
2641 (Array A B) .substitute([A, C], [(Array C D), (Array A B)]) will
2642 return (Array (Array C D) B).
2643 """
2644
2645 # The resulting sort after substitution
2646 cdef Sort sort = Sort(self.solver)
2647 # lists for substitutions
2648 cdef vector[c_Sort] ces
2649 cdef vector[c_Sort] creplacements
2650
2651 # normalize the input parameters to be lists
2652 if isinstance(sort_or_list_1, list):
2653 assert isinstance(sort_or_list_2, list)
2654 es = sort_or_list_1
2655 replacements = sort_or_list_2
2656 if len(es) != len(replacements):
2657 raise RuntimeError("Expecting list inputs to substitute to "
2658 "have the same length but got: "
2659 "{} and {}".format(len(es), len(replacements)))
2660
2661 for e, r in zip(es, replacements):
2662 ces.push_back((<Sort?> e).csort)
2663 creplacements.push_back((<Sort?> r).csort)
2664
2665 else:
2666 # add the single elements to the vectors
2667 ces.push_back((<Sort?> sort_or_list_1).csort)
2668 creplacements.push_back((<Sort?> sort_or_list_2).csort)
2669
2670 # call the API substitute method with lists
2671 sort.csort = self.csort.substitute(ces, creplacements)
2672 return sort
2673
2674
2675 def getConstructorArity(self):
2676 """
2677 :return: the arity of a constructor sort.
2678 """
2679 return self.csort.getConstructorArity()
2680
2681 def getConstructorDomainSorts(self):
2682 """
2683 :return: the domain sorts of a constructor sort
2684 """
2685 domain_sorts = []
2686 for s in self.csort.getConstructorDomainSorts():
2687 sort = Sort(self.solver)
2688 sort.csort = s
2689 domain_sorts.append(sort)
2690 return domain_sorts
2691
2692 def getConstructorCodomainSort(self):
2693 """
2694 :return: the codomain sort of a constructor sort
2695 """
2696 cdef Sort sort = Sort(self.solver)
2697 sort.csort = self.csort.getConstructorCodomainSort()
2698 return sort
2699
2700 def getSelectorDomainSort(self):
2701 """
2702 :return: the domain sort of a selector sort
2703 """
2704 cdef Sort sort = Sort(self.solver)
2705 sort.csort = self.csort.getSelectorDomainSort()
2706 return sort
2707
2708 def getSelectorCodomainSort(self):
2709 """
2710 :return: the codomain sort of a selector sort
2711 """
2712 cdef Sort sort = Sort(self.solver)
2713 sort.csort = self.csort.getSelectorCodomainSort()
2714 return sort
2715
2716 def getTesterDomainSort(self):
2717 """
2718 :return: the domain sort of a tester sort
2719 """
2720 cdef Sort sort = Sort(self.solver)
2721 sort.csort = self.csort.getTesterDomainSort()
2722 return sort
2723
2724 def getTesterCodomainSort(self):
2725 """
2726 :return: the codomain sort of a tester sort, which is the Boolean sort
2727 """
2728 cdef Sort sort = Sort(self.solver)
2729 sort.csort = self.csort.getTesterCodomainSort()
2730 return sort
2731
2732 def getFunctionArity(self):
2733 """
2734 :return: the arity of a function sort
2735 """
2736 return self.csort.getFunctionArity()
2737
2738 def getFunctionDomainSorts(self):
2739 """
2740 :return: the domain sorts of a function sort
2741 """
2742 domain_sorts = []
2743 for s in self.csort.getFunctionDomainSorts():
2744 sort = Sort(self.solver)
2745 sort.csort = s
2746 domain_sorts.append(sort)
2747 return domain_sorts
2748
2749 def getFunctionCodomainSort(self):
2750 """
2751 :return: the codomain sort of a function sort
2752 """
2753 cdef Sort sort = Sort(self.solver)
2754 sort.csort = self.csort.getFunctionCodomainSort()
2755 return sort
2756
2757 def getArrayIndexSort(self):
2758 """
2759 :return: the array index sort of an array sort
2760 """
2761 cdef Sort sort = Sort(self.solver)
2762 sort.csort = self.csort.getArrayIndexSort()
2763 return sort
2764
2765 def getArrayElementSort(self):
2766 """
2767 :return: the array element sort of an array sort
2768 """
2769 cdef Sort sort = Sort(self.solver)
2770 sort.csort = self.csort.getArrayElementSort()
2771 return sort
2772
2773 def getSetElementSort(self):
2774 """
2775 :return: the element sort of a set sort
2776 """
2777 cdef Sort sort = Sort(self.solver)
2778 sort.csort = self.csort.getSetElementSort()
2779 return sort
2780
2781 def getBagElementSort(self):
2782 """
2783 :return: the element sort of a bag sort
2784 """
2785 cdef Sort sort = Sort(self.solver)
2786 sort.csort = self.csort.getBagElementSort()
2787 return sort
2788
2789 def getSequenceElementSort(self):
2790 """
2791 :return: the element sort of a sequence sort
2792 """
2793 cdef Sort sort = Sort(self.solver)
2794 sort.csort = self.csort.getSequenceElementSort()
2795 return sort
2796
2797 def getUninterpretedSortName(self):
2798 """
2799 :return: the name of an uninterpreted sort
2800 """
2801 return self.csort.getUninterpretedSortName().decode()
2802
2803 def isUninterpretedSortParameterized(self):
2804 """
2805 :return: True if an uninterpreted sort is parameterized
2806 """
2807 return self.csort.isUninterpretedSortParameterized()
2808
2809 def getUninterpretedSortParamSorts(self):
2810 """
2811 :return: the parameter sorts of an uninterpreted sort
2812 """
2813 param_sorts = []
2814 for s in self.csort.getUninterpretedSortParamSorts():
2815 sort = Sort(self.solver)
2816 sort.csort = s
2817 param_sorts.append(sort)
2818 return param_sorts
2819
2820 def getSortConstructorName(self):
2821 """
2822 :return: the name of a sort constructor sort
2823 """
2824 return self.csort.getSortConstructorName().decode()
2825
2826 def getSortConstructorArity(self):
2827 """
2828 :return: the arity of a sort constructor sort
2829 """
2830 return self.csort.getSortConstructorArity()
2831
2832 def getBitVectorSize(self):
2833 """
2834 :return: the bit-width of the bit-vector sort
2835 """
2836 return self.csort.getBitVectorSize()
2837
2838 def getFloatingPointExponentSize(self):
2839 """
2840 :return: the bit-width of the exponent of the floating-point sort
2841 """
2842 return self.csort.getFloatingPointExponentSize()
2843
2844 def getFloatingPointSignificandSize(self):
2845 """
2846 :return: the width of the significand of the floating-point sort
2847 """
2848 return self.csort.getFloatingPointSignificandSize()
2849
2850 def getDatatypeParamSorts(self):
2851 """
2852 Return the parameters of a parametric datatype sort. If this sort
2853 is a non-instantiated parametric datatype, this returns the
2854 parameter sorts of the underlying datatype. If this sort is an
2855 instantiated parametric datatype, then this returns the sort
2856 parameters that were used to construct the sort via
2857 :py:meth:`instantiate()`.
2858
2859 :return: the parameter sorts of a parametric datatype sort
2860 """
2861 param_sorts = []
2862 for s in self.csort.getDatatypeParamSorts():
2863 sort = Sort(self.solver)
2864 sort.csort = s
2865 param_sorts.append(sort)
2866 return param_sorts
2867
2868 def getDatatypeArity(self):
2869 """
2870 :return: the arity of a datatype sort
2871 """
2872 return self.csort.getDatatypeArity()
2873
2874 def getTupleLength(self):
2875 """
2876 :return: the length of a tuple sort
2877 """
2878 return self.csort.getTupleLength()
2879
2880 def getTupleSorts(self):
2881 """
2882 :return: the element sorts of a tuple sort
2883 """
2884 tuple_sorts = []
2885 for s in self.csort.getTupleSorts():
2886 sort = Sort(self.solver)
2887 sort.csort = s
2888 tuple_sorts.append(sort)
2889 return tuple_sorts
2890
2891
2892 cdef class Term:
2893 """
2894 A cvc5 Term.
2895 Wrapper class for :cpp:class:`cvc5::api::Term`.
2896 """
2897 cdef c_Term cterm
2898 cdef Solver solver
2899 def __cinit__(self, Solver solver):
2900 # cterm always set in the Solver object
2901 self.solver = solver
2902
2903 def __eq__(self, Term other):
2904 return self.cterm == other.cterm
2905
2906 def __ne__(self, Term other):
2907 return self.cterm != other.cterm
2908
2909 def __lt__(self, Term other):
2910 return self.cterm < other.cterm
2911
2912 def __gt__(self, Term other):
2913 return self.cterm > other.cterm
2914
2915 def __le__(self, Term other):
2916 return self.cterm <= other.cterm
2917
2918 def __ge__(self, Term other):
2919 return self.cterm >= other.cterm
2920
2921 def __getitem__(self, int index):
2922 cdef Term term = Term(self.solver)
2923 if index >= 0:
2924 term.cterm = self.cterm[index]
2925 else:
2926 raise ValueError("Expecting a non-negative integer or string")
2927 return term
2928
2929 def __str__(self):
2930 return self.cterm.toString().decode()
2931
2932 def __repr__(self):
2933 return self.cterm.toString().decode()
2934
2935 def __iter__(self):
2936 for ci in self.cterm:
2937 term = Term(self.solver)
2938 term.cterm = ci
2939 yield term
2940
2941 def __hash__(self):
2942 return ctermhash(self.cterm)
2943
2944 def getNumChildren(self):
2945 """:return: the number of children of this term."""
2946 return self.cterm.getNumChildren()
2947
2948 def getId(self):
2949 """:return: the id of this term."""
2950 return self.cterm.getId()
2951
2952 def getKind(self):
2953 """:return: the :py:class:`cvc5.Kind` of this term."""
2954 return Kind(<int> self.cterm.getKind())
2955
2956 def getSort(self):
2957 """:return: the :py:class:`cvc5.Sort` of this term."""
2958 cdef Sort sort = Sort(self.solver)
2959 sort.csort = self.cterm.getSort()
2960 return sort
2961
2962 def substitute(self, term_or_list_1, term_or_list_2):
2963 """
2964 :return: the result of simultaneously replacing the term(s) stored in ``term_or_list_1`` by the term(s) stored in ``term_or_list_2`` in this term.
2965
2966 Note that this replacement is applied during a pre-order traversal and
2967 only once to the term. It is not run until fix point. In the case that
2968 terms contains duplicates, the replacement earliest in the list takes
2969 priority. For example, calling substitute on f(x,y) with
2970 term_or_list_1 = [ x, z ], term_or_list_2 = [ g(z), w ]
2971 results in the term f(g(z),y).
2972 """
2973 # The resulting term after substitution
2974 cdef Term term = Term(self.solver)
2975 # lists for substitutions
2976 cdef vector[c_Term] ces
2977 cdef vector[c_Term] creplacements
2978
2979 # normalize the input parameters to be lists
2980 if isinstance(term_or_list_1, list):
2981 assert isinstance(term_or_list_2, list)
2982 es = term_or_list_1
2983 replacements = term_or_list_2
2984 if len(es) != len(replacements):
2985 raise RuntimeError("Expecting list inputs to substitute to "
2986 "have the same length but got: "
2987 "{} and {}".format(len(es), len(replacements)))
2988
2989 for e, r in zip(es, replacements):
2990 ces.push_back((<Term?> e).cterm)
2991 creplacements.push_back((<Term?> r).cterm)
2992
2993 else:
2994 # add the single elements to the vectors
2995 ces.push_back((<Term?> term_or_list_1).cterm)
2996 creplacements.push_back((<Term?> term_or_list_2).cterm)
2997
2998 # call the API substitute method with lists
2999 term.cterm = self.cterm.substitute(ces, creplacements)
3000 return term
3001
3002 def hasOp(self):
3003 """:return: True iff this term has an operator."""
3004 return self.cterm.hasOp()
3005
3006 def getOp(self):
3007 """
3008 .. note:: This is safe to call when :py:meth:`hasOp()` returns True.
3009
3010 :return: the :py:class:`cvc5.Op` used to create this Term.
3011 """
3012 cdef Op op = Op(self.solver)
3013 op.cop = self.cterm.getOp()
3014 return op
3015
3016 def hasSymbol(self):
3017 """:return: True iff this term has a symbol."""
3018 return self.cterm.hasSymbol()
3019
3020 def getSymbol(self):
3021 """
3022 Asserts :py:meth:`hasSymbol()`.
3023
3024 :return: the raw symbol of the term.
3025 """
3026 return self.cterm.getSymbol().decode()
3027
3028 def isNull(self):
3029 """:return: True iff this term is a null term."""
3030 return self.cterm.isNull()
3031
3032 def notTerm(self):
3033 """
3034 Boolean negation.
3035
3036 :return: the Boolean negation of this term.
3037 """
3038 cdef Term term = Term(self.solver)
3039 term.cterm = self.cterm.notTerm()
3040 return term
3041
3042 def andTerm(self, Term t):
3043 """
3044 Boolean and.
3045
3046 :param t: a Boolean term
3047 :return: the conjunction of this term and the given term
3048 """
3049 cdef Term term = Term(self.solver)
3050 term.cterm = self.cterm.andTerm((<Term> t).cterm)
3051 return term
3052
3053 def orTerm(self, Term t):
3054 """
3055 Boolean or.
3056
3057 :param t: a Boolean term
3058 :return: the disjunction of this term and the given term
3059 """
3060 cdef Term term = Term(self.solver)
3061 term.cterm = self.cterm.orTerm(t.cterm)
3062 return term
3063
3064 def xorTerm(self, Term t):
3065 """
3066 Boolean exclusive or.
3067
3068 :param t: a Boolean term
3069 :return: the exclusive disjunction of this term and the given term
3070 """
3071 cdef Term term = Term(self.solver)
3072 term.cterm = self.cterm.xorTerm(t.cterm)
3073 return term
3074
3075 def eqTerm(self, Term t):
3076 """
3077 Equality
3078
3079 :param t: a Boolean term
3080 :return: the Boolean equivalence of this term and the given term
3081 """
3082 cdef Term term = Term(self.solver)
3083 term.cterm = self.cterm.eqTerm(t.cterm)
3084 return term
3085
3086 def impTerm(self, Term t):
3087 """
3088 Boolean Implication.
3089
3090 :param t: a Boolean term
3091 :return: the implication of this term and the given term
3092 """
3093 cdef Term term = Term(self.solver)
3094 term.cterm = self.cterm.impTerm(t.cterm)
3095 return term
3096
3097 def iteTerm(self, Term then_t, Term else_t):
3098 """
3099 If-then-else with this term as the Boolean condition.
3100
3101 :param then_t: the `then` term
3102 :param else_t: the `else` term
3103 :return: the if-then-else term with this term as the Boolean condition
3104 """
3105 cdef Term term = Term(self.solver)
3106 term.cterm = self.cterm.iteTerm(then_t.cterm, else_t.cterm)
3107 return term
3108
3109 def isConstArray(self):
3110 """:return: True iff this term is a constant array."""
3111 return self.cterm.isConstArray()
3112
3113 def getConstArrayBase(self):
3114 """
3115 Asserts :py:meth:`isConstArray()`.
3116
3117 :return: the base (element stored at all indicies) of this constant array
3118 """
3119 cdef Term term = Term(self.solver)
3120 term.cterm = self.cterm.getConstArrayBase()
3121 return term
3122
3123 def isBooleanValue(self):
3124 """:return: True iff this term is a Boolean value."""
3125 return self.cterm.isBooleanValue()
3126
3127 def getBooleanValue(self):
3128 """
3129 Asserts :py:meth:`isBooleanValue()`
3130
3131 :return: the representation of a Boolean value as a native Boolean value.
3132 """
3133 return self.cterm.getBooleanValue()
3134
3135 def isStringValue(self):
3136 """:return: True iff this term is a string value."""
3137 return self.cterm.isStringValue()
3138
3139 def getStringValue(self):
3140 """
3141 Asserts :py:meth:`isStringValue()`.
3142
3143 .. note::
3144 This method is not to be confused with :py:meth:`__str__()` which
3145 returns the term in some string representation, whatever data it
3146 may hold.
3147
3148 :return: the string term as a native string value.
3149 """
3150 cdef Py_ssize_t size
3151 cdef c_wstring s = self.cterm.getStringValue()
3152 return PyUnicode_FromWideChar(s.data(), s.size())
3153
3154 def getRealOrIntegerValueSign(self):
3155 """
3156 Get integer or real value sign. Must be called on integer or real values,
3157 or otherwise an exception is thrown.
3158
3159 :return: 0 if this term is zero, -1 if this term is a negative real or
3160 integer value, 1 if this term is a positive real or integer value.
3161 """
3162 return self.cterm.getRealOrIntegerValueSign()
3163
3164 def isIntegerValue(self):
3165 """:return: True iff this term is an integer value."""
3166 return self.cterm.isIntegerValue()
3167
3168 def getIntegerValue(self):
3169 """
3170 Asserts :py:meth:`isIntegerValue()`.
3171
3172 :return: the integer term as a native python integer.
3173 """
3174 return int(self.cterm.getIntegerValue().decode())
3175
3176 def isFloatingPointPosZero(self):
3177 """:return: True iff the term is the floating-point value for positive zero."""
3178 return self.cterm.isFloatingPointPosZero()
3179
3180 def isFloatingPointNegZero(self):
3181 """:return: True iff the term is the floating-point value for negative zero."""
3182 return self.cterm.isFloatingPointNegZero()
3183
3184 def isFloatingPointPosInf(self):
3185 """:return: True iff the term is the floating-point value for positive infinity."""
3186 return self.cterm.isFloatingPointPosInf()
3187
3188 def isFloatingPointNegInf(self):
3189 """:return: True iff the term is the floating-point value for negative infinity."""
3190 return self.cterm.isFloatingPointNegInf()
3191
3192 def isFloatingPointNaN(self):
3193 """:return: True iff the term is the floating-point value for not a number."""
3194 return self.cterm.isFloatingPointNaN()
3195
3196 def isFloatingPointValue(self):
3197 """:return: True iff this term is a floating-point value."""
3198 return self.cterm.isFloatingPointValue()
3199
3200 def getFloatingPointValue(self):
3201 """
3202 Asserts :py:meth:`isFloatingPointValue()`.
3203
3204 :return: the representation of a floating-point value as a tuple of the exponent width, the significand width and a bit-vector value.
3205 """
3206 cdef c_tuple[uint32_t, uint32_t, c_Term] t = self.cterm.getFloatingPointValue()
3207 cdef Term term = Term(self.solver)
3208 term.cterm = get2(t)
3209 return (get0(t), get1(t), term)
3210
3211 def isSetValue(self):
3212 """
3213 A term is a set value if it is considered to be a (canonical) constant
3214 set value. A canonical set value is one whose AST is:
3215
3216 .. code::
3217
3218 (union
3219 (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
3220
3221 where ``c1 ... cn`` are values ordered by id such that
3222 ``c1 > ... > cn`` (see also :cpp:func:`cvc5::api::Term::operator>()`).
3223
3224 .. note::
3225 A universe set term ``(kind SET_UNIVERSE)`` is not considered to be
3226 a set value.
3227
3228 :return: True if the term is a set value.
3229 """
3230 return self.cterm.isSetValue()
3231
3232 def getSetValue(self):
3233 """
3234 Asserts :py:meth:`isSetValue()`.
3235
3236 :return: the representation of a set value as a set of terms.
3237 """
3238 elems = set()
3239 for e in self.cterm.getSetValue():
3240 term = Term(self.solver)
3241 term.cterm = e
3242 elems.add(term)
3243 return elems
3244
3245 def isSequenceValue(self):
3246 """:return: True iff this term is a sequence value."""
3247 return self.cterm.isSequenceValue()
3248
3249 def getSequenceValue(self):
3250 """
3251 Asserts :py:meth:`isSequenceValue()`.
3252
3253 .. note::
3254 It is usually necessary for sequences to call
3255 :py:meth:`Solver.simplify()` to turn a sequence that is constructed
3256 by, e.g., concatenation of unit sequences, into a sequence value.
3257
3258 :return: the representation of a sequence value as a vector of terms.
3259 """
3260 elems = []
3261 for e in self.cterm.getSequenceValue():
3262 term = Term(self.solver)
3263 term.cterm = e
3264 elems.append(term)
3265 return elems
3266
3267 def isUninterpretedSortValue(self):
3268 """:return: True iff this term is a value from an uninterpreted sort."""
3269 return self.cterm.isUninterpretedSortValue()
3270
3271 def getUninterpretedSortValue(self):
3272 """
3273 Asserts :py:meth:`isUninterpretedSortValue()`.
3274
3275 :return: the representation of an uninterpreted value as a pair of its sort and its index.
3276 """
3277 return self.cterm.getUninterpretedSortValue()
3278
3279 def isTupleValue(self):
3280 """:return: True iff this term is a tuple value."""
3281 return self.cterm.isTupleValue()
3282
3283 def getTupleValue(self):
3284 """
3285 Asserts :py:meth:`isTupleValue()`.
3286
3287 :return: the representation of a tuple value as a vector of terms.
3288 """
3289 elems = []
3290 for e in self.cterm.getTupleValue():
3291 term = Term(self.solver)
3292 term.cterm = e
3293 elems.append(term)
3294 return elems
3295
3296 def isRealValue(self):
3297 """
3298 .. note:: A term of kind PI is not considered to be a real value.
3299
3300 :return: True iff this term is a rational value.
3301 """
3302 return self.cterm.isRealValue()
3303
3304 def getRealValue(self):
3305 """
3306 Asserts :py:meth:`isRealValue()`.
3307
3308 :return: the representation of a rational value as a python Fraction.
3309 """
3310 return Fraction(self.cterm.getRealValue().decode())
3311
3312 def isBitVectorValue(self):
3313 """:return: True iff this term is a bit-vector value."""
3314 return self.cterm.isBitVectorValue()
3315
3316 def getBitVectorValue(self, base = 2):
3317 """
3318 Asserts :py:meth:`isBitVectorValue()`.
3319 Supported bases are 2 (bit string), 10 (decimal string) or 16 (hexdecimal string).
3320
3321 :return: the representation of a bit-vector value in string representation.
3322 """
3323 return self.cterm.getBitVectorValue(base).decode()
3324
3325 def toPythonObj(self):
3326 """
3327 Converts a constant value Term to a Python object.
3328
3329 Currently supports:
3330
3331 - Boolean -- returns a Python bool
3332 - Int -- returns a Python int
3333 - Real -- returns a Python Fraction
3334 - BV -- returns a Python int (treats BV as unsigned)
3335 - String -- returns a Python Unicode string
3336 - Array -- returns a Python dict mapping indices to values. the constant base is returned as the default value
3337
3338 """
3339
3340 if self.isBooleanValue():
3341 return self.getBooleanValue()
3342 elif self.isIntegerValue():
3343 return self.getIntegerValue()
3344 elif self.isRealValue():
3345 return self.getRealValue()
3346 elif self.isBitVectorValue():
3347 return int(self.getBitVectorValue(), 2)
3348 elif self.isStringValue():
3349 return self.getStringValue()
3350 elif self.getSort().isArray():
3351 res = None
3352 keys = []
3353 values = []
3354 base_value = None
3355 to_visit = [self]
3356 # Array models are represented as a series of store operations
3357 # on a constant array
3358 while to_visit:
3359 t = to_visit.pop()
3360 if t.getKind().value == c_Kind.STORE:
3361 # save the mappings
3362 keys.append(t[1].toPythonObj())
3363 values.append(t[2].toPythonObj())
3364 to_visit.append(t[0])
3365 else:
3366 assert t.getKind().value == c_Kind.CONST_ARRAY
3367 base_value = t.getConstArrayBase().toPythonObj()
3368
3369 assert len(keys) == len(values)
3370 assert base_value is not None
3371
3372 # put everything in a dictionary with the constant
3373 # base as the result for any index not included in the stores
3374 res = defaultdict(lambda : base_value)
3375 for k, v in zip(keys, values):
3376 res[k] = v
3377
3378 return res
3379
3380
3381 # Generate rounding modes
3382 cdef __rounding_modes = {
3383 <int> ROUND_NEAREST_TIES_TO_EVEN: "RoundNearestTiesToEven",
3384 <int> ROUND_TOWARD_POSITIVE: "RoundTowardPositive",
3385 <int> ROUND_TOWARD_NEGATIVE: "RoundTowardNegative",
3386 <int> ROUND_TOWARD_ZERO: "RoundTowardZero",
3387 <int> ROUND_NEAREST_TIES_TO_AWAY: "RoundNearestTiesToAway"
3388 }
3389
3390 mod_ref = sys.modules[__name__]
3391 for rm_int, name in __rounding_modes.items():
3392 r = RoundingMode(rm_int)
3393
3394 if name in dir(mod_ref):
3395 raise RuntimeError("Redefinition of Python RoundingMode %s."%name)
3396
3397 setattr(mod_ref, name, r)
3398
3399 del r
3400 del rm_int
3401 del name
3402
3403
3404 # Generate unknown explanations
3405 cdef __unknown_explanations = {
3406 <int> REQUIRES_FULL_CHECK: "RequiresFullCheck",
3407 <int> INCOMPLETE: "Incomplete",
3408 <int> TIMEOUT: "Timeout",
3409 <int> RESOURCEOUT: "Resourceout",
3410 <int> MEMOUT: "Memout",
3411 <int> INTERRUPTED: "Interrupted",
3412 <int> NO_STATUS: "NoStatus",
3413 <int> UNSUPPORTED: "Unsupported",
3414 <int> OTHER: "Other",
3415 <int> UNKNOWN_REASON: "UnknownReason"
3416 }
3417
3418 for ue_int, name in __unknown_explanations.items():
3419 u = UnknownExplanation(ue_int)
3420
3421 if name in dir(mod_ref):
3422 raise RuntimeError("Redefinition of Python UnknownExplanation %s."%name)
3423
3424 setattr(mod_ref, name, u)
3425
3426 del u
3427 del ue_int
3428 del name