@@ -127,32 +127,32 @@ def _get_args(args):
127127class Context (object ):
128128 """A Context manages all terms, configurations, etc.
129129
130- In cvc5's API, these are managed by a solver, but we keep the Context class
131- (which just wraps a solver) for compatiblity.
132-
133- It's only responsibilities are:
130+ In z3's API, a context owns terms, sorts, and solvers. It is used to create
131+ them. Terms/sorts/solvers from one context cannot be implicitly used in
132+ another. Items *can* be explicitly transfered between contexts. The result
133+ is that essentially all functions have a context threaded through them.
134+ There is a default "main" context.
135+
136+ In cvc5's API, terms and sorts are created using a solver, but stored
137+ globally and are freely transferable.
138+
139+ Our compatibility solution is:
140+ * a context wraps a solver, so that a context can be used to create terms
141+ * also, a context does these things:
134142 * making fresh identifiers for a given sort
135143 * looking up previously defined constants
136144 """
137145
138- def __init__ (self , * args , ** kws ):
139- self .reset ()
140-
141- def __del__ (self ):
142- self .solver = None
143-
144- def reset (self ):
145- """Fully reset the context. This actually destroys the solver object and
146- recreates it. **This invalidates all objects created within this context
147- and using them will most likely crash.**
148- """
149- self .solver = pc .Solver ()
150- self .solver .setOption ("produce-models" , "true" )
146+ def __init__ (self , solver = None ):
147+ self .solver = solver .solver if solver is not None else SimpleSolver ().solver
151148 # Map from (name, sort) pairs to constant terms
152149 self .vars = {}
153150 # An increasing identifier used to make fresh identifiers
154151 self .next_fresh_var = 0
155152
153+ def __del__ (self ):
154+ self .solver = None
155+
156156 def get_var (self , name , sort ):
157157 """Get the variable identified by `name`.
158158
@@ -633,7 +633,6 @@ def eq(self, other):
633633 True
634634 """
635635 instance_check (other , SortRef )
636- assert self .ctx == other .ctx
637636 return self .as_ast () == other .as_ast ()
638637
639638 def hash (self ):
@@ -1754,6 +1753,16 @@ def is_string(self):
17541753 """
17551754 return isinstance (self , StringSortRef )
17561755
1756+ def elem_sort (self ):
1757+ """Get the element sort for this sequence
1758+
1759+ >>> SeqSort(IntSort()).elem_sort()
1760+ Int
1761+ >>> SeqSort(SeqSort(IntSort())).elem_sort()
1762+ (Seq Int)
1763+ """
1764+ return _to_sort_ref (self .ast .getSequenceElementSort (), self .ctx )
1765+
17571766
17581767class SeqRef (ExprRef ):
17591768 """Sequence Expressions"""
@@ -1990,13 +1999,13 @@ def Empty(s):
19901999 True
19912000 >>> e3 = Empty(SeqSort(IntSort()))
19922001 >>> print(e3)
1993- (as seq.empty (Seq (Seq Int) ))()
2002+ (as seq.empty (Seq Int))()
19942003 """
19952004 if isinstance (s , ReSortRef ):
19962005 return ReRef (s .ctx .solver .mkRegexpNone (), s .ctx )
19972006 if isinstance (s , StringSortRef ):
19982007 return StringRef (s .ctx .solver .mkString ("" ), s .ctx )
1999- return _to_expr_ref (s .ctx .solver .mkEmptySequence (s .ast ), s .ctx )
2008+ return _to_expr_ref (s .ctx .solver .mkEmptySequence (s .elem_sort (). ast ), s .ctx )
20002009
20012010
20022011def is_seq (a ):
@@ -5968,20 +5977,27 @@ class Solver(object):
59685977 * get-model,
59695978 * etc."""
59705979
5971- def __init__ (self , solver = None , ctx = None , logFile = None ):
5972- assert solver is None or ctx is not None
5973- self .ctx = _get_ctx (ctx )
5974- self .solver = self .ctx .solver
5980+ def __init__ (self , logic = None , ctx = None , logFile = None ):
5981+ # save logic so that we can re-build the solver if needed.
5982+ self .logic = logic
5983+ # ignore ctx (the paramter is kept for z3 compatibility)
5984+ self .solver = None
5985+ self .initFromLogic ()
59755986 self .scopes = 0
59765987 self .assertions_ = [[]]
59775988 self .last_result = None
59785989 self .resetAssertions ()
59795990
5991+ def initFromLogic (self ):
5992+ """Create the base-API solver from the logic"""
5993+ self .solver = pc .Solver ()
5994+ if self .logic is not None :
5995+ self .solver .setLogic (self .logic )
5996+ self .solver .setOption ("produce-models" , "true" )
5997+
59805998 def __del__ (self ):
59815999 if self .solver is not None :
59826000 self .solver = None
5983- if self .ctx is not None :
5984- self .ctx = None
59856001
59866002 def push (self ):
59876003 """Create a backtracking point.
@@ -6081,9 +6097,7 @@ def reset(self):
60816097 >>> s.reset()
60826098 >>> s.setOption(incremental=True)
60836099 """
6084- self .ctx .reset ()
6085- self .solver = self .ctx .solver
6086- self .resetAssertions ()
6100+ self .initFromLogic ()
60876101
60886102 def assert_exprs (self , * args ):
60896103 """Assert constraints into the solver.
@@ -6095,7 +6109,7 @@ def assert_exprs(self, *args):
60956109 [x > 0, x < 2]
60966110 """
60976111 args = _get_args (args )
6098- s = BoolSort (self . ctx )
6112+ s = BoolSort ()
60996113 for arg in args :
61006114 arg = s .cast (arg )
61016115 self .assertions_ [- 1 ].append (arg )
@@ -6184,7 +6198,7 @@ def model(self):
61846198 >>> s.model()
61856199 [a = -2]
61866200 """
6187- return ModelRef (self , self . ctx )
6201+ return ModelRef (self )
61886202
61896203 def assertions (self ):
61906204 """Return an AST vector containing all added constraints.
@@ -6229,7 +6243,6 @@ def sexpr(self):
62296243 def set (self , * args , ** kwargs ):
62306244 """Set an option on the solver. Wraps ``setOption()``.
62316245
6232- >>> main_ctx().reset()
62336246 >>> s = Solver()
62346247 >>> s.set(incremental=True)
62356248 >>> s.set('incremental', 'true')
@@ -6244,7 +6257,6 @@ def setOption(self, name=None, value=None, **kwargs):
62446257 properly converted manually, all other types are convertes using
62456258 ``str()``.
62466259
6247- >>> main_ctx().reset()
62486260 >>> s = Solver()
62496261 >>> s.setOption('incremental', True)
62506262 >>> s.setOption(incremental='true')
@@ -6263,7 +6275,6 @@ def getOption(self, name):
62636275 """Get the current value of an option from the solver. The value is
62646276 returned as a string. For type-safe querying use ``getOptionInfo()``.
62656277
6266- >>> main_ctx().reset()
62676278 >>> s = Solver()
62686279 >>> s.setOption(incremental=True)
62696280 >>> s.getOption("incremental")
@@ -6285,12 +6296,10 @@ def getOptionInfo(self, name):
62856296 """Get the current value of an option from the solver. The value is
62866297 returned as a string. For type-safe querying use ``getOptionInfo()``.
62876298
6288- >>> main_ctx().reset()
62896299 >>> s = Solver()
62906300 >>> s.setOption(incremental=False)
62916301 >>> s.getOptionInfo("incremental")
62926302 {'name': 'incremental', 'aliases': [], 'setByUser': True, 'type': <class 'bool'>, 'current': False, 'default': True}
6293- >>> main_ctx().reset()
62946303 """
62956304 return self .solver .getOptionInfo (name )
62966305
@@ -6305,7 +6314,7 @@ def statistics(self):
63056314 sat
63066315 >>> stats = s.statistics()
63076316 >>> stats['cvc5::CONSTANT']
6308- {'defaulted': False , 'internal': False, 'value': {'integer type': 1 }}
6317+ {'defaulted': True , 'internal': False, 'value': {}}
63096318 >>> len(stats.get()) < 10
63106319 True
63116320 >>> len(stats.get(True, True)) > 30
@@ -6331,11 +6340,7 @@ def SolverFor(logic, ctx=None, logFile=None):
63316340 # sat
63326341 # >>> s.model()
63336342 # [x = 1]
6334- # """
6335- solver = pc .Solver ()
6336- solver .setLogic (logic )
6337- ctx = _get_ctx (ctx )
6338- return Solver (solver , ctx , logFile )
6343+ return Solver (logic = logic , ctx = ctx , logFile = logFile )
63396344
63406345
63416346def SimpleSolver (ctx = None , logFile = None ):
@@ -6347,8 +6352,7 @@ def SimpleSolver(ctx=None, logFile=None):
63476352 >>> s.check()
63486353 sat
63496354 """
6350- ctx = _get_ctx (ctx )
6351- return Solver (None , ctx , logFile )
6355+ return Solver (ctx = ctx , logFile = logFile )
63526356
63536357
63546358#########################################
@@ -6571,17 +6575,13 @@ def is_tautology(taut):
65716575class ModelRef :
65726576 """Model/Solution of a satisfiability problem (aka system of constraints)."""
65736577
6574- def __init__ (self , solver , ctx ):
6578+ def __init__ (self , solver ):
65756579 assert solver is not None
6576- assert ctx is not None
65776580 self .solver = solver
6578- self .ctx = ctx
65796581
65806582 def __del__ (self ):
65816583 if self .solver is not None :
65826584 self .solver = None
6583- if self .ctx is not None :
6584- self .ctx = None
65856585
65866586 def vars (self ):
65876587 """Returns the free constants in an assertion, as terms"""
@@ -6629,7 +6629,7 @@ def eval(self, t, model_completion=False):
66296629 >>> m.eval(x == 1)
66306630 True
66316631 """
6632- return _to_expr_ref (self .solver .solver .getValue (t .ast ), self .solver . ctx )
6632+ return _to_expr_ref (self .solver .solver .getValue (t .ast ), Context ( self .solver ) )
66336633
66346634 def evaluate (self , t , model_completion = False ):
66356635 """Alias for `eval`.
0 commit comments