Fix some python docstrings which lead to sphinx warnings (#7293)
[cvc5.git] / src / api / python / cvc5.pxi
1 from collections import defaultdict, Set
2 from fractions import Fraction
3 from functools import wraps
4 import sys
5
6 from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t
7 from libc.stddef cimport wchar_t
8
9 from libcpp.pair cimport pair
10 from libcpp.set cimport set as c_set
11 from libcpp.string cimport string
12 from libcpp.vector cimport vector
13
14 from cvc5 cimport cout
15 from cvc5 cimport Datatype as c_Datatype
16 from cvc5 cimport DatatypeConstructor as c_DatatypeConstructor
17 from cvc5 cimport DatatypeConstructorDecl as c_DatatypeConstructorDecl
18 from cvc5 cimport DatatypeDecl as c_DatatypeDecl
19 from cvc5 cimport DatatypeSelector as c_DatatypeSelector
20 from cvc5 cimport Result as c_Result
21 from cvc5 cimport RoundingMode as c_RoundingMode
22 from cvc5 cimport UnknownExplanation as c_UnknownExplanation
23 from cvc5 cimport Op as c_Op
24 from cvc5 cimport Solver as c_Solver
25 from cvc5 cimport Grammar as c_Grammar
26 from cvc5 cimport Sort as c_Sort
27 from cvc5 cimport ROUND_NEAREST_TIES_TO_EVEN, ROUND_TOWARD_POSITIVE
28 from cvc5 cimport ROUND_TOWARD_NEGATIVE, ROUND_TOWARD_ZERO
29 from cvc5 cimport ROUND_NEAREST_TIES_TO_AWAY
30 from cvc5 cimport REQUIRES_FULL_CHECK, INCOMPLETE, TIMEOUT
31 from cvc5 cimport RESOURCEOUT, MEMOUT, INTERRUPTED
32 from cvc5 cimport NO_STATUS, UNSUPPORTED, UNKNOWN_REASON
33 from cvc5 cimport OTHER
34 from cvc5 cimport Term as c_Term
35 from cvc5 cimport hash as c_hash
36 from cvc5 cimport wstring as c_wstring
37 from cvc5 cimport tuple as c_tuple
38 from cvc5 cimport get0, get1, get2
39 from cvc5kinds cimport Kind as c_Kind
40
41 cdef extern from "Python.h":
42 wchar_t* PyUnicode_AsWideCharString(object, Py_ssize_t *)
43 object PyUnicode_FromWideChar(const wchar_t*, Py_ssize_t)
44 void PyMem_Free(void*)
45
46 ################################## DECORATORS #################################
47 def expand_list_arg(num_req_args=0):
48 """
49 Creates a decorator that looks at index num_req_args of the args,
50 if it's a list, it expands it before calling the function.
51 """
52 def decorator(func):
53 @wraps(func)
54 def wrapper(owner, *args):
55 if len(args) == num_req_args + 1 and \
56 isinstance(args[num_req_args], list):
57 args = list(args[:num_req_args]) + args[num_req_args]
58 return func(owner, *args)
59 return wrapper
60 return decorator
61 ###############################################################################
62
63 # Style Guidelines
64 ### Using PEP-8 spacing recommendations
65 ### Limit linewidth to 79 characters
66 ### Break before binary operators
67 ### surround top level functions and classes with two spaces
68 ### separate methods by one space
69 ### use spaces in functions sparingly to separate logical blocks
70 ### can omit spaces between unrelated oneliners
71 ### always use c++ default arguments
72 #### only use default args of None at python level
73
74 # References and pointers
75 # The Solver object holds a pointer to a c_Solver.
76 # This is because the assignment operator is deleted in the C++ API for solvers.
77 # Cython has a limitation where you can't stack allocate objects
78 # that have constructors with arguments:
79 # https://groups.google.com/forum/#!topic/cython-users/fuKd-nQLpBs.
80 # To get around that you can either have a nullary constructor and assignment
81 # or, use a pointer (which is what we chose).
82 # An additional complication of this is that to free up resources, you must
83 # know when to delete the object.
84 # Python will not follow the same scoping rules as in C++, so it must be
85 # able to reference count. To do this correctly, the solver must be a
86 # reference in the Python class for any class that keeps a pointer to
87 # the solver in C++ (to ensure the solver is not deleted before something
88 # that depends on it).
89
90
91 ## Objects for hashing
92 cdef c_hash[c_Op] cophash = c_hash[c_Op]()
93 cdef c_hash[c_Sort] csorthash = c_hash[c_Sort]()
94 cdef c_hash[c_Term] ctermhash = c_hash[c_Term]()
95
96
97 cdef class Datatype:
98 """Wrapper class for :cpp:class:`cvc5::api::Datatype`."""
99 cdef c_Datatype cd
100 cdef Solver solver
101 def __cinit__(self, Solver solver):
102 self.solver = solver
103
104 def __getitem__(self, index):
105 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
106 if isinstance(index, int) and index >= 0:
107 dc.cdc = self.cd[(<int?> index)]
108 elif isinstance(index, str):
109 dc.cdc = self.cd[(<const string &> index.encode())]
110 else:
111 raise ValueError("Expecting a non-negative integer or string")
112 return dc
113
114 def getConstructor(self, str name):
115 """
116 :param name: the name of the constructor.
117 :return: a constructor by name.
118 """
119 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
120 dc.cdc = self.cd.getConstructor(name.encode())
121 return dc
122
123 def getConstructorTerm(self, str name):
124 """
125 :param name: the name of the constructor.
126 :return: the term representing the datatype constructor with the given name (see :cpp:func:`Datatype::getConstructorTerm() <cvc5::api::Datatype::getConstructorTerm>`).
127 """
128 cdef Term term = Term(self.solver)
129 term.cterm = self.cd.getConstructorTerm(name.encode())
130 return term
131
132 def getSelector(self, str name):
133 """
134 :param name: the name of the selector..
135 :return: a selector by name.
136 """
137 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
138 ds.cds = self.cd.getSelector(name.encode())
139 return ds
140
141 def getName(self):
142 """
143 :return: the name of the datatype.
144 """
145 return self.cd.getName().decode()
146
147 def getNumConstructors(self):
148 """
149 :return: number of constructors in this datatype.
150 """
151 return self.cd.getNumConstructors()
152
153 def isParametric(self):
154 """:return: whether this datatype is parametric."""
155 return self.cd.isParametric()
156
157 def isCodatatype(self):
158 """:return: whether this datatype corresponds to a co-datatype."""
159 return self.cd.isCodatatype()
160
161 def isTuple(self):
162 """:return: whether this datatype corresponds to a tuple."""
163 return self.cd.isTuple()
164
165 def isRecord(self):
166 """:return: whether this datatype corresponds to a record."""
167 return self.cd.isRecord()
168
169 def isFinite(self):
170 """:return: whether this datatype is finite."""
171 return self.cd.isFinite()
172
173 def isWellFounded(self):
174 """:return: whether this datatype is well-founded (see :cpp:func:`Datatype::isWellFounded() <cvc5::api::Datatype::isWellFounded>`)."""
175 return self.cd.isWellFounded()
176
177 def hasNestedRecursion(self):
178 """:return: whether this datatype has nested recursion (see :cpp:func:`Datatype::hasNestedRecursion() <cvc5::api::Datatype::hasNestedRecursion>`)."""
179 return self.cd.hasNestedRecursion()
180
181 def isNull(self):
182 return self.cd.isNull()
183
184 def __str__(self):
185 return self.cd.toString().decode()
186
187 def __repr__(self):
188 return self.cd.toString().decode()
189
190 def __iter__(self):
191 for ci in self.cd:
192 dc = DatatypeConstructor(self.solver)
193 dc.cdc = ci
194 yield dc
195
196
197 cdef class DatatypeConstructor:
198 """Wrapper class for :cpp:class:`cvc5::api::DatatypeConstructor`."""
199 cdef c_DatatypeConstructor cdc
200 cdef Solver solver
201 def __cinit__(self, Solver solver):
202 self.cdc = c_DatatypeConstructor()
203 self.solver = solver
204
205 def __getitem__(self, index):
206 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
207 if isinstance(index, int) and index >= 0:
208 ds.cds = self.cdc[(<int?> index)]
209 elif isinstance(index, str):
210 ds.cds = self.cdc[(<const string &> index.encode())]
211 else:
212 raise ValueError("Expecting a non-negative integer or string")
213 return ds
214
215 def getName(self):
216 """
217 :return: the name of the constructor.
218 """
219 return self.cdc.getName().decode()
220
221 def getConstructorTerm(self):
222 """
223 :return: the constructor operator as a term.
224 """
225 cdef Term term = Term(self.solver)
226 term.cterm = self.cdc.getConstructorTerm()
227 return term
228
229 def getSpecializedConstructorTerm(self, Sort retSort):
230 """
231 Specialized method for parametric datatypes (see :cpp:func:`DatatypeConstructor::getSpecializedConstructorTerm() <cvc5::api::DatatypeConstructor::getSpecializedConstructorTerm>`).
232
233 :param retSort: the desired return sort of the constructor
234 :return: the constructor operator as a term.
235 """
236 cdef Term term = Term(self.solver)
237 term.cterm = self.cdc.getSpecializedConstructorTerm(retSort.csort)
238 return term
239
240 def getTesterTerm(self):
241 """
242 :return: the tester operator that is related to this constructor, as a term.
243 """
244 cdef Term term = Term(self.solver)
245 term.cterm = self.cdc.getTesterTerm()
246 return term
247
248 def getNumSelectors(self):
249 """
250 :return: the number of selecters (so far) of this Datatype constructor.
251 """
252 return self.cdc.getNumSelectors()
253
254 def getSelector(self, str name):
255 """
256 :param name: the name of the datatype selector.
257 :return: the first datatype selector with the given name
258 """
259 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
260 ds.cds = self.cdc.getSelector(name.encode())
261 return ds
262
263 def getSelectorTerm(self, str name):
264 """
265 :param name: the name of the datatype selector.
266 :return: a term representing the firstdatatype selector with the given name.
267 """
268 cdef Term term = Term(self.solver)
269 term.cterm = self.cdc.getSelectorTerm(name.encode())
270 return term
271
272 def isNull(self):
273 return self.cdc.isNull()
274
275 def __str__(self):
276 return self.cdc.toString().decode()
277
278 def __repr__(self):
279 return self.cdc.toString().decode()
280
281 def __iter__(self):
282 for ci in self.cdc:
283 ds = DatatypeSelector(self.solver)
284 ds.cds = ci
285 yield ds
286
287
288 cdef class DatatypeConstructorDecl:
289 """Wrapper class for :cpp:class:`cvc5::api::DatatypeConstructorDecl`."""
290 cdef c_DatatypeConstructorDecl cddc
291 cdef Solver solver
292
293 def __cinit__(self, Solver solver):
294 self.solver = solver
295
296 def addSelector(self, str name, Sort sort):
297 """
298 Add datatype selector declaration.
299
300 :param name: the name of the datatype selector declaration to add.
301 :param sort: the range sort of the datatype selector declaration to add.
302 """
303 self.cddc.addSelector(name.encode(), sort.csort)
304
305 def addSelectorSelf(self, str name):
306 """
307 Add datatype selector declaration whose range sort is the datatype itself.
308
309 :param name: the name of the datatype selector declaration to add.
310 """
311 self.cddc.addSelectorSelf(name.encode())
312
313 def isNull(self):
314 return self.cddc.isNull()
315
316 def __str__(self):
317 return self.cddc.toString().decode()
318
319 def __repr__(self):
320 return self.cddc.toString().decode()
321
322
323 cdef class DatatypeDecl:
324 """Wrapper class for :cpp:class:`cvc5::api::DatatypeDecl`."""
325 cdef c_DatatypeDecl cdd
326 cdef Solver solver
327 def __cinit__(self, Solver solver):
328 self.solver = solver
329
330 def addConstructor(self, DatatypeConstructorDecl ctor):
331 """
332 Add a datatype constructor declaration.
333
334 :param ctor: the datatype constructor declaration to add.
335 """
336 self.cdd.addConstructor(ctor.cddc)
337
338 def getNumConstructors(self):
339 """
340 :return: number of constructors (so far) for this datatype declaration.
341 """
342 return self.cdd.getNumConstructors()
343
344 def isParametric(self):
345 """
346 :return: is this datatype declaration parametric?
347 """
348 return self.cdd.isParametric()
349
350 def getName(self):
351 """
352 :return: the name of this datatype declaration.
353 """
354 return self.cdd.getName().decode()
355
356 def isNull(self):
357 return self.cdd.isNull()
358
359 def __str__(self):
360 return self.cdd.toString().decode()
361
362 def __repr__(self):
363 return self.cdd.toString().decode()
364
365
366 cdef class DatatypeSelector:
367 """Wrapper class for :cpp:class:`cvc5::api::DatatypeSelector`."""
368 cdef c_DatatypeSelector cds
369 cdef Solver solver
370 def __cinit__(self, Solver solver):
371 self.cds = c_DatatypeSelector()
372 self.solver = solver
373
374 def getName(self):
375 """
376 :return: the name of this datatype selector.
377 """
378 return self.cds.getName().decode()
379
380 def getSelectorTerm(self):
381 """
382 :return: the selector opeartor of this datatype selector as a term.
383 """
384 cdef Term term = Term(self.solver)
385 term.cterm = self.cds.getSelectorTerm()
386 return term
387
388 def getUpdaterTerm(self):
389 """
390 :return: the updater opeartor of this datatype selector as a term.
391 """
392 cdef Term term = Term(self.solver)
393 term.cterm = self.cds.getUpdaterTerm()
394 return term
395
396 def getRangeSort(self):
397 """
398 :return: the range sort of this selector.
399 """
400 cdef Sort sort = Sort(self.solver)
401 sort.csort = self.cds.getRangeSort()
402 return sort
403
404 def isNull(self):
405 return self.cds.isNull()
406
407 def __str__(self):
408 return self.cds.toString().decode()
409
410 def __repr__(self):
411 return self.cds.toString().decode()
412
413
414 cdef class Op:
415 cdef c_Op cop
416 cdef Solver solver
417 def __cinit__(self, Solver solver):
418 self.cop = c_Op()
419 self.solver = solver
420
421 def __eq__(self, Op other):
422 return self.cop == other.cop
423
424 def __ne__(self, Op other):
425 return self.cop != other.cop
426
427 def __str__(self):
428 return self.cop.toString().decode()
429
430 def __repr__(self):
431 return self.cop.toString().decode()
432
433 def __hash__(self):
434 return cophash(self.cop)
435
436 def getKind(self):
437 return kind(<int> self.cop.getKind())
438
439 def isIndexed(self):
440 return self.cop.isIndexed()
441
442 def isNull(self):
443 return self.cop.isNull()
444
445 def getNumIndices(self):
446 return self.cop.getNumIndices()
447
448 def getIndices(self):
449 indices = None
450 try:
451 indices = self.cop.getIndices[string]().decode()
452 except:
453 pass
454
455 try:
456 indices = self.cop.getIndices[uint32_t]()
457 except:
458 pass
459
460 try:
461 indices = self.cop.getIndices[pair[uint32_t, uint32_t]]()
462 except:
463 pass
464
465 if indices is None:
466 raise RuntimeError("Unable to retrieve indices from {}".format(self))
467
468 return indices
469
470 cdef class Grammar:
471 cdef c_Grammar cgrammar
472 cdef Solver solver
473 def __cinit__(self, Solver solver):
474 self.solver = solver
475 self.cgrammar = c_Grammar()
476
477 def addRule(self, Term ntSymbol, Term rule):
478 self.cgrammar.addRule(ntSymbol.cterm, rule.cterm)
479
480 def addAnyConstant(self, Term ntSymbol):
481 self.cgrammar.addAnyConstant(ntSymbol.cterm)
482
483 def addAnyVariable(self, Term ntSymbol):
484 self.cgrammar.addAnyVariable(ntSymbol.cterm)
485
486 def addRules(self, Term ntSymbol, rules):
487 cdef vector[c_Term] crules
488 for r in rules:
489 crules.push_back((<Term?> r).cterm)
490 self.cgrammar.addRules(ntSymbol.cterm, crules)
491
492 cdef class Result:
493 cdef c_Result cr
494 def __cinit__(self):
495 # gets populated by solver
496 self.cr = c_Result()
497
498 def isNull(self):
499 return self.cr.isNull()
500
501 def isSat(self):
502 return self.cr.isSat()
503
504 def isUnsat(self):
505 return self.cr.isUnsat()
506
507 def isSatUnknown(self):
508 return self.cr.isSatUnknown()
509
510 def isEntailed(self):
511 return self.cr.isEntailed()
512
513 def isNotEntailed(self):
514 return self.cr.isNotEntailed()
515
516 def isEntailmentUnknown(self):
517 return self.cr.isEntailmentUnknown()
518
519 def __eq__(self, Result other):
520 return self.cr == other.cr
521
522 def __ne__(self, Result other):
523 return self.cr != other.cr
524
525 def getUnknownExplanation(self):
526 return UnknownExplanation(<int> self.cr.getUnknownExplanation())
527
528 def __str__(self):
529 return self.cr.toString().decode()
530
531 def __repr__(self):
532 return self.cr.toString().decode()
533
534
535 cdef class RoundingMode:
536 cdef c_RoundingMode crm
537 cdef str name
538 def __cinit__(self, int rm):
539 # crm always assigned externally
540 self.crm = <c_RoundingMode> rm
541 self.name = __rounding_modes[rm]
542
543 def __eq__(self, RoundingMode other):
544 return (<int> self.crm) == (<int> other.crm)
545
546 def __ne__(self, RoundingMode other):
547 return not self.__eq__(other)
548
549 def __hash__(self):
550 return hash((<int> self.crm, self.name))
551
552 def __str__(self):
553 return self.name
554
555 def __repr__(self):
556 return self.name
557
558
559 cdef class UnknownExplanation:
560 cdef c_UnknownExplanation cue
561 cdef str name
562 def __cinit__(self, int ue):
563 # crm always assigned externally
564 self.cue = <c_UnknownExplanation> ue
565 self.name = __unknown_explanations[ue]
566
567 def __eq__(self, UnknownExplanation other):
568 return (<int> self.cue) == (<int> other.cue)
569
570 def __ne__(self, UnknownExplanation other):
571 return not self.__eq__(other)
572
573 def __hash__(self):
574 return hash((<int> self.crm, self.name))
575
576 def __str__(self):
577 return self.name
578
579 def __repr__(self):
580 return self.name
581
582
583 cdef class Solver:
584 """Wrapper class for :cpp:class:`cvc5::api::Solver`."""
585 cdef c_Solver* csolver
586
587 def __cinit__(self):
588 self.csolver = new c_Solver()
589
590 def __dealloc__(self):
591 del self.csolver
592
593 def getBooleanSort(self):
594 """:return: sort Boolean
595 """
596 cdef Sort sort = Sort(self)
597 sort.csort = self.csolver.getBooleanSort()
598 return sort
599
600 def getIntegerSort(self):
601 """:return: sort Integer
602 """
603 cdef Sort sort = Sort(self)
604 sort.csort = self.csolver.getIntegerSort()
605 return sort
606
607 def getNullSort(self):
608 """:return: sort null
609 """
610 cdef Sort sort = Sort(self)
611 sort.csort = self.csolver.getNullSort()
612 return sort
613
614 def getRealSort(self):
615 """:return: sort Real
616 """
617 cdef Sort sort = Sort(self)
618 sort.csort = self.csolver.getRealSort()
619 return sort
620
621 def getRegExpSort(self):
622 """:return: sort of RegExp
623 """
624 cdef Sort sort = Sort(self)
625 sort.csort = self.csolver.getRegExpSort()
626 return sort
627
628 def getRoundingModeSort(self):
629 """:return: sort RoundingMode
630 """
631 cdef Sort sort = Sort(self)
632 sort.csort = self.csolver.getRoundingModeSort()
633 return sort
634
635 def getStringSort(self):
636 """:return: sort String
637 """
638 cdef Sort sort = Sort(self)
639 sort.csort = self.csolver.getStringSort()
640 return sort
641
642 def mkArraySort(self, Sort indexSort, Sort elemSort):
643 """Create an array sort.
644
645 :param indexSort: the array index sort
646 :param elemSort: the array element sort
647 :return: the array sort
648 """
649 cdef Sort sort = Sort(self)
650 sort.csort = self.csolver.mkArraySort(indexSort.csort, elemSort.csort)
651 return sort
652
653 def mkBitVectorSort(self, uint32_t size):
654 """Create a bit-vector sort.
655
656 :param size: the bit-width of the bit-vector sort
657 :return: the bit-vector sort
658 """
659 cdef Sort sort = Sort(self)
660 sort.csort = self.csolver.mkBitVectorSort(size)
661 return sort
662
663 def mkFloatingPointSort(self, uint32_t exp, uint32_t sig):
664 """Create a floating-point sort.
665
666 :param exp: the bit-width of the exponent of the floating-point sort.
667 :param sig: the bit-width of the significand of the floating-point sort.
668 """
669 cdef Sort sort = Sort(self)
670 sort.csort = self.csolver.mkFloatingPointSort(exp, sig)
671 return sort
672
673 def mkDatatypeSort(self, DatatypeDecl dtypedecl):
674 """Create a datatype sort.
675
676 :param dtypedecl: the datatype declaration from which the sort is created
677 :return: the datatype sort
678 """
679 cdef Sort sort = Sort(self)
680 sort.csort = self.csolver.mkDatatypeSort(dtypedecl.cdd)
681 return sort
682
683 def mkDatatypeSorts(self, list dtypedecls, unresolvedSorts = None):
684 """
685 Create a vector of datatype sorts using unresolved sorts. The names of
686 the datatype declarations in dtypedecls must be distinct.
687
688 This method is called when the DatatypeDecl objects dtypedecls have been
689 built using "unresolved" sorts.
690
691 We associate each sort in unresolvedSorts with exacly one datatype from
692 dtypedecls. In particular, it must have the same name as exactly one
693 datatype declaration in dtypedecls.
694
695 When constructing datatypes, unresolved sorts are replaced by the datatype
696 sort constructed for the datatype declaration it is associated with.
697
698 :param dtypedecls: the datatype declarations from which the sort is created
699 :param unresolvedSorts: the list of unresolved sorts
700 :return: the datatype sorts
701 """
702 if unresolvedSorts == None:
703 unresolvedSorts = set([])
704 else:
705 assert isinstance(unresolvedSorts, Set)
706
707 sorts = []
708 cdef vector[c_DatatypeDecl] decls
709 for decl in dtypedecls:
710 decls.push_back((<DatatypeDecl?> decl).cdd)
711
712 cdef c_set[c_Sort] usorts
713 for usort in unresolvedSorts:
714 usorts.insert((<Sort?> usort).csort)
715
716 csorts = self.csolver.mkDatatypeSorts(
717 <const vector[c_DatatypeDecl]&> decls, <const c_set[c_Sort]&> usorts)
718 for csort in csorts:
719 sort = Sort(self)
720 sort.csort = csort
721 sorts.append(sort)
722
723 return sorts
724
725 def mkFunctionSort(self, sorts, Sort codomain):
726 """ Create function sort.
727
728 :param sorts: the sort of the function arguments
729 :param codomain: the sort of the function return value
730 :return: the function sort
731 """
732
733 cdef Sort sort = Sort(self)
734 # populate a vector with dereferenced c_Sorts
735 cdef vector[c_Sort] v
736
737 if isinstance(sorts, Sort):
738 sort.csort = self.csolver.mkFunctionSort((<Sort?> sorts).csort,
739 codomain.csort)
740 elif isinstance(sorts, list):
741 for s in sorts:
742 v.push_back((<Sort?>s).csort)
743
744 sort.csort = self.csolver.mkFunctionSort(<const vector[c_Sort]&> v,
745 codomain.csort)
746 return sort
747
748 def mkParamSort(self, symbolname):
749 """ Create a sort parameter.
750
751 :param symbol: the name of the sort
752 :return: the sort parameter
753 """
754 cdef Sort sort = Sort(self)
755 sort.csort = self.csolver.mkParamSort(symbolname.encode())
756 return sort
757
758 @expand_list_arg(num_req_args=0)
759 def mkPredicateSort(self, *sorts):
760 """Create a predicate sort.
761
762 :param sorts: the list of sorts of the predicate, as a list or as distinct arguments.
763 :return: the predicate sort
764 """
765 cdef Sort sort = Sort(self)
766 cdef vector[c_Sort] v
767 for s in sorts:
768 v.push_back((<Sort?> s).csort)
769 sort.csort = self.csolver.mkPredicateSort(<const vector[c_Sort]&> v)
770 return sort
771
772 @expand_list_arg(num_req_args=0)
773 def mkRecordSort(self, *fields):
774 """Create a record sort
775
776 :param fields: the list of fields of the record, as a list or as distinct arguments
777 :return: the record sort
778 """
779 cdef Sort sort = Sort(self)
780 cdef vector[pair[string, c_Sort]] v
781 cdef pair[string, c_Sort] p
782 for f in fields:
783 name, sortarg = f
784 name = name.encode()
785 p = pair[string, c_Sort](<string?> name, (<Sort?> sortarg).csort)
786 v.push_back(p)
787 sort.csort = self.csolver.mkRecordSort(
788 <const vector[pair[string, c_Sort]] &> v)
789 return sort
790
791 def mkSetSort(self, Sort elemSort):
792 """Create a set sort.
793
794 :param elemSort: the sort of the set elements
795 :return: the set sort
796 """
797 cdef Sort sort = Sort(self)
798 sort.csort = self.csolver.mkSetSort(elemSort.csort)
799 return sort
800
801 def mkBagSort(self, Sort elemSort):
802 """Create a bag sort.
803
804 :param elemSort: the sort of the bag elements
805 :return: the bag sort
806 """
807 cdef Sort sort = Sort(self)
808 sort.csort = self.csolver.mkBagSort(elemSort.csort)
809 return sort
810
811 def mkSequenceSort(self, Sort elemSort):
812 """Create a sequence sort.
813
814 :param elemSort: the sort of the sequence elements
815 :return: the sequence sort
816 """
817 cdef Sort sort = Sort(self)
818 sort.csort = self.csolver.mkSequenceSort(elemSort.csort)
819 return sort
820
821 def mkUninterpretedSort(self, str name):
822 """Create an uninterpreted sort.
823
824 :param symbol: the name of the sort
825 :return: the uninterpreted sort
826 """
827 cdef Sort sort = Sort(self)
828 sort.csort = self.csolver.mkUninterpretedSort(name.encode())
829 return sort
830
831 def mkSortConstructorSort(self, str symbol, size_t arity):
832 """Create a sort constructor sort.
833
834 :param symbol: the symbol of the sort
835 :param arity: the arity of the sort
836 :return: the sort constructor sort
837 """
838 cdef Sort sort = Sort(self)
839 sort.csort =self.csolver.mkSortConstructorSort(symbol.encode(), arity)
840 return sort
841
842 @expand_list_arg(num_req_args=0)
843 def mkTupleSort(self, *sorts):
844 """Create a tuple sort.
845
846 :param sorts: of the elements of the tuple, as a list or as distinct arguments
847 :return: the tuple sort
848 """
849 cdef Sort sort = Sort(self)
850 cdef vector[c_Sort] v
851 for s in sorts:
852 v.push_back((<Sort?> s).csort)
853 sort.csort = self.csolver.mkTupleSort(v)
854 return sort
855
856 @expand_list_arg(num_req_args=1)
857 def mkTerm(self, kind_or_op, *args):
858 """
859 Supports the following arguments:
860
861 - ``Term mkTerm(Kind kind)``
862 - ``Term mkTerm(Kind kind, Op child1, List[Term] children)``
863 - ``Term mkTerm(Kind kind, List[Term] children)``
864
865 where ``List[Term]`` can also be comma-separated arguments
866 """
867 cdef Term term = Term(self)
868 cdef vector[c_Term] v
869
870 op = kind_or_op
871 if isinstance(kind_or_op, kind):
872 op = self.mkOp(kind_or_op)
873
874 if len(args) == 0:
875 term.cterm = self.csolver.mkTerm((<Op?> op).cop)
876 else:
877 for a in args:
878 v.push_back((<Term?> a).cterm)
879 term.cterm = self.csolver.mkTerm((<Op?> op).cop, v)
880 return term
881
882 def mkTuple(self, sorts, terms):
883 """Create a tuple term. Terms are automatically converted if sorts are compatible.
884
885 :param sorts: The sorts of the elements in the tuple
886 :param terms: The elements in the tuple
887 :return: the tuple Term
888 """
889 cdef vector[c_Sort] csorts
890 cdef vector[c_Term] cterms
891
892 for s in sorts:
893 csorts.push_back((<Sort?> s).csort)
894 for s in terms:
895 cterms.push_back((<Term?> s).cterm)
896 cdef Term result = Term(self)
897 result.cterm = self.csolver.mkTuple(csorts, cterms)
898 return result
899
900 @expand_list_arg(num_req_args=0)
901 def mkOp(self, kind k, *args):
902 """
903 Supports the following uses:
904
905 - ``Op mkOp(Kind kind)``
906 - ``Op mkOp(Kind kind, Kind k)``
907 - ``Op mkOp(Kind kind, const string& arg)``
908 - ``Op mkOp(Kind kind, uint32_t arg)``
909 - ``Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1)``
910 """
911 cdef Op op = Op(self)
912 cdef vector[int] v
913
914 if len(args) == 0:
915 op.cop = self.csolver.mkOp(k.k)
916 elif len(args) == 1:
917 if isinstance(args[0], str):
918 op.cop = self.csolver.mkOp(k.k,
919 <const string &>
920 args[0].encode())
921 elif isinstance(args[0], int):
922 op.cop = self.csolver.mkOp(k.k, <int?> args[0])
923 elif isinstance(args[0], list):
924 for a in args[0]:
925 v.push_back((<int?> a))
926 op.cop = self.csolver.mkOp(k.k, <const vector[uint32_t]&> v)
927 else:
928 raise ValueError("Unsupported signature"
929 " mkOp: {}".format(" X ".join([str(k), str(args[0])])))
930 elif len(args) == 2:
931 if isinstance(args[0], int) and isinstance(args[1], int):
932 op.cop = self.csolver.mkOp(k.k, <int> args[0], <int> args[1])
933 else:
934 raise ValueError("Unsupported signature"
935 " mkOp: {}".format(" X ".join([k, args[0], args[1]])))
936 return op
937
938 def mkTrue(self):
939 """Create a Boolean true constant.
940
941 :return: the true constant
942 """
943 cdef Term term = Term(self)
944 term.cterm = self.csolver.mkTrue()
945 return term
946
947 def mkFalse(self):
948 """Create a Boolean false constant.
949
950 :return: the false constant
951 """
952 cdef Term term = Term(self)
953 term.cterm = self.csolver.mkFalse()
954 return term
955
956 def mkBoolean(self, bint val):
957 """Create a Boolean constant.
958
959 :return: the Boolean constant
960 :param val: the value of the constant
961 """
962 cdef Term term = Term(self)
963 term.cterm = self.csolver.mkBoolean(val)
964 return term
965
966 def mkPi(self):
967 """Create a constant representing the number Pi.
968
969 :return: a constant representing Pi
970 """
971 cdef Term term = Term(self)
972 term.cterm = self.csolver.mkPi()
973 return term
974
975 def mkInteger(self, val):
976 """Create an integer constant.
977
978 :param val: representation of the constant: either a string or integer
979 :return: a constant of sort Integer
980 """
981 cdef Term term = Term(self)
982 if isinstance(val, str):
983 term.cterm = self.csolver.mkInteger(<const string &> str(val).encode())
984 else:
985 assert(isinstance(val, int))
986 term.cterm = self.csolver.mkInteger((<int?> val))
987 return term
988
989 def mkReal(self, val, den=None):
990 """Create a real constant.
991
992 :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.
993 :param: `den` if not None, the value is `val`/`den`
994 :return: a real term with literal value
995
996 Can be used in various forms:
997
998 - Given a string ``"N/D"`` constructs the corresponding rational.
999 - Given a string ``"W.D"`` constructs the reduction of ``(W * P + D)/P``, where ``P`` is the appropriate power of 10.
1000 - 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``.
1001 - Given a string ``"W"`` or an integer, constructs that integer.
1002 - Given two strings and/or integers ``N`` and ``D``, constructs ``N/D``.
1003 """
1004 cdef Term term = Term(self)
1005 if den is None:
1006 term.cterm = self.csolver.mkReal(str(val).encode())
1007 else:
1008 if not isinstance(val, int) or not isinstance(den, int):
1009 raise ValueError("Expecting integers when"
1010 " constructing a rational"
1011 " but got: {}".format((val, den)))
1012 term.cterm = self.csolver.mkReal("{}/{}".format(val, den).encode())
1013 return term
1014
1015 def mkRegexpEmpty(self):
1016 """Create a regular expression empty term.
1017
1018 :return: the empty term
1019 """
1020 cdef Term term = Term(self)
1021 term.cterm = self.csolver.mkRegexpEmpty()
1022 return term
1023
1024 def mkRegexpSigma(self):
1025 """Create a regular expression sigma term.
1026
1027 :return: the sigma term
1028 """
1029 cdef Term term = Term(self)
1030 term.cterm = self.csolver.mkRegexpSigma()
1031 return term
1032
1033 def mkEmptySet(self, Sort s):
1034 """Create a constant representing an empty set of the given sort.
1035
1036 :param sort: the sort of the set elements.
1037 :return: the empty set constant
1038 """
1039 cdef Term term = Term(self)
1040 term.cterm = self.csolver.mkEmptySet(s.csort)
1041 return term
1042
1043 def mkEmptyBag(self, Sort s):
1044 """Create a constant representing an empty bag of the given sort.
1045
1046 :param sort: the sort of the bag elements.
1047 :return: the empty bag constant
1048 """
1049 cdef Term term = Term(self)
1050 term.cterm = self.csolver.mkEmptyBag(s.csort)
1051 return term
1052
1053 def mkSepNil(self, Sort sort):
1054 """Create a separation logic nil term.
1055
1056 :param sort: the sort of the nil term
1057 :return: the separation logic nil term
1058 """
1059 cdef Term term = Term(self)
1060 term.cterm = self.csolver.mkSepNil(sort.csort)
1061 return term
1062
1063 def mkString(self, str s, useEscSequences = None):
1064 """
1065 Create a String constant from a `str` which may contain SMT-LIB
1066 compatible escape sequences like ``\\u1234`` to encode unicode characters.
1067
1068 :param s: the string this constant represents
1069 :param useEscSequences: determines whether escape sequences in `s` should be converted to the corresponding unicode character
1070 :return: the String constant
1071 """
1072 cdef Term term = Term(self)
1073 cdef Py_ssize_t size
1074 cdef wchar_t* tmp = PyUnicode_AsWideCharString(s, &size)
1075 if isinstance(useEscSequences, bool):
1076 term.cterm = self.csolver.mkString(
1077 s.encode(), <bint> useEscSequences)
1078 else:
1079 term.cterm = self.csolver.mkString(c_wstring(tmp, size))
1080 PyMem_Free(tmp)
1081 return term
1082
1083 def mkEmptySequence(self, Sort sort):
1084 """Create an empty sequence of the given element sort.
1085
1086 :param sort: The element sort of the sequence.
1087 :return: the empty sequence with given element sort.
1088 """
1089 cdef Term term = Term(self)
1090 term.cterm = self.csolver.mkEmptySequence(sort.csort)
1091 return term
1092
1093 def mkUniverseSet(self, Sort sort):
1094 """Create a universe set of the given sort.
1095
1096 :param sort: the sort of the set elements
1097 :return: the universe set constant
1098 """
1099 cdef Term term = Term(self)
1100 term.cterm = self.csolver.mkUniverseSet(sort.csort)
1101 return term
1102
1103 @expand_list_arg(num_req_args=0)
1104 def mkBitVector(self, *args):
1105 """
1106 Supports the following arguments:
1107
1108 - ``Term mkBitVector(int size, int val=0)``
1109 - ``Term mkBitVector(int size, string val, int base)``
1110
1111 :return: a bit-vector literal term
1112 :param: `size` an integer size.
1113 :param: `val` an integer representating the value, in the first form. In the second form, a string representing the value.
1114 :param: `base` the base of the string representation (second form only)
1115 """
1116 cdef Term term = Term(self)
1117 if len(args) == 0:
1118 raise ValueError("Missing arguments to mkBitVector")
1119 size = args[0]
1120 if not isinstance(size, int):
1121 raise ValueError(
1122 "Invalid first argument to mkBitVector '{}', "
1123 "expected bit-vector size".format(size))
1124 if len(args) == 1:
1125 term.cterm = self.csolver.mkBitVector(<uint32_t> size)
1126 elif len(args) == 2:
1127 val = args[1]
1128 if not isinstance(val, int):
1129 raise ValueError(
1130 "Invalid second argument to mkBitVector '{}', "
1131 "expected integer value".format(size))
1132 term.cterm = self.csolver.mkBitVector(
1133 <uint32_t> size, <uint32_t> val)
1134 elif len(args) == 3:
1135 val = args[1]
1136 base = args[2]
1137 if not isinstance(val, str):
1138 raise ValueError(
1139 "Invalid second argument to mkBitVector '{}', "
1140 "expected value string".format(size))
1141 if not isinstance(base, int):
1142 raise ValueError(
1143 "Invalid third argument to mkBitVector '{}', "
1144 "expected base given as integer".format(size))
1145 term.cterm = self.csolver.mkBitVector(
1146 <uint32_t> size,
1147 <const string&> str(val).encode(),
1148 <uint32_t> base)
1149 else:
1150 raise ValueError("Unexpected inputs to mkBitVector")
1151 return term
1152
1153 def mkConstArray(self, Sort sort, Term val):
1154 """
1155 Create a constant array with the provided constant value stored at every
1156 index
1157
1158 :param sort: the sort of the constant array (must be an array sort)
1159 :param val: the constant value to store (must match the sort's element sort)
1160 :return: the constant array term
1161 """
1162 cdef Term term = Term(self)
1163 term.cterm = self.csolver.mkConstArray(sort.csort, val.cterm)
1164 return term
1165
1166 def mkPosInf(self, int exp, int sig):
1167 """Create a positive infinity floating-point constant.
1168
1169 :param exp: Number of bits in the exponent
1170 :param sig: Number of bits in the significand
1171 :return: the floating-point constant
1172 """
1173 cdef Term term = Term(self)
1174 term.cterm = self.csolver.mkPosInf(exp, sig)
1175 return term
1176
1177 def mkNegInf(self, int exp, int sig):
1178 """Create a negative infinity floating-point constant.
1179
1180 :param exp: Number of bits in the exponent
1181 :param sig: Number of bits in the significand
1182 :return: the floating-point constant
1183 """
1184 cdef Term term = Term(self)
1185 term.cterm = self.csolver.mkNegInf(exp, sig)
1186 return term
1187
1188 def mkNaN(self, int exp, int sig):
1189 """Create a not-a-number (NaN) floating-point constant.
1190
1191 :param exp: Number of bits in the exponent
1192 :param sig: Number of bits in the significand
1193 :return: the floating-point constant
1194 """
1195 cdef Term term = Term(self)
1196 term.cterm = self.csolver.mkNaN(exp, sig)
1197 return term
1198
1199 def mkPosZero(self, int exp, int sig):
1200 """Create a positive zero (+0.0) floating-point constant.
1201
1202 :param exp: Number of bits in the exponent
1203 :param sig: Number of bits in the significand
1204 :return: the floating-point constant
1205 """
1206 cdef Term term = Term(self)
1207 term.cterm = self.csolver.mkPosZero(exp, sig)
1208 return term
1209
1210 def mkNegZero(self, int exp, int sig):
1211 """Create a negative zero (+0.0) floating-point constant.
1212
1213 :param exp: Number of bits in the exponent
1214 :param sig: Number of bits in the significand
1215 :return: the floating-point constant
1216 """
1217 cdef Term term = Term(self)
1218 term.cterm = self.csolver.mkNegZero(exp, sig)
1219 return term
1220
1221 def mkRoundingMode(self, RoundingMode rm):
1222 """Create a roundingmode constant.
1223
1224 :param rm: the floating point rounding mode this constant represents
1225 """
1226 cdef Term term = Term(self)
1227 term.cterm = self.csolver.mkRoundingMode(<c_RoundingMode> rm.crm)
1228 return term
1229
1230 def mkUninterpretedConst(self, Sort sort, int index):
1231 """Create uninterpreted constant.
1232
1233 :param sort: Sort of the constant
1234 :param index: Index of the constant
1235 """
1236 cdef Term term = Term(self)
1237 term.cterm = self.csolver.mkUninterpretedConst(sort.csort, index)
1238 return term
1239
1240 def mkAbstractValue(self, index):
1241 """
1242 Create an abstract value constant.
1243 The given index needs to be positive.
1244
1245 :param index: Index of the abstract value
1246 """
1247 cdef Term term = Term(self)
1248 try:
1249 term.cterm = self.csolver.mkAbstractValue(str(index).encode())
1250 except:
1251 raise ValueError(
1252 "mkAbstractValue expects a str representing a number"
1253 " or an int, but got{}".format(index))
1254 return term
1255
1256 def mkFloatingPoint(self, int exp, int sig, Term val):
1257 """Create a floating-point constant.
1258
1259 :param exp: Size of the exponent
1260 :param sig: Size of the significand
1261 :param val: Value of the floating-point constant as a bit-vector term
1262 """
1263 cdef Term term = Term(self)
1264 term.cterm = self.csolver.mkFloatingPoint(exp, sig, val.cterm)
1265 return term
1266
1267 def mkConst(self, Sort sort, symbol=None):
1268 """
1269 Create (first-order) constant (0-arity function symbol).
1270
1271 SMT-LIB:
1272
1273 .. code-block:: smtlib
1274
1275 ( declare-const <symbol> <sort> )
1276 ( declare-fun <symbol> ( ) <sort> )
1277
1278 :param sort: the sort of the constant
1279 :param symbol: the name of the constant. If None, a default symbol is used.
1280 :return: the first-order constant
1281 """
1282 cdef Term term = Term(self)
1283 if symbol is None:
1284 term.cterm = self.csolver.mkConst(sort.csort)
1285 else:
1286 term.cterm = self.csolver.mkConst(sort.csort,
1287 (<str?> symbol).encode())
1288 return term
1289
1290 def mkVar(self, Sort sort, symbol=None):
1291 """
1292 Create a bound variable to be used in a binder (i.e. a quantifier, a
1293 lambda, or a witness binder).
1294
1295 :param sort: the sort of the variable
1296 :param symbol: the name of the variable
1297 :return: the variable
1298 """
1299 cdef Term term = Term(self)
1300 if symbol is None:
1301 term.cterm = self.csolver.mkVar(sort.csort)
1302 else:
1303 term.cterm = self.csolver.mkVar(sort.csort,
1304 (<str?> symbol).encode())
1305 return term
1306
1307 def mkDatatypeConstructorDecl(self, str name):
1308 """
1309 :return: a datatype constructor declaration
1310 :param: `name` the constructor's name
1311 """
1312 cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl(self)
1313 ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
1314 return ddc
1315
1316 def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
1317 """Create a datatype declaration.
1318
1319 :param name: the name of the datatype
1320 :param isCoDatatype: true if a codatatype is to be constructed
1321 :return: the DatatypeDecl
1322 """
1323 cdef DatatypeDecl dd = DatatypeDecl(self)
1324 cdef vector[c_Sort] v
1325
1326 # argument cases
1327 if sorts_or_bool is None and isCoDatatype is None:
1328 dd.cdd = self.csolver.mkDatatypeDecl(name.encode())
1329 elif sorts_or_bool is not None and isCoDatatype is None:
1330 if isinstance(sorts_or_bool, bool):
1331 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1332 <bint> sorts_or_bool)
1333 elif isinstance(sorts_or_bool, Sort):
1334 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1335 (<Sort> sorts_or_bool).csort)
1336 elif isinstance(sorts_or_bool, list):
1337 for s in sorts_or_bool:
1338 v.push_back((<Sort?> s).csort)
1339 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1340 <const vector[c_Sort]&> v)
1341 else:
1342 raise ValueError("Unhandled second argument type {}"
1343 .format(type(sorts_or_bool)))
1344 elif sorts_or_bool is not None and isCoDatatype is not None:
1345 if isinstance(sorts_or_bool, Sort):
1346 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1347 (<Sort> sorts_or_bool).csort,
1348 <bint> isCoDatatype)
1349 elif isinstance(sorts_or_bool, list):
1350 for s in sorts_or_bool:
1351 v.push_back((<Sort?> s).csort)
1352 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1353 <const vector[c_Sort]&> v,
1354 <bint> isCoDatatype)
1355 else:
1356 raise ValueError("Unhandled second argument type {}"
1357 .format(type(sorts_or_bool)))
1358 else:
1359 raise ValueError("Can't create DatatypeDecl with {}".format([type(a)
1360 for a in [name,
1361 sorts_or_bool,
1362 isCoDatatype]]))
1363
1364 return dd
1365
1366 def simplify(self, Term t):
1367 """
1368 Simplify a formula without doing "much" work. Does not involve the
1369 SAT Engine in the simplification, but uses the current definitions,
1370 assertions, and the current partial model, if one has been constructed.
1371 It also involves theory normalization.
1372
1373 :param t: the formula to simplify
1374 :return: the simplified formula
1375 """
1376 cdef Term term = Term(self)
1377 term.cterm = self.csolver.simplify(t.cterm)
1378 return term
1379
1380 def assertFormula(self, Term term):
1381 """ Assert a formula
1382
1383 SMT-LIB:
1384
1385 .. code-block:: smtlib
1386
1387 ( assert <term> )
1388
1389 :param term: the formula to assert
1390 """
1391 self.csolver.assertFormula(term.cterm)
1392
1393 def checkSat(self):
1394 """
1395 Check satisfiability.
1396
1397 SMT-LIB:
1398
1399 .. code-block:: smtlib
1400
1401 ( check-sat )
1402
1403 :return: the result of the satisfiability check.
1404 """
1405 cdef Result r = Result()
1406 r.cr = self.csolver.checkSat()
1407 return r
1408
1409 def mkSygusGrammar(self, boundVars, ntSymbols):
1410 """
1411 Create a SyGuS grammar. The first non-terminal is treated as the
1412 starting non-terminal, so the order of non-terminals matters.
1413
1414 :param boundVars: the parameters to corresponding synth-fun/synth-inv
1415 :param ntSymbols: the pre-declaration of the non-terminal symbols
1416 :return: the grammar
1417 """
1418 cdef Grammar grammar = Grammar(self)
1419 cdef vector[c_Term] bvc
1420 cdef vector[c_Term] ntc
1421 for bv in boundVars:
1422 bvc.push_back((<Term?> bv).cterm)
1423 for nt in ntSymbols:
1424 ntc.push_back((<Term?> nt).cterm)
1425 grammar.cgrammar = self.csolver.mkSygusGrammar(<const vector[c_Term]&> bvc, <const vector[c_Term]&> ntc)
1426 return grammar
1427
1428 def mkSygusVar(self, Sort sort, str symbol=""):
1429 """Append symbol to the current list of universal variables.
1430
1431 SyGuS v2:
1432
1433 .. code-block:: smtlib
1434
1435 ( declare-var <symbol> <sort> )
1436
1437 :param sort: the sort of the universal variable
1438 :param symbol: the name of the universal variable
1439 :return: the universal variable
1440 """
1441 cdef Term term = Term(self)
1442 term.cterm = self.csolver.mkSygusVar(sort.csort, symbol.encode())
1443 return term
1444
1445 def addSygusConstraint(self, Term t):
1446 """
1447 Add a formula to the set of SyGuS constraints.
1448
1449 SyGuS v2:
1450
1451 .. code-block:: smtlib
1452
1453 ( constraint <term> )
1454
1455 :param term: the formula to add as a constraint
1456 """
1457 self.csolver.addSygusConstraint(t.cterm)
1458
1459 def addSygusInvConstraint(self, Term inv_f, Term pre_f, Term trans_f, Term post_f):
1460 """
1461 Add a set of SyGuS constraints to the current state that correspond to an
1462 invariant synthesis problem.
1463
1464 SyGuS v2:
1465
1466 .. code-block:: smtlib
1467
1468 ( inv-constraint <inv> <pre> <trans> <post> )
1469
1470 :param inv: the function-to-synthesize
1471 :param pre: the pre-condition
1472 :param trans: the transition relation
1473 :param post: the post-condition
1474 """
1475 self.csolver.addSygusInvConstraint(inv_f.cterm, pre_f.cterm, trans_f.cterm, post_f.cterm)
1476
1477 def synthFun(self, str symbol, bound_vars, Sort sort, Grammar grammar=None):
1478 """
1479 Synthesize n-ary function following specified syntactic constraints.
1480
1481 SyGuS v2:
1482
1483 .. code-block:: smtlib
1484
1485 ( synth-fun <symbol> ( <boundVars>* ) <sort> <g> )
1486
1487 :param symbol: the name of the function
1488 :param boundVars: the parameters to this function
1489 :param sort: the sort of the return value of this function
1490 :param grammar: the syntactic constraints
1491 :return: the function
1492 """
1493 cdef Term term = Term(self)
1494 cdef vector[c_Term] v
1495 for bv in bound_vars:
1496 v.push_back((<Term?> bv).cterm)
1497 if grammar is None:
1498 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort)
1499 else:
1500 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort, grammar.cgrammar)
1501 return term
1502
1503 def checkSynth(self):
1504 """
1505 Try to find a solution for the synthesis conjecture corresponding to the
1506 current list of functions-to-synthesize, universal variables and
1507 constraints.
1508
1509 SyGuS v2:
1510
1511 .. code-block:: smtlib
1512
1513 ( check-synth )
1514
1515 :return: the result of the synthesis conjecture.
1516 """
1517 cdef Result r = Result()
1518 r.cr = self.csolver.checkSynth()
1519 return r
1520
1521 def getSynthSolution(self, Term term):
1522 """
1523 Get the synthesis solution of the given term. This method should be
1524 called immediately after the solver answers unsat for sygus input.
1525
1526 :param term: the term for which the synthesis solution is queried
1527 :return: the synthesis solution of the given term
1528 """
1529 cdef Term t = Term(self)
1530 t.cterm = self.csolver.getSynthSolution(term.cterm)
1531 return t
1532
1533 def getSynthSolutions(self, list terms):
1534 """
1535 Get the synthesis solutions of the given terms. This method should be
1536 called immediately after the solver answers unsat for sygus input.
1537
1538 :param terms: the terms for which the synthesis solutions is queried
1539 :return: the synthesis solutions of the given terms
1540 """
1541 result = []
1542 cdef vector[c_Term] vec
1543 for t in terms:
1544 vec.push_back((<Term?> t).cterm)
1545 cresult = self.csolver.getSynthSolutions(vec)
1546 for s in cresult:
1547 term = Term(self)
1548 term.cterm = s
1549 result.append(term)
1550 return result
1551
1552
1553 def synthInv(self, symbol, bound_vars, Grammar grammar=None):
1554 """
1555 Synthesize invariant.
1556
1557 SyGuS v2:
1558
1559 .. code-block:: smtlib
1560
1561 ( synth-inv <symbol> ( <boundVars>* ) <grammar> )
1562
1563 :param symbol: the name of the invariant
1564 :param boundVars: the parameters to this invariant
1565 :param grammar: the syntactic constraints
1566 :return: the invariant
1567 """
1568 cdef Term term = Term(self)
1569 cdef vector[c_Term] v
1570 for bv in bound_vars:
1571 v.push_back((<Term?> bv).cterm)
1572 if grammar is None:
1573 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v)
1574 else:
1575 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v, grammar.cgrammar)
1576 return term
1577
1578 @expand_list_arg(num_req_args=0)
1579 def checkSatAssuming(self, *assumptions):
1580 """ Check satisfiability assuming the given formula.
1581
1582 SMT-LIB:
1583
1584 .. code-block:: smtlib
1585
1586 ( check-sat-assuming ( <prop_literal> ) )
1587
1588 :param assumptions: the formulas to assume, as a list or as distinct arguments
1589 :return: the result of the satisfiability check.
1590 """
1591 cdef Result r = Result()
1592 # used if assumptions is a list of terms
1593 cdef vector[c_Term] v
1594 for a in assumptions:
1595 v.push_back((<Term?> a).cterm)
1596 r.cr = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
1597 return r
1598
1599 @expand_list_arg(num_req_args=0)
1600 def checkEntailed(self, *assumptions):
1601 """Check entailment of the given formula w.r.t. the current set of assertions.
1602
1603 :param terms: the formulas to check entailment for, as a list or as distinct arguments
1604 :return: the result of the entailment check.
1605 """
1606 cdef Result r = Result()
1607 # used if assumptions is a list of terms
1608 cdef vector[c_Term] v
1609 for a in assumptions:
1610 v.push_back((<Term?> a).cterm)
1611 r.cr = self.csolver.checkEntailed(<const vector[c_Term]&> v)
1612 return r
1613
1614 @expand_list_arg(num_req_args=1)
1615 def declareDatatype(self, str symbol, *ctors):
1616 """
1617 Create datatype sort.
1618
1619 SMT-LIB:
1620
1621 .. code-block:: smtlib
1622
1623 ( declare-datatype <symbol> <datatype_decl> )
1624
1625 :param symbol: the name of the datatype sort
1626 :param ctors: the constructor declarations of the datatype sort, as a list or as distinct arguments
1627 :return: the datatype sort
1628 """
1629 cdef Sort sort = Sort(self)
1630 cdef vector[c_DatatypeConstructorDecl] v
1631
1632 for c in ctors:
1633 v.push_back((<DatatypeConstructorDecl?> c).cddc)
1634 sort.csort = self.csolver.declareDatatype(symbol.encode(), v)
1635 return sort
1636
1637 def declareFun(self, str symbol, list sorts, Sort sort):
1638 """Declare n-ary function symbol.
1639
1640 SMT-LIB:
1641
1642 .. code-block:: smtlib
1643
1644 ( declare-fun <symbol> ( <sort>* ) <sort> )
1645
1646 :param symbol: the name of the function
1647 :param sorts: the sorts of the parameters to this function
1648 :param sort: the sort of the return value of this function
1649 :return: the function
1650 """
1651 cdef Term term = Term(self)
1652 cdef vector[c_Sort] v
1653 for s in sorts:
1654 v.push_back((<Sort?> s).csort)
1655 term.cterm = self.csolver.declareFun(symbol.encode(),
1656 <const vector[c_Sort]&> v,
1657 sort.csort)
1658 return term
1659
1660 def declareSort(self, str symbol, int arity):
1661 """Declare uninterpreted sort.
1662
1663 SMT-LIB:
1664
1665 .. code-block:: smtlib
1666
1667 ( declare-sort <symbol> <numeral> )
1668
1669 :param symbol: the name of the sort
1670 :param arity: the arity of the sort
1671 :return: the sort
1672 """
1673 cdef Sort sort = Sort(self)
1674 sort.csort = self.csolver.declareSort(symbol.encode(), arity)
1675 return sort
1676
1677 def defineFun(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1678 """
1679 Define n-ary function.
1680 Supports two uses:
1681
1682 - ``Term defineFun(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1683 - ``Term defineFun(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1684
1685
1686 SMT-LIB:
1687
1688 .. code-block:: smtlib
1689
1690 ( define-fun <function_def> )
1691
1692 :param symbol: the name of the function
1693 :param bound_vars: the parameters to this function
1694 :param sort: the sort of the return value of this function
1695 :param term: the function body
1696 :param global: determines whether this definition is global (i.e. persists when popping the context)
1697 :return: the function
1698 """
1699 cdef Term term = Term(self)
1700 cdef vector[c_Term] v
1701 for bv in bound_vars:
1702 v.push_back((<Term?> bv).cterm)
1703
1704 if t is not None:
1705 term.cterm = self.csolver.defineFun((<str?> sym_or_fun).encode(),
1706 <const vector[c_Term] &> v,
1707 (<Sort?> sort_or_term).csort,
1708 (<Term?> t).cterm,
1709 <bint> glbl)
1710 else:
1711 term.cterm = self.csolver.defineFun((<Term?> sym_or_fun).cterm,
1712 <const vector[c_Term]&> v,
1713 (<Term?> sort_or_term).cterm,
1714 <bint> glbl)
1715
1716 return term
1717
1718 def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1719 """Define recursive functions.
1720
1721 Supports two uses:
1722
1723 - ``Term defineFunRec(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1724 - ``Term defineFunRec(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1725
1726
1727 SMT-LIB:
1728
1729 .. code-block:: smtlib
1730
1731 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1732
1733 Create elements of parameter ``funs`` with mkConst().
1734
1735 :param funs: the sorted functions
1736 :param bound_vars: the list of parameters to the functions
1737 :param terms: the list of function bodies of the functions
1738 :param global: determines whether this definition is global (i.e. persists when popping the context)
1739 :return: the function
1740 """
1741 cdef Term term = Term(self)
1742 cdef vector[c_Term] v
1743 for bv in bound_vars:
1744 v.push_back((<Term?> bv).cterm)
1745
1746 if t is not None:
1747 term.cterm = self.csolver.defineFunRec((<str?> sym_or_fun).encode(),
1748 <const vector[c_Term] &> v,
1749 (<Sort?> sort_or_term).csort,
1750 (<Term?> t).cterm,
1751 <bint> glbl)
1752 else:
1753 term.cterm = self.csolver.defineFunRec((<Term?> sym_or_fun).cterm,
1754 <const vector[c_Term]&> v,
1755 (<Term?> sort_or_term).cterm,
1756 <bint> glbl)
1757
1758 return term
1759
1760 def defineFunsRec(self, funs, bound_vars, terms):
1761 """Define recursive functions.
1762
1763 SMT-LIB:
1764
1765 .. code-block:: smtlib
1766
1767 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1768
1769 Create elements of parameter ``funs`` with mkConst().
1770
1771 :param funs: the sorted functions
1772 :param bound_vars: the list of parameters to the functions
1773 :param terms: the list of function bodies of the functions
1774 :param global: determines whether this definition is global (i.e. persists when popping the context)
1775 :return: the function
1776 """
1777 cdef vector[c_Term] vf
1778 cdef vector[vector[c_Term]] vbv
1779 cdef vector[c_Term] vt
1780
1781 for f in funs:
1782 vf.push_back((<Term?> f).cterm)
1783
1784 cdef vector[c_Term] temp
1785 for v in bound_vars:
1786 for t in v:
1787 temp.push_back((<Term?> t).cterm)
1788 vbv.push_back(temp)
1789 temp.clear()
1790
1791 for t in terms:
1792 vf.push_back((<Term?> t).cterm)
1793
1794 def getAssertions(self):
1795 """Get the list of asserted formulas.
1796
1797 SMT-LIB:
1798
1799 .. code-block:: smtlib
1800
1801 ( get-assertions )
1802
1803 :return: the list of asserted formulas
1804 """
1805 assertions = []
1806 for a in self.csolver.getAssertions():
1807 term = Term(self)
1808 term.cterm = a
1809 assertions.append(term)
1810 return assertions
1811
1812 def getInfo(self, str flag):
1813 """Get info from the solver.
1814
1815 SMT-LIB:
1816
1817 .. code-block:: smtlib
1818
1819 ( get-info <info_flag> )
1820
1821 :param flag: the info flag
1822 :return: the info
1823 """
1824 return self.csolver.getInfo(flag.encode())
1825
1826 def getOption(self, str option):
1827 """Get the value of a given option.
1828
1829 SMT-LIB:
1830
1831 .. code-block:: smtlib
1832
1833 ( get-option <keyword> )
1834
1835 :param option: the option for which the value is queried
1836 :return: a string representation of the option value
1837 """
1838 return self.csolver.getOption(option.encode())
1839
1840 def getUnsatAssumptions(self):
1841 """
1842 Get the set of unsat ("failed") assumptions.
1843
1844 SMT-LIB:
1845
1846 .. code-block:: smtlib
1847
1848 ( get-unsat-assumptions )
1849
1850 Requires to enable option :ref:`produce-unsat-assumptions <lbl-option-produce-unsat-assumptions>`.
1851
1852 :return: the set of unsat assumptions.
1853 """
1854 assumptions = []
1855 for a in self.csolver.getUnsatAssumptions():
1856 term = Term(self)
1857 term.cterm = a
1858 assumptions.append(term)
1859 return assumptions
1860
1861 def getUnsatCore(self):
1862 """Get the unsatisfiable core.
1863
1864 SMT-LIB:
1865
1866 .. code-block:: smtlib
1867
1868 ( get-unsat-core )
1869
1870 Requires to enable option :ref:`produce-unsat-cores <lbl-produce-unsat-cores>`.
1871
1872 :return: a set of terms representing the unsatisfiable core
1873 """
1874 core = []
1875 for a in self.csolver.getUnsatCore():
1876 term = Term(self)
1877 term.cterm = a
1878 core.append(term)
1879 return core
1880
1881 def getValue(self, Term t):
1882 """Get the value of the given term in the current model.
1883
1884 SMT-LIB:
1885
1886 .. code-block:: smtlib
1887
1888 ( get-value ( <term> ) )
1889
1890 :param term: the term for which the value is queried
1891 :return: the value of the given term
1892 """
1893 cdef Term term = Term(self)
1894 term.cterm = self.csolver.getValue(t.cterm)
1895 return term
1896
1897 def getModelDomainElements(self, Sort s):
1898 """
1899 Get the domain elements of uninterpreted sort s in the current model. The
1900 current model interprets s as the finite sort whose domain elements are
1901 given in the return value of this method.
1902
1903 :param s: The uninterpreted sort in question
1904 :return: the domain elements of s in the current model
1905 """
1906 result = []
1907 cresult = self.csolver.getModelDomainElements(s.csort)
1908 for e in cresult:
1909 term = Term(self)
1910 term.cterm = e
1911 result.append(term)
1912 return result
1913
1914 def isModelCoreSymbol(self, Term v):
1915 """
1916 This returns false if the model value of free constant v was not
1917 essential for showing the satisfiability of the last call to checkSat
1918 using the current model. This method will only return false (for any v)
1919 if the model-cores option has been set.
1920
1921 :param v: The term in question
1922 :return: true if v is a model core symbol
1923 """
1924 return self.csolver.isModelCoreSymbol(v.cterm)
1925
1926 def getSeparationHeap(self):
1927 """When using separation logic, obtain the term for the heap.
1928
1929 :return: The term for the heap
1930 """
1931 cdef Term term = Term(self)
1932 term.cterm = self.csolver.getSeparationHeap()
1933 return term
1934
1935 def getSeparationNilTerm(self):
1936 """When using separation logic, obtain the term for nil.
1937
1938 :return: The term for nil
1939 """
1940 cdef Term term = Term(self)
1941 term.cterm = self.csolver.getSeparationNilTerm()
1942 return term
1943
1944 def declareSeparationHeap(self, Sort locType, Sort dataType):
1945 """
1946 When using separation logic, this sets the location sort and the
1947 datatype sort to the given ones. This method should be invoked exactly
1948 once, before any separation logic constraints are provided.
1949
1950 :param locSort: The location sort of the heap
1951 :param dataSort: The data sort of the heap
1952 """
1953 self.csolver.declareSeparationHeap(locType.csort, dataType.csort)
1954
1955 def declarePool(self, str symbol, Sort sort, initValue):
1956 """Declare a symbolic pool of terms with the given initial value.
1957
1958 SMT-LIB:
1959
1960 .. code-block:: smtlib
1961
1962 ( declare-pool <symbol> <sort> ( <term>* ) )
1963
1964 :param symbol: The name of the pool
1965 :param sort: The sort of the elements of the pool.
1966 :param initValue: The initial value of the pool
1967 """
1968 cdef Term term = Term(self)
1969 cdef vector[c_Term] niv
1970 for v in initValue:
1971 niv.push_back((<Term?> v).cterm)
1972 term.cterm = self.csolver.declarePool(symbol.encode(), sort.csort, niv)
1973 return term
1974
1975 def pop(self, nscopes=1):
1976 """Pop ``nscopes`` level(s) from the assertion stack.
1977
1978 SMT-LIB:
1979
1980 .. code-block:: smtlib
1981
1982 ( pop <numeral> )
1983
1984 :param nscopes: the number of levels to pop
1985 """
1986 self.csolver.pop(nscopes)
1987
1988 def push(self, nscopes=1):
1989 """ Push ``nscopes`` level(s) to the assertion stack.
1990
1991 SMT-LIB:
1992
1993 .. code-block:: smtlib
1994
1995 ( push <numeral> )
1996
1997 :param nscopes: the number of levels to push
1998 """
1999 self.csolver.push(nscopes)
2000
2001 def resetAssertions(self):
2002 """
2003 Remove all assertions.
2004
2005 SMT-LIB:
2006
2007 .. code-block:: smtlib
2008
2009 ( reset-assertions )
2010
2011 """
2012 self.csolver.resetAssertions()
2013
2014 def setInfo(self, str keyword, str value):
2015 """Set info.
2016
2017 SMT-LIB:
2018
2019 .. code-block:: smtlib
2020
2021 ( set-info <attribute> )
2022
2023 :param keyword: the info flag
2024 :param value: the value of the info flag
2025 """
2026 self.csolver.setInfo(keyword.encode(), value.encode())
2027
2028 def setLogic(self, str logic):
2029 """Set logic.
2030
2031 SMT-LIB:
2032
2033 .. code-block:: smtlib
2034
2035 ( set-logic <symbol> )
2036
2037 :param logic: the logic to set
2038 """
2039 self.csolver.setLogic(logic.encode())
2040
2041 def setOption(self, str option, str value):
2042 """Set option.
2043
2044 SMT-LIB:
2045
2046 .. code-block:: smtlib
2047
2048 ( set-option <option> )
2049
2050 :param option: the option name
2051 :param value: the option value
2052 """
2053 self.csolver.setOption(option.encode(), value.encode())
2054
2055
2056 cdef class Sort:
2057 cdef c_Sort csort
2058 cdef Solver solver
2059 def __cinit__(self, Solver solver):
2060 # csort always set by Solver
2061 self.solver = solver
2062
2063 def __eq__(self, Sort other):
2064 return self.csort == other.csort
2065
2066 def __ne__(self, Sort other):
2067 return self.csort != other.csort
2068
2069 def __lt__(self, Sort other):
2070 return self.csort < other.csort
2071
2072 def __gt__(self, Sort other):
2073 return self.csort > other.csort
2074
2075 def __le__(self, Sort other):
2076 return self.csort <= other.csort
2077
2078 def __ge__(self, Sort other):
2079 return self.csort >= other.csort
2080
2081 def __str__(self):
2082 return self.csort.toString().decode()
2083
2084 def __repr__(self):
2085 return self.csort.toString().decode()
2086
2087 def __hash__(self):
2088 return csorthash(self.csort)
2089
2090 def isBoolean(self):
2091 return self.csort.isBoolean()
2092
2093 def isInteger(self):
2094 return self.csort.isInteger()
2095
2096 def isReal(self):
2097 return self.csort.isReal()
2098
2099 def isString(self):
2100 return self.csort.isString()
2101
2102 def isRegExp(self):
2103 return self.csort.isRegExp()
2104
2105 def isRoundingMode(self):
2106 return self.csort.isRoundingMode()
2107
2108 def isBitVector(self):
2109 return self.csort.isBitVector()
2110
2111 def isFloatingPoint(self):
2112 return self.csort.isFloatingPoint()
2113
2114 def isDatatype(self):
2115 return self.csort.isDatatype()
2116
2117 def isParametricDatatype(self):
2118 return self.csort.isParametricDatatype()
2119
2120 def isConstructor(self):
2121 return self.csort.isConstructor()
2122
2123 def isSelector(self):
2124 return self.csort.isSelector()
2125
2126 def isTester(self):
2127 return self.csort.isTester()
2128
2129 def isFunction(self):
2130 return self.csort.isFunction()
2131
2132 def isPredicate(self):
2133 return self.csort.isPredicate()
2134
2135 def isTuple(self):
2136 return self.csort.isTuple()
2137
2138 def isRecord(self):
2139 return self.csort.isRecord()
2140
2141 def isArray(self):
2142 return self.csort.isArray()
2143
2144 def isSet(self):
2145 return self.csort.isSet()
2146
2147 def isBag(self):
2148 return self.csort.isBag()
2149
2150 def isSequence(self):
2151 return self.csort.isSequence()
2152
2153 def isUninterpretedSort(self):
2154 return self.csort.isUninterpretedSort()
2155
2156 def isSortConstructor(self):
2157 return self.csort.isSortConstructor()
2158
2159 def isFirstClass(self):
2160 return self.csort.isFirstClass()
2161
2162 def isFunctionLike(self):
2163 return self.csort.isFunctionLike()
2164
2165 def isSubsortOf(self, Sort sort):
2166 return self.csort.isSubsortOf(sort.csort)
2167
2168 def isComparableTo(self, Sort sort):
2169 return self.csort.isComparableTo(sort.csort)
2170
2171 def getDatatype(self):
2172 cdef Datatype d = Datatype(self.solver)
2173 d.cd = self.csort.getDatatype()
2174 return d
2175
2176 def instantiate(self, params):
2177 cdef Sort sort = Sort(self.solver)
2178 cdef vector[c_Sort] v
2179 for s in params:
2180 v.push_back((<Sort?> s).csort)
2181 sort.csort = self.csort.instantiate(v)
2182 return sort
2183
2184 def getConstructorArity(self):
2185 return self.csort.getConstructorArity()
2186
2187 def getConstructorDomainSorts(self):
2188 domain_sorts = []
2189 for s in self.csort.getConstructorDomainSorts():
2190 sort = Sort(self.solver)
2191 sort.csort = s
2192 domain_sorts.append(sort)
2193 return domain_sorts
2194
2195 def getConstructorCodomainSort(self):
2196 cdef Sort sort = Sort(self.solver)
2197 sort.csort = self.csort.getConstructorCodomainSort()
2198 return sort
2199
2200 def getSelectorDomainSort(self):
2201 cdef Sort sort = Sort(self.solver)
2202 sort.csort = self.csort.getSelectorDomainSort()
2203 return sort
2204
2205 def getSelectorCodomainSort(self):
2206 cdef Sort sort = Sort(self.solver)
2207 sort.csort = self.csort.getSelectorCodomainSort()
2208 return sort
2209
2210 def getTesterDomainSort(self):
2211 cdef Sort sort = Sort(self.solver)
2212 sort.csort = self.csort.getTesterDomainSort()
2213 return sort
2214
2215 def getTesterCodomainSort(self):
2216 cdef Sort sort = Sort(self.solver)
2217 sort.csort = self.csort.getTesterCodomainSort()
2218 return sort
2219
2220 def getFunctionArity(self):
2221 return self.csort.getFunctionArity()
2222
2223 def getFunctionDomainSorts(self):
2224 domain_sorts = []
2225 for s in self.csort.getFunctionDomainSorts():
2226 sort = Sort(self.solver)
2227 sort.csort = s
2228 domain_sorts.append(sort)
2229 return domain_sorts
2230
2231 def getFunctionCodomainSort(self):
2232 cdef Sort sort = Sort(self.solver)
2233 sort.csort = self.csort.getFunctionCodomainSort()
2234 return sort
2235
2236 def getArrayIndexSort(self):
2237 cdef Sort sort = Sort(self.solver)
2238 sort.csort = self.csort.getArrayIndexSort()
2239 return sort
2240
2241 def getArrayElementSort(self):
2242 cdef Sort sort = Sort(self.solver)
2243 sort.csort = self.csort.getArrayElementSort()
2244 return sort
2245
2246 def getSetElementSort(self):
2247 cdef Sort sort = Sort(self.solver)
2248 sort.csort = self.csort.getSetElementSort()
2249 return sort
2250
2251 def getBagElementSort(self):
2252 cdef Sort sort = Sort(self.solver)
2253 sort.csort = self.csort.getBagElementSort()
2254 return sort
2255
2256 def getSequenceElementSort(self):
2257 cdef Sort sort = Sort(self.solver)
2258 sort.csort = self.csort.getSequenceElementSort()
2259 return sort
2260
2261 def getUninterpretedSortName(self):
2262 return self.csort.getUninterpretedSortName().decode()
2263
2264 def isUninterpretedSortParameterized(self):
2265 return self.csort.isUninterpretedSortParameterized()
2266
2267 def getUninterpretedSortParamSorts(self):
2268 param_sorts = []
2269 for s in self.csort.getUninterpretedSortParamSorts():
2270 sort = Sort(self.solver)
2271 sort.csort = s
2272 param_sorts.append(sort)
2273 return param_sorts
2274
2275 def getSortConstructorName(self):
2276 return self.csort.getSortConstructorName().decode()
2277
2278 def getSortConstructorArity(self):
2279 return self.csort.getSortConstructorArity()
2280
2281 def getBVSize(self):
2282 return self.csort.getBVSize()
2283
2284 def getFPExponentSize(self):
2285 return self.csort.getFPExponentSize()
2286
2287 def getFPSignificandSize(self):
2288 return self.csort.getFPSignificandSize()
2289
2290 def getDatatypeParamSorts(self):
2291 param_sorts = []
2292 for s in self.csort.getDatatypeParamSorts():
2293 sort = Sort(self.solver)
2294 sort.csort = s
2295 param_sorts.append(sort)
2296 return param_sorts
2297
2298 def getDatatypeArity(self):
2299 return self.csort.getDatatypeArity()
2300
2301 def getTupleLength(self):
2302 return self.csort.getTupleLength()
2303
2304 def getTupleSorts(self):
2305 tuple_sorts = []
2306 for s in self.csort.getTupleSorts():
2307 sort = Sort(self.solver)
2308 sort.csort = s
2309 tuple_sorts.append(sort)
2310 return tuple_sorts
2311
2312
2313 cdef class Term:
2314 cdef c_Term cterm
2315 cdef Solver solver
2316 def __cinit__(self, Solver solver):
2317 # cterm always set in the Solver object
2318 self.solver = solver
2319
2320 def __eq__(self, Term other):
2321 return self.cterm == other.cterm
2322
2323 def __ne__(self, Term other):
2324 return self.cterm != other.cterm
2325
2326 def __lt__(self, Term other):
2327 return self.cterm < other.cterm
2328
2329 def __gt__(self, Term other):
2330 return self.cterm > other.cterm
2331
2332 def __le__(self, Term other):
2333 return self.cterm <= other.cterm
2334
2335 def __ge__(self, Term other):
2336 return self.cterm >= other.cterm
2337
2338 def __getitem__(self, int index):
2339 cdef Term term = Term(self.solver)
2340 if index >= 0:
2341 term.cterm = self.cterm[index]
2342 else:
2343 raise ValueError("Expecting a non-negative integer or string")
2344 return term
2345
2346 def __str__(self):
2347 return self.cterm.toString().decode()
2348
2349 def __repr__(self):
2350 return self.cterm.toString().decode()
2351
2352 def __iter__(self):
2353 for ci in self.cterm:
2354 term = Term(self.solver)
2355 term.cterm = ci
2356 yield term
2357
2358 def __hash__(self):
2359 return ctermhash(self.cterm)
2360
2361 def getNumChildren(self):
2362 return self.cterm.getNumChildren()
2363
2364 def getId(self):
2365 return self.cterm.getId()
2366
2367 def getKind(self):
2368 return kind(<int> self.cterm.getKind())
2369
2370 def getSort(self):
2371 cdef Sort sort = Sort(self.solver)
2372 sort.csort = self.cterm.getSort()
2373 return sort
2374
2375 def substitute(self, term_or_list_1, term_or_list_2):
2376 # The resulting term after substitution
2377 cdef Term term = Term(self.solver)
2378 # lists for substitutions
2379 cdef vector[c_Term] ces
2380 cdef vector[c_Term] creplacements
2381
2382 # normalize the input parameters to be lists
2383 if isinstance(term_or_list_1, list):
2384 assert isinstance(term_or_list_2, list)
2385 es = term_or_list_1
2386 replacements = term_or_list_2
2387 if len(es) != len(replacements):
2388 raise RuntimeError("Expecting list inputs to substitute to "
2389 "have the same length but got: "
2390 "{} and {}".format(len(es), len(replacements)))
2391
2392 for e, r in zip(es, replacements):
2393 ces.push_back((<Term?> e).cterm)
2394 creplacements.push_back((<Term?> r).cterm)
2395
2396 else:
2397 # add the single elements to the vectors
2398 ces.push_back((<Term?> term_or_list_1).cterm)
2399 creplacements.push_back((<Term?> term_or_list_2).cterm)
2400
2401 # call the API substitute method with lists
2402 term.cterm = self.cterm.substitute(ces, creplacements)
2403 return term
2404
2405 def hasOp(self):
2406 return self.cterm.hasOp()
2407
2408 def getOp(self):
2409 cdef Op op = Op(self.solver)
2410 op.cop = self.cterm.getOp()
2411 return op
2412
2413 def isNull(self):
2414 return self.cterm.isNull()
2415
2416 def notTerm(self):
2417 cdef Term term = Term(self.solver)
2418 term.cterm = self.cterm.notTerm()
2419 return term
2420
2421 def andTerm(self, Term t):
2422 cdef Term term = Term(self.solver)
2423 term.cterm = self.cterm.andTerm((<Term> t).cterm)
2424 return term
2425
2426 def orTerm(self, Term t):
2427 cdef Term term = Term(self.solver)
2428 term.cterm = self.cterm.orTerm(t.cterm)
2429 return term
2430
2431 def xorTerm(self, Term t):
2432 cdef Term term = Term(self.solver)
2433 term.cterm = self.cterm.xorTerm(t.cterm)
2434 return term
2435
2436 def eqTerm(self, Term t):
2437 cdef Term term = Term(self.solver)
2438 term.cterm = self.cterm.eqTerm(t.cterm)
2439 return term
2440
2441 def impTerm(self, Term t):
2442 cdef Term term = Term(self.solver)
2443 term.cterm = self.cterm.impTerm(t.cterm)
2444 return term
2445
2446 def iteTerm(self, Term then_t, Term else_t):
2447 cdef Term term = Term(self.solver)
2448 term.cterm = self.cterm.iteTerm(then_t.cterm, else_t.cterm)
2449 return term
2450
2451 def isConstArray(self):
2452 return self.cterm.isConstArray()
2453
2454 def getConstArrayBase(self):
2455 cdef Term term = Term(self.solver)
2456 term.cterm = self.cterm.getConstArrayBase()
2457 return term
2458
2459 def isBooleanValue(self):
2460 return self.cterm.isBooleanValue()
2461
2462 def getBooleanValue(self):
2463 return self.cterm.getBooleanValue()
2464
2465 def isStringValue(self):
2466 return self.cterm.isStringValue()
2467
2468 def getStringValue(self):
2469 cdef Py_ssize_t size
2470 cdef c_wstring s = self.cterm.getStringValue()
2471 return PyUnicode_FromWideChar(s.data(), s.size())
2472
2473 def isIntegerValue(self):
2474 return self.cterm.isIntegerValue()
2475 def isAbstractValue(self):
2476 return self.cterm.isAbstractValue()
2477
2478 def getAbstractValue(self):
2479 return self.cterm.getAbstractValue().decode()
2480
2481 def isFloatingPointPosZero(self):
2482 return self.cterm.isFloatingPointPosZero()
2483
2484 def isFloatingPointNegZero(self):
2485 return self.cterm.isFloatingPointNegZero()
2486
2487 def isFloatingPointPosInf(self):
2488 return self.cterm.isFloatingPointPosInf()
2489
2490 def isFloatingPointNegInf(self):
2491 return self.cterm.isFloatingPointNegInf()
2492
2493 def isFloatingPointNaN(self):
2494 return self.cterm.isFloatingPointNaN()
2495
2496 def isFloatingPointValue(self):
2497 return self.cterm.isFloatingPointValue()
2498
2499 def getFloatingPointValue(self):
2500 cdef c_tuple[uint32_t, uint32_t, c_Term] t = self.cterm.getFloatingPointValue()
2501 cdef Term term = Term(self.solver)
2502 term.cterm = get2(t)
2503 return (get0(t), get1(t), term)
2504
2505 def isSetValue(self):
2506 return self.cterm.isSetValue()
2507
2508 def getSetValue(self):
2509 elems = set()
2510 for e in self.cterm.getSetValue():
2511 term = Term(self.solver)
2512 term.cterm = e
2513 elems.add(term)
2514 return elems
2515
2516 def isSequenceValue(self):
2517 return self.cterm.isSequenceValue()
2518
2519 def getSequenceValue(self):
2520 elems = []
2521 for e in self.cterm.getSequenceValue():
2522 term = Term(self.solver)
2523 term.cterm = e
2524 elems.append(term)
2525 return elems
2526
2527 def isUninterpretedValue(self):
2528 return self.cterm.isUninterpretedValue()
2529
2530 def getUninterpretedValue(self):
2531 cdef pair[c_Sort, int32_t] p = self.cterm.getUninterpretedValue()
2532 cdef Sort sort = Sort(self.solver)
2533 sort.csort = p.first
2534 i = p.second
2535 return (sort, i)
2536
2537 def isTupleValue(self):
2538 return self.cterm.isTupleValue()
2539
2540 def getTupleValue(self):
2541 elems = []
2542 for e in self.cterm.getTupleValue():
2543 term = Term(self.solver)
2544 term.cterm = e
2545 elems.append(term)
2546 return elems
2547
2548 def getIntegerValue(self):
2549 return int(self.cterm.getIntegerValue().decode())
2550
2551 def isRealValue(self):
2552 return self.cterm.isRealValue()
2553
2554 def getRealValue(self):
2555 """Returns the value of a real term as a Fraction"""
2556 return Fraction(self.cterm.getRealValue().decode())
2557
2558 def isBitVectorValue(self):
2559 return self.cterm.isBitVectorValue()
2560
2561 def getBitVectorValue(self, base = 2):
2562 """Returns the value of a bit-vector term as a 0/1 string"""
2563 return self.cterm.getBitVectorValue(base).decode()
2564
2565 def toPythonObj(self):
2566 """
2567 Converts a constant value Term to a Python object.
2568
2569 Currently supports:
2570 Boolean -- returns a Python bool
2571 Int -- returns a Python int
2572 Real -- returns a Python Fraction
2573 BV -- returns a Python int (treats BV as unsigned)
2574 String -- returns a Python Unicode string
2575 Array -- returns a Python dict mapping indices to values
2576 -- the constant base is returned as the default value
2577 """
2578
2579 if self.isBooleanValue():
2580 return self.getBooleanValue()
2581 elif self.isIntegerValue():
2582 return self.getIntegerValue()
2583 elif self.isRealValue():
2584 return self.getRealValue()
2585 elif self.isBitVectorValue():
2586 return int(self.getBitVectorValue(), 2)
2587 elif self.isStringValue():
2588 return self.getStringValue()
2589 elif self.getSort().isArray():
2590 res = None
2591 keys = []
2592 values = []
2593 base_value = None
2594 to_visit = [self]
2595 # Array models are represented as a series of store operations
2596 # on a constant array
2597 while to_visit:
2598 t = to_visit.pop()
2599 if t.getKind() == kinds.Store:
2600 # save the mappings
2601 keys.append(t[1].toPythonObj())
2602 values.append(t[2].toPythonObj())
2603 to_visit.append(t[0])
2604 else:
2605 assert t.getKind() == kinds.ConstArray
2606 base_value = t.getConstArrayBase().toPythonObj()
2607
2608 assert len(keys) == len(values)
2609 assert base_value is not None
2610
2611 # put everything in a dictionary with the constant
2612 # base as the result for any index not included in the stores
2613 res = defaultdict(lambda : base_value)
2614 for k, v in zip(keys, values):
2615 res[k] = v
2616
2617 return res
2618
2619
2620 # Generate rounding modes
2621 cdef __rounding_modes = {
2622 <int> ROUND_NEAREST_TIES_TO_EVEN: "RoundNearestTiesToEven",
2623 <int> ROUND_TOWARD_POSITIVE: "RoundTowardPositive",
2624 <int> ROUND_TOWARD_NEGATIVE: "RoundTowardNegative",
2625 <int> ROUND_TOWARD_ZERO: "RoundTowardZero",
2626 <int> ROUND_NEAREST_TIES_TO_AWAY: "RoundNearestTiesToAway"
2627 }
2628
2629 mod_ref = sys.modules[__name__]
2630 for rm_int, name in __rounding_modes.items():
2631 r = RoundingMode(rm_int)
2632
2633 if name in dir(mod_ref):
2634 raise RuntimeError("Redefinition of Python RoundingMode %s."%name)
2635
2636 setattr(mod_ref, name, r)
2637
2638 del r
2639 del rm_int
2640 del name
2641
2642
2643 # Generate unknown explanations
2644 cdef __unknown_explanations = {
2645 <int> REQUIRES_FULL_CHECK: "RequiresFullCheck",
2646 <int> INCOMPLETE: "Incomplete",
2647 <int> TIMEOUT: "Timeout",
2648 <int> RESOURCEOUT: "Resourceout",
2649 <int> MEMOUT: "Memout",
2650 <int> INTERRUPTED: "Interrupted",
2651 <int> NO_STATUS: "NoStatus",
2652 <int> UNSUPPORTED: "Unsupported",
2653 <int> OTHER: "Other",
2654 <int> UNKNOWN_REASON: "UnknownReason"
2655 }
2656
2657 for ue_int, name in __unknown_explanations.items():
2658 u = UnknownExplanation(ue_int)
2659
2660 if name in dir(mod_ref):
2661 raise RuntimeError("Redefinition of Python UnknownExplanation %s."%name)
2662
2663 setattr(mod_ref, name, u)
2664
2665 del u
2666 del ue_int
2667 del name