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