Start python API Solver documentation (#7064)
[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 """Create a vector of datatype sorts using unresolved sorts. The names of
685 the datatype declarations in dtypedecls must be distinct.
686
687 This method is called when the DatatypeDecl objects dtypedecls have been
688 built using "unresolved" sorts.
689
690 We associate each sort in unresolvedSorts with exacly one datatype from
691 dtypedecls. In particular, it must have the same name as exactly one
692 datatype declaration in dtypedecls.
693
694 When constructing datatypes, unresolved sorts are replaced by the datatype
695 sort constructed for the datatype declaration it is associated with.
696
697 :param dtypedecls: the datatype declarations from which the sort is created
698 :param unresolvedSorts: the list of unresolved sorts
699 :return: the datatype sorts
700 """
701 if unresolvedSorts == None:
702 unresolvedSorts = set([])
703 else:
704 assert isinstance(unresolvedSorts, Set)
705
706 sorts = []
707 cdef vector[c_DatatypeDecl] decls
708 for decl in dtypedecls:
709 decls.push_back((<DatatypeDecl?> decl).cdd)
710
711 cdef c_set[c_Sort] usorts
712 for usort in unresolvedSorts:
713 usorts.insert((<Sort?> usort).csort)
714
715 csorts = self.csolver.mkDatatypeSorts(
716 <const vector[c_DatatypeDecl]&> decls, <const c_set[c_Sort]&> usorts)
717 for csort in csorts:
718 sort = Sort(self)
719 sort.csort = csort
720 sorts.append(sort)
721
722 return sorts
723
724 def mkFunctionSort(self, sorts, Sort codomain):
725 """ Create function sort.
726
727 :param sorts: the sort of the function arguments
728 :param codomain: the sort of the function return value
729 :return: the function sort
730 """
731
732 cdef Sort sort = Sort(self)
733 # populate a vector with dereferenced c_Sorts
734 cdef vector[c_Sort] v
735
736 if isinstance(sorts, Sort):
737 sort.csort = self.csolver.mkFunctionSort((<Sort?> sorts).csort,
738 codomain.csort)
739 elif isinstance(sorts, list):
740 for s in sorts:
741 v.push_back((<Sort?>s).csort)
742
743 sort.csort = self.csolver.mkFunctionSort(<const vector[c_Sort]&> v,
744 codomain.csort)
745 return sort
746
747 def mkParamSort(self, symbolname):
748 """ Create a sort parameter.
749
750 :param symbol: the name of the sort
751 :return: the sort parameter
752 """
753 cdef Sort sort = Sort(self)
754 sort.csort = self.csolver.mkParamSort(symbolname.encode())
755 return sort
756
757 @expand_list_arg(num_req_args=0)
758 def mkPredicateSort(self, *sorts):
759 """Create a predicate sort.
760
761 :param sorts: the list of sorts of the predicate, as a list or as distinct arguments.
762 :return: the predicate sort
763 """
764 cdef Sort sort = Sort(self)
765 cdef vector[c_Sort] v
766 for s in sorts:
767 v.push_back((<Sort?> s).csort)
768 sort.csort = self.csolver.mkPredicateSort(<const vector[c_Sort]&> v)
769 return sort
770
771 @expand_list_arg(num_req_args=0)
772 def mkRecordSort(self, *fields):
773 """Create a record sort
774
775 :param fields: the list of fields of the record, as a list or as distinct arguments
776 :return: the record sort
777 """
778 cdef Sort sort = Sort(self)
779 cdef vector[pair[string, c_Sort]] v
780 cdef pair[string, c_Sort] p
781 for f in fields:
782 name, sortarg = f
783 name = name.encode()
784 p = pair[string, c_Sort](<string?> name, (<Sort?> sortarg).csort)
785 v.push_back(p)
786 sort.csort = self.csolver.mkRecordSort(
787 <const vector[pair[string, c_Sort]] &> v)
788 return sort
789
790 def mkSetSort(self, Sort elemSort):
791 """Create a set sort.
792
793 :param elemSort: the sort of the set elements
794 :return: the set sort
795 """
796 cdef Sort sort = Sort(self)
797 sort.csort = self.csolver.mkSetSort(elemSort.csort)
798 return sort
799
800 def mkBagSort(self, Sort elemSort):
801 """Create a bag sort.
802
803 :param elemSort: the sort of the bag elements
804 :return: the bag sort
805 """
806 cdef Sort sort = Sort(self)
807 sort.csort = self.csolver.mkBagSort(elemSort.csort)
808 return sort
809
810 def mkSequenceSort(self, Sort elemSort):
811 """Create a sequence sort.
812
813 :param elemSort: the sort of the sequence elements
814 :return: the sequence sort
815 """
816 cdef Sort sort = Sort(self)
817 sort.csort = self.csolver.mkSequenceSort(elemSort.csort)
818 return sort
819
820 def mkUninterpretedSort(self, str name):
821 """Create an uninterpreted sort.
822
823 :param symbol: the name of the sort
824 :return: the uninterpreted sort
825 """
826 cdef Sort sort = Sort(self)
827 sort.csort = self.csolver.mkUninterpretedSort(name.encode())
828 return sort
829
830 def mkSortConstructorSort(self, str symbol, size_t arity):
831 """Create a sort constructor sort.
832
833 :param symbol: the symbol of the sort
834 :param arity: the arity of the sort
835 :return: the sort constructor sort
836 """
837 cdef Sort sort = Sort(self)
838 sort.csort =self.csolver.mkSortConstructorSort(symbol.encode(), arity)
839 return sort
840
841 @expand_list_arg(num_req_args=0)
842 def mkTupleSort(self, *sorts):
843 """Create a tuple sort.
844
845 :param sorts: of the elements of the tuple, as a list or as distinct arguments
846 :return: the tuple sort
847 """
848 cdef Sort sort = Sort(self)
849 cdef vector[c_Sort] v
850 for s in sorts:
851 v.push_back((<Sort?> s).csort)
852 sort.csort = self.csolver.mkTupleSort(v)
853 return sort
854
855 @expand_list_arg(num_req_args=1)
856 def mkTerm(self, kind_or_op, *args):
857 """
858 Supports the following arguments:
859
860 - ``Term mkTerm(Kind kind)``
861 - ``Term mkTerm(Kind kind, Op child1, List[Term] children)``
862 - ``Term mkTerm(Kind kind, List[Term] children)``
863
864 where ``List[Term]`` can also be comma-separated arguments
865 """
866 cdef Term term = Term(self)
867 cdef vector[c_Term] v
868
869 op = kind_or_op
870 if isinstance(kind_or_op, kind):
871 op = self.mkOp(kind_or_op)
872
873 if len(args) == 0:
874 term.cterm = self.csolver.mkTerm((<Op?> op).cop)
875 else:
876 for a in args:
877 v.push_back((<Term?> a).cterm)
878 term.cterm = self.csolver.mkTerm((<Op?> op).cop, v)
879 return term
880
881 def mkTuple(self, sorts, terms):
882 """Create a tuple term. Terms are automatically converted if sorts are compatible.
883
884 :param sorts: The sorts of the elements in the tuple
885 :param terms: The elements in the tuple
886 :return: the tuple Term
887 """
888 cdef vector[c_Sort] csorts
889 cdef vector[c_Term] cterms
890
891 for s in sorts:
892 csorts.push_back((<Sort?> s).csort)
893 for s in terms:
894 cterms.push_back((<Term?> s).cterm)
895 cdef Term result = Term(self)
896 result.cterm = self.csolver.mkTuple(csorts, cterms)
897 return result
898
899 @expand_list_arg(num_req_args=0)
900 def mkOp(self, kind k, *args):
901 """
902 Supports the following uses:
903
904 - ``Op mkOp(Kind kind)``
905 - ``Op mkOp(Kind kind, Kind k)``
906 - ``Op mkOp(Kind kind, const string& arg)``
907 - ``Op mkOp(Kind kind, uint32_t arg)``
908 - ``Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1)``
909 """
910 cdef Op op = Op(self)
911 cdef vector[int] v
912
913 if len(args) == 0:
914 op.cop = self.csolver.mkOp(k.k)
915 elif len(args) == 1:
916 if isinstance(args[0], str):
917 op.cop = self.csolver.mkOp(k.k,
918 <const string &>
919 args[0].encode())
920 elif isinstance(args[0], int):
921 op.cop = self.csolver.mkOp(k.k, <int?> args[0])
922 elif isinstance(args[0], list):
923 for a in args[0]:
924 v.push_back((<int?> a))
925 op.cop = self.csolver.mkOp(k.k, <const vector[uint32_t]&> v)
926 else:
927 raise ValueError("Unsupported signature"
928 " mkOp: {}".format(" X ".join([str(k), str(args[0])])))
929 elif len(args) == 2:
930 if isinstance(args[0], int) and isinstance(args[1], int):
931 op.cop = self.csolver.mkOp(k.k, <int> args[0], <int> args[1])
932 else:
933 raise ValueError("Unsupported signature"
934 " mkOp: {}".format(" X ".join([k, args[0], args[1]])))
935 return op
936
937 def mkTrue(self):
938 """Create a Boolean true constant.
939
940 :return: the true constant
941 """
942 cdef Term term = Term(self)
943 term.cterm = self.csolver.mkTrue()
944 return term
945
946 def mkFalse(self):
947 """Create a Boolean false constant.
948
949 :return: the false constant
950 """
951 cdef Term term = Term(self)
952 term.cterm = self.csolver.mkFalse()
953 return term
954
955 def mkBoolean(self, bint val):
956 """Create a Boolean constant.
957
958 :return: the Boolean constant
959 :param val: the value of the constant
960 """
961 cdef Term term = Term(self)
962 term.cterm = self.csolver.mkBoolean(val)
963 return term
964
965 def mkPi(self):
966 """Create a constant representing the number Pi.
967
968 :return: a constant representing Pi
969 """
970 cdef Term term = Term(self)
971 term.cterm = self.csolver.mkPi()
972 return term
973
974 def mkInteger(self, val):
975 """Create an integer constant.
976
977 :param val: representation of the constant: either a string or integer
978 :return: a constant of sort Integer
979 """
980 cdef Term term = Term(self)
981 if isinstance(val, str):
982 term.cterm = self.csolver.mkInteger(<const string &> str(val).encode())
983 else:
984 assert(isinstance(val, int))
985 term.cterm = self.csolver.mkInteger((<int?> val))
986 return term
987
988 def mkReal(self, val, den=None):
989 """Create a real constant.
990
991 :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.
992 :param: `den` if not None, the value is `val`/`den`
993 :return: a real term with literal value
994
995 Can be used in various forms:
996
997 - Given a string ``"N/D"`` constructs the corresponding rational.
998 - Given a string ``"W.D"`` constructs the reduction of ``(W * P + D)/P``, where ``P`` is the appropriate power of 10.
999 - 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``.
1000 - Given a string ``"W"`` or an integer, constructs that integer.
1001 - Given two strings and/or integers ``N`` and ``D``, constructs ``N/D``.
1002 """
1003 cdef Term term = Term(self)
1004 if den is None:
1005 term.cterm = self.csolver.mkReal(str(val).encode())
1006 else:
1007 if not isinstance(val, int) or not isinstance(den, int):
1008 raise ValueError("Expecting integers when"
1009 " constructing a rational"
1010 " but got: {}".format((val, den)))
1011 term.cterm = self.csolver.mkReal("{}/{}".format(val, den).encode())
1012 return term
1013
1014 def mkRegexpEmpty(self):
1015 """Create a regular expression empty term.
1016
1017 :return: the empty term
1018 """
1019 cdef Term term = Term(self)
1020 term.cterm = self.csolver.mkRegexpEmpty()
1021 return term
1022
1023 def mkRegexpSigma(self):
1024 """Create a regular expression sigma term.
1025
1026 :return: the sigma term
1027 """
1028 cdef Term term = Term(self)
1029 term.cterm = self.csolver.mkRegexpSigma()
1030 return term
1031
1032 def mkEmptySet(self, Sort s):
1033 """Create a constant representing an empty set of the given sort.
1034
1035 :param sort: the sort of the set elements.
1036 :return: the empty set constant
1037 """
1038 cdef Term term = Term(self)
1039 term.cterm = self.csolver.mkEmptySet(s.csort)
1040 return term
1041
1042 def mkEmptyBag(self, Sort s):
1043 """Create a constant representing an empty bag of the given sort.
1044
1045 :param sort: the sort of the bag elements.
1046 :return: the empty bag constant
1047 """
1048 cdef Term term = Term(self)
1049 term.cterm = self.csolver.mkEmptyBag(s.csort)
1050 return term
1051
1052 def mkSepNil(self, Sort sort):
1053 """Create a separation logic nil term.
1054
1055 :param sort: the sort of the nil term
1056 :return: the separation logic nil term
1057 """
1058 cdef Term term = Term(self)
1059 term.cterm = self.csolver.mkSepNil(sort.csort)
1060 return term
1061
1062 def mkString(self, str s, useEscSequences = None):
1063 """Create a String constant from a `str` which may contain SMT-LIB
1064 compatible escape sequences like ``\\u1234`` to encode unicode characters.
1065
1066 :param s: the string this constant represents
1067 :param useEscSequences: determines whether escape sequences in `s` should be converted to the corresponding unicode character
1068 :return: the String constant
1069 """
1070 cdef Term term = Term(self)
1071 cdef Py_ssize_t size
1072 cdef wchar_t* tmp = PyUnicode_AsWideCharString(s, &size)
1073 if isinstance(useEscSequences, bool):
1074 term.cterm = self.csolver.mkString(
1075 s.encode(), <bint> useEscSequences)
1076 else:
1077 term.cterm = self.csolver.mkString(c_wstring(tmp, size))
1078 PyMem_Free(tmp)
1079 return term
1080
1081 def mkEmptySequence(self, Sort sort):
1082 """Create an empty sequence of the given element sort.
1083
1084 :param sort: The element sort of the sequence.
1085 :return: the empty sequence with given element sort.
1086 """
1087 cdef Term term = Term(self)
1088 term.cterm = self.csolver.mkEmptySequence(sort.csort)
1089 return term
1090
1091 def mkUniverseSet(self, Sort sort):
1092 """Create a universe set of the given sort.
1093
1094 :param sort: the sort of the set elements
1095 :return: the universe set constant
1096 """
1097 cdef Term term = Term(self)
1098 term.cterm = self.csolver.mkUniverseSet(sort.csort)
1099 return term
1100
1101 @expand_list_arg(num_req_args=0)
1102 def mkBitVector(self, *args):
1103 """
1104 Supports the following arguments:
1105
1106 - ``Term mkBitVector(int size, int val=0)``
1107 - ``Term mkBitVector(int size, string val, int base)``
1108
1109 :return: a bit-vector literal term
1110 :param: `size` an integer size.
1111 :param: `val` an integer representating the value, in the first form. In the second form, a string representing the value.
1112 :param: `base` the base of the string representation (second form only)
1113 """
1114 cdef Term term = Term(self)
1115 if len(args) == 0:
1116 raise ValueError("Missing arguments to mkBitVector")
1117 size = args[0]
1118 if not isinstance(size, int):
1119 raise ValueError(
1120 "Invalid first argument to mkBitVector '{}', "
1121 "expected bit-vector size".format(size))
1122 if len(args) == 1:
1123 term.cterm = self.csolver.mkBitVector(<uint32_t> size)
1124 elif len(args) == 2:
1125 val = args[1]
1126 if not isinstance(val, int):
1127 raise ValueError(
1128 "Invalid second argument to mkBitVector '{}', "
1129 "expected integer value".format(size))
1130 term.cterm = self.csolver.mkBitVector(
1131 <uint32_t> size, <uint32_t> val)
1132 elif len(args) == 3:
1133 val = args[1]
1134 base = args[2]
1135 if not isinstance(val, str):
1136 raise ValueError(
1137 "Invalid second argument to mkBitVector '{}', "
1138 "expected value string".format(size))
1139 if not isinstance(base, int):
1140 raise ValueError(
1141 "Invalid third argument to mkBitVector '{}', "
1142 "expected base given as integer".format(size))
1143 term.cterm = self.csolver.mkBitVector(
1144 <uint32_t> size,
1145 <const string&> str(val).encode(),
1146 <uint32_t> base)
1147 else:
1148 raise ValueError("Unexpected inputs to mkBitVector")
1149 return term
1150
1151 def mkConstArray(self, Sort sort, Term val):
1152 """ Create a constant array with the provided constant value stored at every
1153 index
1154
1155 :param sort: the sort of the constant array (must be an array sort)
1156 :param val: the constant value to store (must match the sort's element sort)
1157 :return: the constant array term
1158 """
1159 cdef Term term = Term(self)
1160 term.cterm = self.csolver.mkConstArray(sort.csort, val.cterm)
1161 return term
1162
1163 def mkPosInf(self, int exp, int sig):
1164 """Create a positive infinity floating-point constant.
1165
1166 :param exp: Number of bits in the exponent
1167 :param sig: Number of bits in the significand
1168 :return: the floating-point constant
1169 """
1170 cdef Term term = Term(self)
1171 term.cterm = self.csolver.mkPosInf(exp, sig)
1172 return term
1173
1174 def mkNegInf(self, int exp, int sig):
1175 """Create a negative infinity floating-point constant.
1176
1177 :param exp: Number of bits in the exponent
1178 :param sig: Number of bits in the significand
1179 :return: the floating-point constant
1180 """
1181 cdef Term term = Term(self)
1182 term.cterm = self.csolver.mkNegInf(exp, sig)
1183 return term
1184
1185 def mkNaN(self, int exp, int sig):
1186 """Create a not-a-number (NaN) floating-point constant.
1187
1188 :param exp: Number of bits in the exponent
1189 :param sig: Number of bits in the significand
1190 :return: the floating-point constant
1191 """
1192 cdef Term term = Term(self)
1193 term.cterm = self.csolver.mkNaN(exp, sig)
1194 return term
1195
1196 def mkPosZero(self, int exp, int sig):
1197 """Create a positive zero (+0.0) floating-point constant.
1198
1199 :param exp: Number of bits in the exponent
1200 :param sig: Number of bits in the significand
1201 :return: the floating-point constant
1202 """
1203 cdef Term term = Term(self)
1204 term.cterm = self.csolver.mkPosZero(exp, sig)
1205 return term
1206
1207 def mkNegZero(self, int exp, int sig):
1208 """Create a negative zero (+0.0) floating-point constant.
1209
1210 :param exp: Number of bits in the exponent
1211 :param sig: Number of bits in the significand
1212 :return: the floating-point constant
1213 """
1214 cdef Term term = Term(self)
1215 term.cterm = self.csolver.mkNegZero(exp, sig)
1216 return term
1217
1218 def mkRoundingMode(self, RoundingMode rm):
1219 """Create a roundingmode constant.
1220
1221 :param rm: the floating point rounding mode this constant represents
1222 """
1223 cdef Term term = Term(self)
1224 term.cterm = self.csolver.mkRoundingMode(<c_RoundingMode> rm.crm)
1225 return term
1226
1227 def mkUninterpretedConst(self, Sort sort, int index):
1228 """Create uninterpreted constant.
1229
1230 :param sort: Sort of the constant
1231 :param index: Index of the constant
1232 """
1233 cdef Term term = Term(self)
1234 term.cterm = self.csolver.mkUninterpretedConst(sort.csort, index)
1235 return term
1236
1237 def mkAbstractValue(self, index):
1238 """Create an abstract value constant.
1239 The given index needs to be positive.
1240
1241 :param index: Index of the abstract value
1242 """
1243 cdef Term term = Term(self)
1244 try:
1245 term.cterm = self.csolver.mkAbstractValue(str(index).encode())
1246 except:
1247 raise ValueError(
1248 "mkAbstractValue expects a str representing a number"
1249 " or an int, but got{}".format(index))
1250 return term
1251
1252 def mkFloatingPoint(self, int exp, int sig, Term val):
1253 """Create a floating-point constant.
1254
1255 :param exp: Size of the exponent
1256 :param sig: Size of the significand
1257 :param val: Value of the floating-point constant as a bit-vector term
1258 """
1259 cdef Term term = Term(self)
1260 term.cterm = self.csolver.mkFloatingPoint(exp, sig, val.cterm)
1261 return term
1262
1263 def mkConst(self, Sort sort, symbol=None):
1264 """
1265 Create (first-order) constant (0-arity function symbol).
1266
1267 SMT-LIB:
1268
1269 .. code-block:: smtlib
1270
1271 ( declare-const <symbol> <sort> )
1272 ( declare-fun <symbol> ( ) <sort> )
1273
1274 :param sort: the sort of the constant
1275 :param symbol: the name of the constant. If None, a default symbol is used.
1276 :return: the first-order constant
1277 """
1278 cdef Term term = Term(self)
1279 if symbol is None:
1280 term.cterm = self.csolver.mkConst(sort.csort)
1281 else:
1282 term.cterm = self.csolver.mkConst(sort.csort,
1283 (<str?> symbol).encode())
1284 return term
1285
1286 def mkVar(self, Sort sort, symbol=None):
1287 """Create a bound variable to be used in a binder (i.e. a quantifier, a
1288 lambda, or a witness binder).
1289
1290 :param sort: the sort of the variable
1291 :param symbol: the name of the variable
1292 :return: the variable
1293 """
1294 cdef Term term = Term(self)
1295 if symbol is None:
1296 term.cterm = self.csolver.mkVar(sort.csort)
1297 else:
1298 term.cterm = self.csolver.mkVar(sort.csort,
1299 (<str?> symbol).encode())
1300 return term
1301
1302 def mkDatatypeConstructorDecl(self, str name):
1303 """ :return: a datatype constructor declaration
1304 :param: `name` the constructor's name
1305 """
1306 cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl(self)
1307 ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
1308 return ddc
1309
1310 def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
1311 """Create a datatype declaration.
1312
1313 :param name: the name of the datatype
1314 :param isCoDatatype: true if a codatatype is to be constructed
1315 :return: the DatatypeDecl
1316 """
1317 cdef DatatypeDecl dd = DatatypeDecl(self)
1318 cdef vector[c_Sort] v
1319
1320 # argument cases
1321 if sorts_or_bool is None and isCoDatatype is None:
1322 dd.cdd = self.csolver.mkDatatypeDecl(name.encode())
1323 elif sorts_or_bool is not None and isCoDatatype is None:
1324 if isinstance(sorts_or_bool, bool):
1325 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1326 <bint> sorts_or_bool)
1327 elif isinstance(sorts_or_bool, Sort):
1328 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1329 (<Sort> sorts_or_bool).csort)
1330 elif isinstance(sorts_or_bool, list):
1331 for s in sorts_or_bool:
1332 v.push_back((<Sort?> s).csort)
1333 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1334 <const vector[c_Sort]&> v)
1335 else:
1336 raise ValueError("Unhandled second argument type {}"
1337 .format(type(sorts_or_bool)))
1338 elif sorts_or_bool is not None and isCoDatatype is not None:
1339 if isinstance(sorts_or_bool, Sort):
1340 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1341 (<Sort> sorts_or_bool).csort,
1342 <bint> isCoDatatype)
1343 elif isinstance(sorts_or_bool, list):
1344 for s in sorts_or_bool:
1345 v.push_back((<Sort?> s).csort)
1346 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1347 <const vector[c_Sort]&> v,
1348 <bint> isCoDatatype)
1349 else:
1350 raise ValueError("Unhandled second argument type {}"
1351 .format(type(sorts_or_bool)))
1352 else:
1353 raise ValueError("Can't create DatatypeDecl with {}".format([type(a)
1354 for a in [name,
1355 sorts_or_bool,
1356 isCoDatatype]]))
1357
1358 return dd
1359
1360 def simplify(self, Term t):
1361 """Simplify a formula without doing "much" work. Does not involve the
1362 SAT Engine in the simplification, but uses the current definitions,
1363 assertions, and the current partial model, if one has been constructed.
1364 It also involves theory normalization.
1365
1366 :param t: the formula to simplify
1367 :return: the simplified formula
1368 """
1369 cdef Term term = Term(self)
1370 term.cterm = self.csolver.simplify(t.cterm)
1371 return term
1372
1373 def assertFormula(self, Term term):
1374 """ Assert a formula
1375
1376 SMT-LIB:
1377
1378 .. code-block:: smtlib
1379
1380 ( assert <term> )
1381
1382 :param term: the formula to assert
1383 """
1384 self.csolver.assertFormula(term.cterm)
1385
1386 def checkSat(self):
1387 """
1388 Check satisfiability.
1389
1390 SMT-LIB:
1391
1392 .. code-block:: smtlib
1393
1394 ( check-sat )
1395
1396 :return: the result of the satisfiability check.
1397 """
1398 cdef Result r = Result()
1399 r.cr = self.csolver.checkSat()
1400 return r
1401
1402 def mkSygusGrammar(self, boundVars, ntSymbols):
1403 """Create a SyGuS grammar. The first non-terminal is treated as the
1404 starting non-terminal, so the order of non-terminals matters.
1405
1406 :param boundVars: the parameters to corresponding synth-fun/synth-inv
1407 :param ntSymbols: the pre-declaration of the non-terminal symbols
1408 :return: the grammar
1409 """
1410 cdef Grammar grammar = Grammar(self)
1411 cdef vector[c_Term] bvc
1412 cdef vector[c_Term] ntc
1413 for bv in boundVars:
1414 bvc.push_back((<Term?> bv).cterm)
1415 for nt in ntSymbols:
1416 ntc.push_back((<Term?> nt).cterm)
1417 grammar.cgrammar = self.csolver.mkSygusGrammar(<const vector[c_Term]&> bvc, <const vector[c_Term]&> ntc)
1418 return grammar
1419
1420 def mkSygusVar(self, Sort sort, str symbol=""):
1421 """Append symbol to the current list of universal variables.
1422
1423 SyGuS v2:
1424
1425 .. code-block:: smtlib
1426
1427 ( declare-var <symbol> <sort> )
1428
1429 :param sort: the sort of the universal variable
1430 :param symbol: the name of the universal variable
1431 :return: the universal variable
1432 """
1433 cdef Term term = Term(self)
1434 term.cterm = self.csolver.mkSygusVar(sort.csort, symbol.encode())
1435 return term
1436
1437 def addSygusConstraint(self, Term t):
1438 """
1439 Add a formula to the set of SyGuS constraints.
1440
1441 SyGuS v2:
1442
1443 .. code-block:: smtlib
1444
1445 ( constraint <term> )
1446
1447 :param term: the formula to add as a constraint
1448 """
1449 self.csolver.addSygusConstraint(t.cterm)
1450
1451 def addSygusInvConstraint(self, Term inv_f, Term pre_f, Term trans_f, Term post_f):
1452 """Add a set of SyGuS constraints to the current state that correspond to an
1453 invariant synthesis problem.
1454
1455 SyGuS v2:
1456
1457 .. code-block:: smtlib
1458
1459 ( inv-constraint <inv> <pre> <trans> <post> )
1460
1461 :param inv: the function-to-synthesize
1462 :param pre: the pre-condition
1463 :param trans: the transition relation
1464 :param post: the post-condition
1465 """
1466 self.csolver.addSygusInvConstraint(inv_f.cterm, pre_f.cterm, trans_f.cterm, post_f.cterm)
1467
1468 def synthFun(self, str symbol, bound_vars, Sort sort, Grammar grammar=None):
1469 """
1470 Synthesize n-ary function following specified syntactic constraints.
1471
1472 SyGuS v2:
1473
1474 .. code-block:: smtlib
1475
1476 ( synth-fun <symbol> ( <boundVars>* ) <sort> <g> )
1477
1478 :param symbol: the name of the function
1479 :param boundVars: the parameters to this function
1480 :param sort: the sort of the return value of this function
1481 :param grammar: the syntactic constraints
1482 :return: the function
1483 """
1484 cdef Term term = Term(self)
1485 cdef vector[c_Term] v
1486 for bv in bound_vars:
1487 v.push_back((<Term?> bv).cterm)
1488 if grammar is None:
1489 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort)
1490 else:
1491 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort, grammar.cgrammar)
1492 return term
1493
1494 def checkSynth(self):
1495 """
1496 Try to find a solution for the synthesis conjecture corresponding to the
1497 current list of functions-to-synthesize, universal variables and
1498 constraints.
1499
1500 SyGuS v2:
1501
1502 .. code-block:: smtlib
1503
1504 ( check-synth )
1505
1506 :return: the result of the synthesis conjecture.
1507 """
1508 cdef Result r = Result()
1509 r.cr = self.csolver.checkSynth()
1510 return r
1511
1512 def getSynthSolution(self, Term term):
1513 """Get the synthesis solution of the given term. This method should be
1514 called immediately after the solver answers unsat for sygus input.
1515
1516 :param term: the term for which the synthesis solution is queried
1517 :return: the synthesis solution of the given term
1518 """
1519 cdef Term t = Term(self)
1520 t.cterm = self.csolver.getSynthSolution(term.cterm)
1521 return t
1522
1523 def getSynthSolutions(self, list terms):
1524 """Get the synthesis solutions of the given terms. This method should be
1525 called immediately after the solver answers unsat for sygus input.
1526
1527 :param terms: the terms for which the synthesis solutions is queried
1528 :return: the synthesis solutions of the given terms
1529 """
1530 result = []
1531 cdef vector[c_Term] vec
1532 for t in terms:
1533 vec.push_back((<Term?> t).cterm)
1534 cresult = self.csolver.getSynthSolutions(vec)
1535 for s in cresult:
1536 term = Term(self)
1537 term.cterm = s
1538 result.append(term)
1539 return result
1540
1541
1542 def synthInv(self, symbol, bound_vars, Grammar grammar=None):
1543 """
1544 Synthesize invariant.
1545
1546 SyGuS v2:
1547
1548 .. code-block:: smtlib
1549
1550 ( synth-inv <symbol> ( <boundVars>* ) <grammar> )
1551
1552 :param symbol: the name of the invariant
1553 :param boundVars: the parameters to this invariant
1554 :param grammar: the syntactic constraints
1555 :return: the invariant
1556 """
1557 cdef Term term = Term(self)
1558 cdef vector[c_Term] v
1559 for bv in bound_vars:
1560 v.push_back((<Term?> bv).cterm)
1561 if grammar is None:
1562 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v)
1563 else:
1564 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v, grammar.cgrammar)
1565 return term
1566
1567 @expand_list_arg(num_req_args=0)
1568 def checkSatAssuming(self, *assumptions):
1569 """ Check satisfiability assuming the given formula.
1570
1571 SMT-LIB:
1572
1573 .. code-block:: smtlib
1574
1575 ( check-sat-assuming ( <prop_literal> ) )
1576
1577 :param assumptions: the formulas to assume, as a list or as distinct arguments
1578 :return: the result of the satisfiability check.
1579 """
1580 cdef Result r = Result()
1581 # used if assumptions is a list of terms
1582 cdef vector[c_Term] v
1583 for a in assumptions:
1584 v.push_back((<Term?> a).cterm)
1585 r.cr = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
1586 return r
1587
1588 @expand_list_arg(num_req_args=0)
1589 def checkEntailed(self, *assumptions):
1590 """Check entailment of the given formula w.r.t. the current set of assertions.
1591
1592 :param terms: the formulas to check entailment for, as a list or as distinct arguments
1593 :return: the result of the entailment check.
1594 """
1595 cdef Result r = Result()
1596 # used if assumptions is a list of terms
1597 cdef vector[c_Term] v
1598 for a in assumptions:
1599 v.push_back((<Term?> a).cterm)
1600 r.cr = self.csolver.checkEntailed(<const vector[c_Term]&> v)
1601 return r
1602
1603 @expand_list_arg(num_req_args=1)
1604 def declareDatatype(self, str symbol, *ctors):
1605 """
1606 Create datatype sort.
1607
1608 SMT-LIB:
1609
1610 .. code-block:: smtlib
1611
1612 ( declare-datatype <symbol> <datatype_decl> )
1613
1614 :param symbol: the name of the datatype sort
1615 :param ctors: the constructor declarations of the datatype sort, as a list or as distinct arguments
1616 :return: the datatype sort
1617 """
1618 cdef Sort sort = Sort(self)
1619 cdef vector[c_DatatypeConstructorDecl] v
1620
1621 for c in ctors:
1622 v.push_back((<DatatypeConstructorDecl?> c).cddc)
1623 sort.csort = self.csolver.declareDatatype(symbol.encode(), v)
1624 return sort
1625
1626 def declareFun(self, str symbol, list sorts, Sort sort):
1627 """Declare n-ary function symbol.
1628
1629 SMT-LIB:
1630
1631 .. code-block:: smtlib
1632
1633 ( declare-fun <symbol> ( <sort>* ) <sort> )
1634
1635 :param symbol: the name of the function
1636 :param sorts: the sorts of the parameters to this function
1637 :param sort: the sort of the return value of this function
1638 :return: the function
1639 """
1640 cdef Term term = Term(self)
1641 cdef vector[c_Sort] v
1642 for s in sorts:
1643 v.push_back((<Sort?> s).csort)
1644 term.cterm = self.csolver.declareFun(symbol.encode(),
1645 <const vector[c_Sort]&> v,
1646 sort.csort)
1647 return term
1648
1649 def declareSort(self, str symbol, int arity):
1650 """Declare uninterpreted sort.
1651
1652 SMT-LIB:
1653
1654 .. code-block:: smtlib
1655
1656 ( declare-sort <symbol> <numeral> )
1657
1658 :param symbol: the name of the sort
1659 :param arity: the arity of the sort
1660 :return: the sort
1661 """
1662 cdef Sort sort = Sort(self)
1663 sort.csort = self.csolver.declareSort(symbol.encode(), arity)
1664 return sort
1665
1666 def defineFun(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1667 """
1668 Define n-ary function.
1669 Supports two uses:
1670
1671 - ``Term defineFun(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1672 - ``Term defineFun(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1673
1674
1675 SMT-LIB:
1676
1677 .. code-block:: smtlib
1678
1679 ( define-fun <function_def> )
1680
1681 :param symbol: the name of the function
1682 :param bound_vars: the parameters to this function
1683 :param sort: the sort of the return value of this function
1684 :param term: the function body
1685 :param global: determines whether this definition is global (i.e. persists when popping the context)
1686 :return: the function
1687 """
1688 cdef Term term = Term(self)
1689 cdef vector[c_Term] v
1690 for bv in bound_vars:
1691 v.push_back((<Term?> bv).cterm)
1692
1693 if t is not None:
1694 term.cterm = self.csolver.defineFun((<str?> sym_or_fun).encode(),
1695 <const vector[c_Term] &> v,
1696 (<Sort?> sort_or_term).csort,
1697 (<Term?> t).cterm,
1698 <bint> glbl)
1699 else:
1700 term.cterm = self.csolver.defineFun((<Term?> sym_or_fun).cterm,
1701 <const vector[c_Term]&> v,
1702 (<Term?> sort_or_term).cterm,
1703 <bint> glbl)
1704
1705 return term
1706
1707 def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1708 """Define recursive functions.
1709
1710 Supports two uses:
1711
1712 - ``Term defineFunRec(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1713 - ``Term defineFunRec(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1714
1715
1716 SMT-LIB:
1717
1718 .. code-block:: smtlib
1719
1720 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1721
1722 Create elements of parameter ``funs`` with mkConst().
1723
1724 :param funs: the sorted functions
1725 :param bound_vars: the list of parameters to the functions
1726 :param terms: the list of function bodies of the functions
1727 :param global: determines whether this definition is global (i.e. persists when popping the context)
1728 :return: the function
1729 """
1730 cdef Term term = Term(self)
1731 cdef vector[c_Term] v
1732 for bv in bound_vars:
1733 v.push_back((<Term?> bv).cterm)
1734
1735 if t is not None:
1736 term.cterm = self.csolver.defineFunRec((<str?> sym_or_fun).encode(),
1737 <const vector[c_Term] &> v,
1738 (<Sort?> sort_or_term).csort,
1739 (<Term?> t).cterm,
1740 <bint> glbl)
1741 else:
1742 term.cterm = self.csolver.defineFunRec((<Term?> sym_or_fun).cterm,
1743 <const vector[c_Term]&> v,
1744 (<Term?> sort_or_term).cterm,
1745 <bint> glbl)
1746
1747 return term
1748
1749 def defineFunsRec(self, funs, bound_vars, terms):
1750 """Define recursive functions.
1751
1752 SMT-LIB:
1753
1754 .. code-block:: smtlib
1755
1756 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1757
1758 Create elements of parameter ``funs`` with mkConst().
1759
1760 :param funs: the sorted functions
1761 :param bound_vars: the list of parameters to the functions
1762 :param terms: the list of function bodies of the functions
1763 :param global: determines whether this definition is global (i.e. persists when popping the context)
1764 :return: the function
1765 """
1766 cdef vector[c_Term] vf
1767 cdef vector[vector[c_Term]] vbv
1768 cdef vector[c_Term] vt
1769
1770 for f in funs:
1771 vf.push_back((<Term?> f).cterm)
1772
1773 cdef vector[c_Term] temp
1774 for v in bound_vars:
1775 for t in v:
1776 temp.push_back((<Term?> t).cterm)
1777 vbv.push_back(temp)
1778 temp.clear()
1779
1780 for t in terms:
1781 vf.push_back((<Term?> t).cterm)
1782
1783 def getAssertions(self):
1784 """Get the list of asserted formulas.
1785
1786 SMT-LIB:
1787
1788 .. code-block:: smtlib
1789
1790 ( get-assertions )
1791
1792 :return: the list of asserted formulas
1793 """
1794 assertions = []
1795 for a in self.csolver.getAssertions():
1796 term = Term(self)
1797 term.cterm = a
1798 assertions.append(term)
1799 return assertions
1800
1801 def getInfo(self, str flag):
1802 """Get info from the solver.
1803
1804 SMT-LIB:
1805
1806 .. code-block:: smtlib
1807
1808 ( get-info <info_flag> )
1809
1810 :param flag: the info flag
1811 :return: the info
1812 """
1813 return self.csolver.getInfo(flag.encode())
1814
1815 def getOption(self, str option):
1816 """Get the value of a given option.
1817
1818 SMT-LIB:
1819
1820 .. code-block:: smtlib
1821
1822 ( get-option <keyword> )
1823
1824 :param option: the option for which the value is queried
1825 :return: a string representation of the option value
1826 """
1827 return self.csolver.getOption(option.encode())
1828
1829 def getUnsatAssumptions(self):
1830 """
1831 Get the set of unsat ("failed") assumptions.
1832
1833 SMT-LIB:
1834
1835 .. code-block:: smtlib
1836
1837 ( get-unsat-assumptions )
1838
1839 Requires to enable option :ref:`produce-unsat-assumptions <lbl-option-produce-unsat-assumptions>`.
1840
1841 :return: the set of unsat assumptions.
1842 """
1843 assumptions = []
1844 for a in self.csolver.getUnsatAssumptions():
1845 term = Term(self)
1846 term.cterm = a
1847 assumptions.append(term)
1848 return assumptions
1849
1850 def getUnsatCore(self):
1851 """Get the unsatisfiable core.
1852
1853 SMT-LIB:
1854
1855 .. code-block:: smtlib
1856
1857 ( get-unsat-core )
1858
1859 Requires to enable option :ref:`produce-unsat-cores <lbl-produce-unsat-cores>`.
1860
1861 :return: a set of terms representing the unsatisfiable core
1862 """
1863 core = []
1864 for a in self.csolver.getUnsatCore():
1865 term = Term(self)
1866 term.cterm = a
1867 core.append(term)
1868 return core
1869
1870 def getValue(self, Term t):
1871 """Get the value of the given term in the current model.
1872
1873 SMT-LIB:
1874
1875 .. code-block:: smtlib
1876
1877 ( get-value ( <term> ) )
1878
1879 :param term: the term for which the value is queried
1880 :return: the value of the given term
1881 """
1882 cdef Term term = Term(self)
1883 term.cterm = self.csolver.getValue(t.cterm)
1884 return term
1885
1886 def getModelDomainElements(self, Sort s):
1887 """
1888 Get the domain elements of uninterpreted sort s in the current model. The
1889 current model interprets s as the finite sort whose domain elements are
1890 given in the return value of this method.
1891
1892 :param s: The uninterpreted sort in question
1893 :return: the domain elements of s in the current model
1894 """
1895 result = []
1896 cresult = self.csolver.getModelDomainElements(s.csort)
1897 for e in cresult:
1898 term = Term(self)
1899 term.cterm = e
1900 result.append(term)
1901 return result
1902
1903 def isModelCoreSymbol(self, Term v):
1904 """This returns false if the model value of free constant v was not
1905 essential for showing the satisfiability of the last call to checkSat
1906 using the current model. This method will only return false (for any v)
1907 if the model-cores option has been set.
1908
1909 :param v: The term in question
1910 :return: true if v is a model core symbol
1911 """
1912 return self.csolver.isModelCoreSymbol(v.cterm)
1913
1914 def getSeparationHeap(self):
1915 """When using separation logic, obtain the term for the heap.
1916
1917 :return: The term for the heap
1918 """
1919 cdef Term term = Term(self)
1920 term.cterm = self.csolver.getSeparationHeap()
1921 return term
1922
1923 def getSeparationNilTerm(self):
1924 """When using separation logic, obtain the term for nil.
1925
1926 :return: The term for nil
1927 """
1928 cdef Term term = Term(self)
1929 term.cterm = self.csolver.getSeparationNilTerm()
1930 return term
1931
1932 def declareSeparationHeap(self, Sort locType, Sort dataType):
1933 """
1934 When using separation logic, this sets the location sort and the
1935 datatype sort to the given ones. This method should be invoked exactly
1936 once, before any separation logic constraints are provided.
1937
1938 :param locSort: The location sort of the heap
1939 :param dataSort: The data sort of the heap
1940 """
1941 self.csolver.declareSeparationHeap(locType.csort, dataType.csort)
1942
1943 def declarePool(self, str symbol, Sort sort, initValue):
1944 """Declare a symbolic pool of terms with the given initial value.
1945
1946 SMT-LIB:
1947
1948 .. code-block:: smtlib
1949
1950 ( declare-pool <symbol> <sort> ( <term>* ) )
1951
1952 :param symbol: The name of the pool
1953 :param sort: The sort of the elements of the pool.
1954 :param initValue: The initial value of the pool
1955 """
1956 cdef Term term = Term(self)
1957 cdef vector[c_Term] niv
1958 for v in initValue:
1959 niv.push_back((<Term?> v).cterm)
1960 term.cterm = self.csolver.declarePool(symbol.encode(), sort.csort, niv)
1961 return term
1962
1963 def pop(self, nscopes=1):
1964 """Pop ``nscopes`` level(s) from the assertion stack.
1965
1966 SMT-LIB:
1967
1968 .. code-block:: smtlib
1969
1970 ( pop <numeral> )
1971
1972 :param nscopes: the number of levels to pop
1973 """
1974 self.csolver.pop(nscopes)
1975
1976 def push(self, nscopes=1):
1977 """ Push ``nscopes`` level(s) to the assertion stack.
1978
1979 SMT-LIB:
1980
1981 .. code-block:: smtlib
1982
1983 ( push <numeral> )
1984
1985 :param nscopes: the number of levels to push
1986 """
1987 self.csolver.push(nscopes)
1988
1989 def resetAssertions(self):
1990 """
1991 Remove all assertions.
1992
1993 SMT-LIB:
1994
1995 .. code-block:: smtlib
1996
1997 ( reset-assertions )
1998
1999 """
2000 self.csolver.resetAssertions()
2001
2002 def setInfo(self, str keyword, str value):
2003 """Set info.
2004
2005 SMT-LIB:
2006
2007 .. code-block:: smtlib
2008
2009 ( set-info <attribute> )
2010
2011 :param keyword: the info flag
2012 :param value: the value of the info flag
2013 """
2014 self.csolver.setInfo(keyword.encode(), value.encode())
2015
2016 def setLogic(self, str logic):
2017 """Set logic.
2018
2019 SMT-LIB:
2020
2021 .. code-block:: smtlib
2022
2023 ( set-logic <symbol> )
2024
2025 :param logic: the logic to set
2026 """
2027 self.csolver.setLogic(logic.encode())
2028
2029 def setOption(self, str option, str value):
2030 """Set option.
2031
2032 SMT-LIB:
2033
2034 .. code-block:: smtlib
2035
2036 ( set-option <option> )
2037
2038 :param option: the option name
2039 :param value: the option value
2040 """
2041 self.csolver.setOption(option.encode(), value.encode())
2042
2043
2044 cdef class Sort:
2045 cdef c_Sort csort
2046 cdef Solver solver
2047 def __cinit__(self, Solver solver):
2048 # csort always set by Solver
2049 self.solver = solver
2050
2051 def __eq__(self, Sort other):
2052 return self.csort == other.csort
2053
2054 def __ne__(self, Sort other):
2055 return self.csort != other.csort
2056
2057 def __lt__(self, Sort other):
2058 return self.csort < other.csort
2059
2060 def __gt__(self, Sort other):
2061 return self.csort > other.csort
2062
2063 def __le__(self, Sort other):
2064 return self.csort <= other.csort
2065
2066 def __ge__(self, Sort other):
2067 return self.csort >= other.csort
2068
2069 def __str__(self):
2070 return self.csort.toString().decode()
2071
2072 def __repr__(self):
2073 return self.csort.toString().decode()
2074
2075 def __hash__(self):
2076 return csorthash(self.csort)
2077
2078 def isBoolean(self):
2079 return self.csort.isBoolean()
2080
2081 def isInteger(self):
2082 return self.csort.isInteger()
2083
2084 def isReal(self):
2085 return self.csort.isReal()
2086
2087 def isString(self):
2088 return self.csort.isString()
2089
2090 def isRegExp(self):
2091 return self.csort.isRegExp()
2092
2093 def isRoundingMode(self):
2094 return self.csort.isRoundingMode()
2095
2096 def isBitVector(self):
2097 return self.csort.isBitVector()
2098
2099 def isFloatingPoint(self):
2100 return self.csort.isFloatingPoint()
2101
2102 def isDatatype(self):
2103 return self.csort.isDatatype()
2104
2105 def isParametricDatatype(self):
2106 return self.csort.isParametricDatatype()
2107
2108 def isConstructor(self):
2109 return self.csort.isConstructor()
2110
2111 def isSelector(self):
2112 return self.csort.isSelector()
2113
2114 def isTester(self):
2115 return self.csort.isTester()
2116
2117 def isFunction(self):
2118 return self.csort.isFunction()
2119
2120 def isPredicate(self):
2121 return self.csort.isPredicate()
2122
2123 def isTuple(self):
2124 return self.csort.isTuple()
2125
2126 def isRecord(self):
2127 return self.csort.isRecord()
2128
2129 def isArray(self):
2130 return self.csort.isArray()
2131
2132 def isSet(self):
2133 return self.csort.isSet()
2134
2135 def isBag(self):
2136 return self.csort.isBag()
2137
2138 def isSequence(self):
2139 return self.csort.isSequence()
2140
2141 def isUninterpretedSort(self):
2142 return self.csort.isUninterpretedSort()
2143
2144 def isSortConstructor(self):
2145 return self.csort.isSortConstructor()
2146
2147 def isFirstClass(self):
2148 return self.csort.isFirstClass()
2149
2150 def isFunctionLike(self):
2151 return self.csort.isFunctionLike()
2152
2153 def isSubsortOf(self, Sort sort):
2154 return self.csort.isSubsortOf(sort.csort)
2155
2156 def isComparableTo(self, Sort sort):
2157 return self.csort.isComparableTo(sort.csort)
2158
2159 def getDatatype(self):
2160 cdef Datatype d = Datatype(self.solver)
2161 d.cd = self.csort.getDatatype()
2162 return d
2163
2164 def instantiate(self, params):
2165 cdef Sort sort = Sort(self.solver)
2166 cdef vector[c_Sort] v
2167 for s in params:
2168 v.push_back((<Sort?> s).csort)
2169 sort.csort = self.csort.instantiate(v)
2170 return sort
2171
2172 def getConstructorArity(self):
2173 return self.csort.getConstructorArity()
2174
2175 def getConstructorDomainSorts(self):
2176 domain_sorts = []
2177 for s in self.csort.getConstructorDomainSorts():
2178 sort = Sort(self.solver)
2179 sort.csort = s
2180 domain_sorts.append(sort)
2181 return domain_sorts
2182
2183 def getConstructorCodomainSort(self):
2184 cdef Sort sort = Sort(self.solver)
2185 sort.csort = self.csort.getConstructorCodomainSort()
2186 return sort
2187
2188 def getSelectorDomainSort(self):
2189 cdef Sort sort = Sort(self.solver)
2190 sort.csort = self.csort.getSelectorDomainSort()
2191 return sort
2192
2193 def getSelectorCodomainSort(self):
2194 cdef Sort sort = Sort(self.solver)
2195 sort.csort = self.csort.getSelectorCodomainSort()
2196 return sort
2197
2198 def getTesterDomainSort(self):
2199 cdef Sort sort = Sort(self.solver)
2200 sort.csort = self.csort.getTesterDomainSort()
2201 return sort
2202
2203 def getTesterCodomainSort(self):
2204 cdef Sort sort = Sort(self.solver)
2205 sort.csort = self.csort.getTesterCodomainSort()
2206 return sort
2207
2208 def getFunctionArity(self):
2209 return self.csort.getFunctionArity()
2210
2211 def getFunctionDomainSorts(self):
2212 domain_sorts = []
2213 for s in self.csort.getFunctionDomainSorts():
2214 sort = Sort(self.solver)
2215 sort.csort = s
2216 domain_sorts.append(sort)
2217 return domain_sorts
2218
2219 def getFunctionCodomainSort(self):
2220 cdef Sort sort = Sort(self.solver)
2221 sort.csort = self.csort.getFunctionCodomainSort()
2222 return sort
2223
2224 def getArrayIndexSort(self):
2225 cdef Sort sort = Sort(self.solver)
2226 sort.csort = self.csort.getArrayIndexSort()
2227 return sort
2228
2229 def getArrayElementSort(self):
2230 cdef Sort sort = Sort(self.solver)
2231 sort.csort = self.csort.getArrayElementSort()
2232 return sort
2233
2234 def getSetElementSort(self):
2235 cdef Sort sort = Sort(self.solver)
2236 sort.csort = self.csort.getSetElementSort()
2237 return sort
2238
2239 def getBagElementSort(self):
2240 cdef Sort sort = Sort(self.solver)
2241 sort.csort = self.csort.getBagElementSort()
2242 return sort
2243
2244 def getSequenceElementSort(self):
2245 cdef Sort sort = Sort(self.solver)
2246 sort.csort = self.csort.getSequenceElementSort()
2247 return sort
2248
2249 def getUninterpretedSortName(self):
2250 return self.csort.getUninterpretedSortName().decode()
2251
2252 def isUninterpretedSortParameterized(self):
2253 return self.csort.isUninterpretedSortParameterized()
2254
2255 def getUninterpretedSortParamSorts(self):
2256 param_sorts = []
2257 for s in self.csort.getUninterpretedSortParamSorts():
2258 sort = Sort(self.solver)
2259 sort.csort = s
2260 param_sorts.append(sort)
2261 return param_sorts
2262
2263 def getSortConstructorName(self):
2264 return self.csort.getSortConstructorName().decode()
2265
2266 def getSortConstructorArity(self):
2267 return self.csort.getSortConstructorArity()
2268
2269 def getBVSize(self):
2270 return self.csort.getBVSize()
2271
2272 def getFPExponentSize(self):
2273 return self.csort.getFPExponentSize()
2274
2275 def getFPSignificandSize(self):
2276 return self.csort.getFPSignificandSize()
2277
2278 def getDatatypeParamSorts(self):
2279 param_sorts = []
2280 for s in self.csort.getDatatypeParamSorts():
2281 sort = Sort(self.solver)
2282 sort.csort = s
2283 param_sorts.append(sort)
2284 return param_sorts
2285
2286 def getDatatypeArity(self):
2287 return self.csort.getDatatypeArity()
2288
2289 def getTupleLength(self):
2290 return self.csort.getTupleLength()
2291
2292 def getTupleSorts(self):
2293 tuple_sorts = []
2294 for s in self.csort.getTupleSorts():
2295 sort = Sort(self.solver)
2296 sort.csort = s
2297 tuple_sorts.append(sort)
2298 return tuple_sorts
2299
2300
2301 cdef class Term:
2302 cdef c_Term cterm
2303 cdef Solver solver
2304 def __cinit__(self, Solver solver):
2305 # cterm always set in the Solver object
2306 self.solver = solver
2307
2308 def __eq__(self, Term other):
2309 return self.cterm == other.cterm
2310
2311 def __ne__(self, Term other):
2312 return self.cterm != other.cterm
2313
2314 def __lt__(self, Term other):
2315 return self.cterm < other.cterm
2316
2317 def __gt__(self, Term other):
2318 return self.cterm > other.cterm
2319
2320 def __le__(self, Term other):
2321 return self.cterm <= other.cterm
2322
2323 def __ge__(self, Term other):
2324 return self.cterm >= other.cterm
2325
2326 def __getitem__(self, int index):
2327 cdef Term term = Term(self.solver)
2328 if index >= 0:
2329 term.cterm = self.cterm[index]
2330 else:
2331 raise ValueError("Expecting a non-negative integer or string")
2332 return term
2333
2334 def __str__(self):
2335 return self.cterm.toString().decode()
2336
2337 def __repr__(self):
2338 return self.cterm.toString().decode()
2339
2340 def __iter__(self):
2341 for ci in self.cterm:
2342 term = Term(self.solver)
2343 term.cterm = ci
2344 yield term
2345
2346 def __hash__(self):
2347 return ctermhash(self.cterm)
2348
2349 def getNumChildren(self):
2350 return self.cterm.getNumChildren()
2351
2352 def getId(self):
2353 return self.cterm.getId()
2354
2355 def getKind(self):
2356 return kind(<int> self.cterm.getKind())
2357
2358 def getSort(self):
2359 cdef Sort sort = Sort(self.solver)
2360 sort.csort = self.cterm.getSort()
2361 return sort
2362
2363 def substitute(self, term_or_list_1, term_or_list_2):
2364 # The resulting term after substitution
2365 cdef Term term = Term(self.solver)
2366 # lists for substitutions
2367 cdef vector[c_Term] ces
2368 cdef vector[c_Term] creplacements
2369
2370 # normalize the input parameters to be lists
2371 if isinstance(term_or_list_1, list):
2372 assert isinstance(term_or_list_2, list)
2373 es = term_or_list_1
2374 replacements = term_or_list_2
2375 if len(es) != len(replacements):
2376 raise RuntimeError("Expecting list inputs to substitute to "
2377 "have the same length but got: "
2378 "{} and {}".format(len(es), len(replacements)))
2379
2380 for e, r in zip(es, replacements):
2381 ces.push_back((<Term?> e).cterm)
2382 creplacements.push_back((<Term?> r).cterm)
2383
2384 else:
2385 # add the single elements to the vectors
2386 ces.push_back((<Term?> term_or_list_1).cterm)
2387 creplacements.push_back((<Term?> term_or_list_2).cterm)
2388
2389 # call the API substitute method with lists
2390 term.cterm = self.cterm.substitute(ces, creplacements)
2391 return term
2392
2393 def hasOp(self):
2394 return self.cterm.hasOp()
2395
2396 def getOp(self):
2397 cdef Op op = Op(self.solver)
2398 op.cop = self.cterm.getOp()
2399 return op
2400
2401 def isNull(self):
2402 return self.cterm.isNull()
2403
2404 def notTerm(self):
2405 cdef Term term = Term(self.solver)
2406 term.cterm = self.cterm.notTerm()
2407 return term
2408
2409 def andTerm(self, Term t):
2410 cdef Term term = Term(self.solver)
2411 term.cterm = self.cterm.andTerm((<Term> t).cterm)
2412 return term
2413
2414 def orTerm(self, Term t):
2415 cdef Term term = Term(self.solver)
2416 term.cterm = self.cterm.orTerm(t.cterm)
2417 return term
2418
2419 def xorTerm(self, Term t):
2420 cdef Term term = Term(self.solver)
2421 term.cterm = self.cterm.xorTerm(t.cterm)
2422 return term
2423
2424 def eqTerm(self, Term t):
2425 cdef Term term = Term(self.solver)
2426 term.cterm = self.cterm.eqTerm(t.cterm)
2427 return term
2428
2429 def impTerm(self, Term t):
2430 cdef Term term = Term(self.solver)
2431 term.cterm = self.cterm.impTerm(t.cterm)
2432 return term
2433
2434 def iteTerm(self, Term then_t, Term else_t):
2435 cdef Term term = Term(self.solver)
2436 term.cterm = self.cterm.iteTerm(then_t.cterm, else_t.cterm)
2437 return term
2438
2439 def isConstArray(self):
2440 return self.cterm.isConstArray()
2441
2442 def getConstArrayBase(self):
2443 cdef Term term = Term(self.solver)
2444 term.cterm = self.cterm.getConstArrayBase()
2445 return term
2446
2447 def isBooleanValue(self):
2448 return self.cterm.isBooleanValue()
2449
2450 def getBooleanValue(self):
2451 return self.cterm.getBooleanValue()
2452
2453 def isStringValue(self):
2454 return self.cterm.isStringValue()
2455
2456 def getStringValue(self):
2457 cdef Py_ssize_t size
2458 cdef c_wstring s = self.cterm.getStringValue()
2459 return PyUnicode_FromWideChar(s.data(), s.size())
2460
2461 def isIntegerValue(self):
2462 return self.cterm.isIntegerValue()
2463 def isAbstractValue(self):
2464 return self.cterm.isAbstractValue()
2465
2466 def getAbstractValue(self):
2467 return self.cterm.getAbstractValue().decode()
2468
2469 def isFloatingPointPosZero(self):
2470 return self.cterm.isFloatingPointPosZero()
2471
2472 def isFloatingPointNegZero(self):
2473 return self.cterm.isFloatingPointNegZero()
2474
2475 def isFloatingPointPosInf(self):
2476 return self.cterm.isFloatingPointPosInf()
2477
2478 def isFloatingPointNegInf(self):
2479 return self.cterm.isFloatingPointNegInf()
2480
2481 def isFloatingPointNaN(self):
2482 return self.cterm.isFloatingPointNaN()
2483
2484 def isFloatingPointValue(self):
2485 return self.cterm.isFloatingPointValue()
2486
2487 def getFloatingPointValue(self):
2488 cdef c_tuple[uint32_t, uint32_t, c_Term] t = self.cterm.getFloatingPointValue()
2489 cdef Term term = Term(self.solver)
2490 term.cterm = get2(t)
2491 return (get0(t), get1(t), term)
2492
2493 def isSetValue(self):
2494 return self.cterm.isSetValue()
2495
2496 def getSetValue(self):
2497 elems = set()
2498 for e in self.cterm.getSetValue():
2499 term = Term(self.solver)
2500 term.cterm = e
2501 elems.add(term)
2502 return elems
2503
2504 def isSequenceValue(self):
2505 return self.cterm.isSequenceValue()
2506
2507 def getSequenceValue(self):
2508 elems = []
2509 for e in self.cterm.getSequenceValue():
2510 term = Term(self.solver)
2511 term.cterm = e
2512 elems.append(term)
2513 return elems
2514
2515 def isUninterpretedValue(self):
2516 return self.cterm.isUninterpretedValue()
2517
2518 def getUninterpretedValue(self):
2519 cdef pair[c_Sort, int32_t] p = self.cterm.getUninterpretedValue()
2520 cdef Sort sort = Sort(self.solver)
2521 sort.csort = p.first
2522 i = p.second
2523 return (sort, i)
2524
2525 def isTupleValue(self):
2526 return self.cterm.isTupleValue()
2527
2528 def getTupleValue(self):
2529 elems = []
2530 for e in self.cterm.getTupleValue():
2531 term = Term(self.solver)
2532 term.cterm = e
2533 elems.append(term)
2534 return elems
2535
2536 def getIntegerValue(self):
2537 return int(self.cterm.getIntegerValue().decode())
2538
2539 def isRealValue(self):
2540 return self.cterm.isRealValue()
2541
2542 def getRealValue(self):
2543 """Returns the value of a real term as a Fraction"""
2544 return Fraction(self.cterm.getRealValue().decode())
2545
2546 def isBitVectorValue(self):
2547 return self.cterm.isBitVectorValue()
2548
2549 def getBitVectorValue(self, base = 2):
2550 """Returns the value of a bit-vector term as a 0/1 string"""
2551 return self.cterm.getBitVectorValue(base).decode()
2552
2553 def toPythonObj(self):
2554 """
2555 Converts a constant value Term to a Python object.
2556
2557 Currently supports:
2558 Boolean -- returns a Python bool
2559 Int -- returns a Python int
2560 Real -- returns a Python Fraction
2561 BV -- returns a Python int (treats BV as unsigned)
2562 String -- returns a Python Unicode string
2563 Array -- returns a Python dict mapping indices to values
2564 -- the constant base is returned as the default value
2565 """
2566
2567 if self.isBooleanValue():
2568 return self.getBooleanValue()
2569 elif self.isIntegerValue():
2570 return self.getIntegerValue()
2571 elif self.isRealValue():
2572 return self.getRealValue()
2573 elif self.isBitVectorValue():
2574 return int(self.getBitVectorValue(), 2)
2575 elif self.isStringValue():
2576 return self.getStringValue()
2577 elif self.getSort().isArray():
2578 res = None
2579 keys = []
2580 values = []
2581 base_value = None
2582 to_visit = [self]
2583 # Array models are represented as a series of store operations
2584 # on a constant array
2585 while to_visit:
2586 t = to_visit.pop()
2587 if t.getKind() == kinds.Store:
2588 # save the mappings
2589 keys.append(t[1].toPythonObj())
2590 values.append(t[2].toPythonObj())
2591 to_visit.append(t[0])
2592 else:
2593 assert t.getKind() == kinds.ConstArray
2594 base_value = t.getConstArrayBase().toPythonObj()
2595
2596 assert len(keys) == len(values)
2597 assert base_value is not None
2598
2599 # put everything in a dictionary with the constant
2600 # base as the result for any index not included in the stores
2601 res = defaultdict(lambda : base_value)
2602 for k, v in zip(keys, values):
2603 res[k] = v
2604
2605 return res
2606
2607
2608 # Generate rounding modes
2609 cdef __rounding_modes = {
2610 <int> ROUND_NEAREST_TIES_TO_EVEN: "RoundNearestTiesToEven",
2611 <int> ROUND_TOWARD_POSITIVE: "RoundTowardPositive",
2612 <int> ROUND_TOWARD_NEGATIVE: "RoundTowardNegative",
2613 <int> ROUND_TOWARD_ZERO: "RoundTowardZero",
2614 <int> ROUND_NEAREST_TIES_TO_AWAY: "RoundNearestTiesToAway"
2615 }
2616
2617 mod_ref = sys.modules[__name__]
2618 for rm_int, name in __rounding_modes.items():
2619 r = RoundingMode(rm_int)
2620
2621 if name in dir(mod_ref):
2622 raise RuntimeError("Redefinition of Python RoundingMode %s."%name)
2623
2624 setattr(mod_ref, name, r)
2625
2626 del r
2627 del rm_int
2628 del name
2629
2630
2631 # Generate unknown explanations
2632 cdef __unknown_explanations = {
2633 <int> REQUIRES_FULL_CHECK: "RequiresFullCheck",
2634 <int> INCOMPLETE: "Incomplete",
2635 <int> TIMEOUT: "Timeout",
2636 <int> RESOURCEOUT: "Resourceout",
2637 <int> MEMOUT: "Memout",
2638 <int> INTERRUPTED: "Interrupted",
2639 <int> NO_STATUS: "NoStatus",
2640 <int> UNSUPPORTED: "Unsupported",
2641 <int> OTHER: "Other",
2642 <int> UNKNOWN_REASON: "UnknownReason"
2643 }
2644
2645 for ue_int, name in __unknown_explanations.items():
2646 u = UnknownExplanation(ue_int)
2647
2648 if name in dir(mod_ref):
2649 raise RuntimeError("Redefinition of Python UnknownExplanation %s."%name)
2650
2651 setattr(mod_ref, name, u)
2652
2653 del u
2654 del ue_int
2655 del name