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