Z3
 
Loading...
Searching...
No Matches
UserPropagator.cs
Go to the documentation of this file.
1/*++
2Copyright (c) 2012 Microsoft Corporation
3
4Module Name:
5
6 UserPropagator.cs
7
8Abstract:
9
10 User Propagator plugin
11
12Author:
13
14 Nikolaj Bjorner (nbjorner) 2022-05-07
15
16Notes:
17
18
19--*/
20
21using System;
22using System.Diagnostics;
23using System.Linq;
24using System.Collections.Generic;
25using System.Runtime.InteropServices;
26
27namespace Microsoft.Z3
28{
29
30 using Z3_solver_callback = System.IntPtr;
31 using Z3_context = System.IntPtr;
32 using Z3_solver = System.IntPtr;
33 using voidp = System.IntPtr;
34 using Z3_ast = System.IntPtr;
35
36
41 {
48 public delegate void FixedEh(Expr term, Expr value);
49
53 public delegate void EqEh(Expr term, Expr value);
54
58 public delegate void CreatedEh(Expr term);
59
66 public delegate void DecideEh(Expr term, uint idx, bool phase);
67
74 public delegate bool OnBindingEh(Expr q, Expr inst);
75
76 // access managed objects through a static array.
77 // thread safety is ignored for now.
78 GCHandle gch;
79 Solver solver;
80 Context ctx;
81 Z3_solver_callback callback = IntPtr.Zero;
82 int callbackNesting = 0;
83 FixedEh fixed_eh;
84 Action final_eh;
85 EqEh eq_eh;
86 EqEh diseq_eh;
87 CreatedEh created_eh;
88 DecideEh decide_eh;
89 OnBindingEh on_binding_eh;
90
91 Native.Z3_push_eh push_eh;
92 Native.Z3_pop_eh pop_eh;
93 Native.Z3_fresh_eh fresh_eh;
94
95 Native.Z3_fixed_eh fixed_wrapper;
96 Native.Z3_final_eh final_wrapper;
97 Native.Z3_eq_eh eq_wrapper;
98 Native.Z3_eq_eh diseq_wrapper;
99 Native.Z3_decide_eh decide_wrapper;
100 Native.Z3_created_eh created_wrapper;
101 Native.Z3_on_binding_eh on_binding_wrapper;
102
103 void Callback(Action fn, Z3_solver_callback cb)
104 {
105 this.callbackNesting++;
106 this.callback = cb;
107 try
108 {
109 fn();
110 }
111 catch
112 {
113 // TBD: add debug log or exception handler
114 }
115 finally
116 {
117 callbackNesting--;
118 if (callbackNesting == 0) // callbacks can be nested (e.g., internalizing new element in "created")
119 this.callback = IntPtr.Zero;
120 }
121 }
122
123
124 static void _push(voidp ctx, Z3_solver_callback cb)
125 {
126 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
127 prop.Callback(() => prop.Push(), cb);
128 }
129
130 static void _pop(voidp ctx, Z3_solver_callback cb, uint num_scopes)
131 {
132 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
133 prop.Callback(() => prop.Pop(num_scopes), cb);
134 }
135
136 static voidp _fresh(voidp _ctx, Z3_context new_context)
137 {
138 var prop = (UserPropagator)GCHandle.FromIntPtr(_ctx).Target;
139 var ctx = new Context(new_context);
140 var prop1 = prop.Fresh(prop.ctx);
141 return GCHandle.ToIntPtr(prop1.gch);
142 }
143
144 static void _fixed(voidp ctx, Z3_solver_callback cb, Z3_ast _term, Z3_ast _value)
145 {
146 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
147 using var term = Expr.Create(prop.ctx, _term);
148 using var value = Expr.Create(prop.ctx, _value);
149 prop.Callback(() => prop.fixed_eh(term, value), cb);
150 }
151
152 static void _final(voidp ctx, Z3_solver_callback cb)
153 {
154 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
155 prop.Callback(() => prop.final_eh(), cb);
156 }
157
158 static void _eq(voidp ctx, Z3_solver_callback cb, Z3_ast a, Z3_ast b)
159 {
160 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
161 using var s = Expr.Create(prop.ctx, a);
162 using var t = Expr.Create(prop.ctx, b);
163 prop.Callback(() => prop.eq_eh(s, t), cb);
164 }
165
166 static void _diseq(voidp ctx, Z3_solver_callback cb, Z3_ast a, Z3_ast b)
167 {
168 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
169 using var s = Expr.Create(prop.ctx, a);
170 using var t = Expr.Create(prop.ctx, b);
171 prop.Callback(() => prop.diseq_eh(s, t), cb);
172 }
173
174 static void _created(voidp ctx, Z3_solver_callback cb, Z3_ast a)
175 {
176 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
177 using var t = Expr.Create(prop.ctx, a);
178 prop.Callback(() => prop.created_eh(t), cb);
179 }
180
181 static void _decide(voidp ctx, Z3_solver_callback cb, Z3_ast a, uint idx, bool phase)
182 {
183 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
184 using var t = Expr.Create(prop.ctx, a);
185 prop.Callback(() => prop.decide_eh(t, idx, phase), cb);
186 }
187
188 static bool _on_binding(voidp _ctx, Z3_solver_callback cb, Z3_ast _q, Z3_ast _inst)
189 {
190 var prop = (UserPropagator)GCHandle.FromIntPtr(_ctx).Target;
191 using var q = Expr.Create(prop.ctx, _q);
192 using var inst = Expr.Create(prop.ctx, _inst);
193 bool result = true;
194 prop.Callback(() => {
195 if (prop.on_binding_wrapper != null)
196 result = prop.on_binding_eh(q, inst);
197 }, cb);
198 return result;
199 }
200
205 {
206 gch = GCHandle.Alloc(this);
207 solver = s;
208 ctx = solver.Context;
209 push_eh = _push;
210 pop_eh = _pop;
211 fresh_eh = _fresh;
212 Native.Z3_solver_propagate_init(ctx.nCtx, solver.NativeObject, GCHandle.ToIntPtr(gch), push_eh, pop_eh, fresh_eh);
213 }
214
219 {
220 gch = GCHandle.Alloc(this);
221 solver = null;
222 ctx = _ctx;
223 }
224
229 {
230 Dispose();
231 }
232
236 public virtual void Dispose()
237 {
238 if (!gch.IsAllocated)
239 return;
240 gch.Free();
241 if (solver == null)
242 ctx.Dispose();
243 }
244
248 public virtual void Push() { throw new Z3Exception("Push method should be overwritten"); }
249
253 public virtual void Pop(uint n) { throw new Z3Exception("Pop method should be overwritten"); }
254
258 public virtual UserPropagator Fresh(Context ctx) { return new UserPropagator(ctx); }
259
263 public void Conflict(params Expr[] terms)
264 {
265 Propagate(terms, ctx.MkFalse());
266 }
267
271 public void Conflict(IEnumerable<Expr> terms)
272 {
273 Propagate(terms, ctx.MkFalse());
274 }
275
283 public bool Propagate(IEnumerable<Expr> terms, Expr conseq)
284 {
285 return Propagate(terms, new EqualityPairs(), conseq);
286 }
287
295 public bool Propagate(IEnumerable<Expr> terms, EqualityPairs equalities, Expr conseq)
296 {
297 var nTerms = Z3Object.ArrayToNative(terms.ToArray());
298 var nLHS = Z3Object.ArrayToNative(equalities.LHS.ToArray());
299 var nRHS = Z3Object.ArrayToNative(equalities.RHS.ToArray());
300 return Native.Z3_solver_propagate_consequence(ctx.nCtx, this.callback, (uint)nTerms.Length, nTerms, (uint)equalities.Count, nLHS, nRHS, conseq.NativeObject) != 0;
301 }
302
303
308 {
309 set
310 {
311 this.fixed_wrapper = _fixed;
312 this.fixed_eh = value;
313 if (solver != null)
314 Native.Z3_solver_propagate_fixed(ctx.nCtx, solver.NativeObject, fixed_wrapper);
315 }
316 }
317
321 public Action Final
322 {
323 set
324 {
325 this.final_wrapper = _final;
326 this.final_eh = value;
327 if (solver != null)
328 Native.Z3_solver_propagate_final(ctx.nCtx, solver.NativeObject, final_wrapper);
329 }
330 }
331
335 public EqEh Eq
336 {
337 set
338 {
339 this.eq_wrapper = _eq;
340 this.eq_eh = value;
341 if (solver != null)
342 Native.Z3_solver_propagate_eq(ctx.nCtx, solver.NativeObject, eq_wrapper);
343 }
344 }
345
349 public EqEh Diseq
350 {
351 set
352 {
353 this.diseq_wrapper = _diseq;
354 this.diseq_eh = value;
355 if (solver != null)
356 Native.Z3_solver_propagate_diseq(ctx.nCtx, solver.NativeObject, diseq_wrapper);
357 }
358 }
359
364 {
365 set
366 {
367 this.created_wrapper = _created;
368 this.created_eh = value;
369 if (solver != null)
370 Native.Z3_solver_propagate_created(ctx.nCtx, solver.NativeObject, created_wrapper);
371 }
372 }
373
378 {
379 set
380 {
381 this.decide_wrapper = _decide;
382 this.decide_eh = value;
383 if (solver != null)
384 Native.Z3_solver_propagate_decide(ctx.nCtx, solver.NativeObject, decide_wrapper);
385 }
386 }
387
392 {
393 set
394 {
395 this.on_binding_wrapper = _on_binding;
396 this.on_binding_eh = value;
397 if (solver != null)
398 Native.Z3_solver_propagate_on_binding(ctx.nCtx, solver.NativeObject, on_binding_wrapper);
399 }
400 }
401
402
413 public bool NextSplit(Expr e, uint idx, int phase)
414 {
415 return Native.Z3_solver_next_split(ctx.nCtx, this.callback, e?.NativeObject ?? IntPtr.Zero, idx, phase) != 0;
416 }
417
418
419
423 public void Register(Expr term)
424 {
425 if (this.callback != IntPtr.Zero)
426 {
427 Native.Z3_solver_propagate_register_cb(ctx.nCtx, callback, term.NativeObject);
428 }
429 else
430 {
431 Native.Z3_solver_propagate_register(ctx.nCtx, solver.NativeObject, term.NativeObject);
432 }
433 }
434 }
435
439 public class EqualityPairs {
440
441 readonly List<Expr> lhsList = new List<Expr>();
442 readonly List<Expr> rhsList = new List<Expr>();
443
447 public Expr[] LHS => lhsList.ToArray();
448
452 public Expr[] RHS => rhsList.ToArray();
453
457 public int Count => lhsList.Count;
458
464 public void Add(Expr lhs, Expr rhs) {
465 lhsList.Add(lhs);
466 rhsList.Add(rhs);
467 }
468
473 public override bool Equals(object obj) {
474 if (ReferenceEquals(this, obj))
475 return true;
476 if (!(obj is EqualityPairs other))
477 return false;
478 if (lhsList.Count != other.lhsList.Count)
479 return false;
480 for (int i = 0; i < lhsList.Count; i++) {
481 if (!lhsList[i].Equals(other.lhsList[i]))
482 return false;
483 }
484 return true;
485 }
486
490 public override int GetHashCode() {
491 int hash = lhsList.Count;
492 unchecked {
493 for (int i = 0; i < lhsList.Count; i++) {
494 hash ^= lhsList[i].GetHashCode();
495 hash *= 17;
496 hash ^= rhsList[i].GetHashCode();
497 hash *= 29;
498 }
499 return hash;
500 }
501 }
502 }
503}
The main interaction with Z3 happens via the Context.
Definition Context.cs:34
A list of equalities used as justifications for propagation.
Expr[] LHS
The left hand sides of the equalities.
override int GetHashCode()
Gets a hash code for the list of equalities.
void Add(Expr lhs, Expr rhs)
Adds an equality to the list. The sorts of the arguments have to be the same.
int Count
The number of equalities.
override bool Equals(object obj)
Checks if two equality lists are equal. The function does not take symmetries, shuffling,...
Expr[] RHS
The right hand sides of the equalities.
Expressions are terms.
Definition Expr.cs:31
Propagator context for .Net.
EqEh Diseq
Set disequality event callback.
void Conflict(IEnumerable< Expr > terms)
Declare combination of assigned expressions a conflict.
virtual void Dispose()
Must be called. The object will not be garbage collected automatically even if the context is dispose...
delegate void CreatedEh(Expr term)
Delegate type for when a new term using a registered function symbol is created internally.
delegate void FixedEh(Expr term, Expr value)
Delegate type for fixed callback Note that the life-time of the term and value only applies within th...
UserPropagator(Solver s)
Propagator constructor from a solver class.
virtual UserPropagator Fresh(Context ctx)
Virtual method for fresh. It can be overwritten by inherited class.
bool Propagate(IEnumerable< Expr > terms, EqualityPairs equalities, Expr conseq)
Propagate consequence true if the propagated expression is new for the solver; false if the propagati...
void Register(Expr term)
Track assignments to a term.
virtual void Pop(uint n)
Virtual method for pop. It must be overwritten by inherited class.
OnBindingEh OnBinding
Set binding callback.
delegate void EqEh(Expr term, Expr value)
Delegate type for equality or disequality callback.
void Conflict(params Expr[] terms)
Declare combination of assigned expressions a conflict.
delegate bool OnBindingEh(Expr q, Expr inst)
Delegate type for callback when a quantifier is bound to an instance.
virtual void Push()
Virtual method for push. It must be overwritten by inherited class.
bool NextSplit(Expr e, uint idx, int phase)
Set the next decision
delegate void DecideEh(Expr term, uint idx, bool phase)
Delegate type for callback into solver's branching. The values can be overridden by calling NextSplit...
EqEh Eq
Set equality event callback.
CreatedEh Created
Set created callback.
FixedEh Fixed
Set fixed callback.
UserPropagator(Context _ctx)
Propagator constructor from a context. It is used from inside of Fresh.
bool Propagate(IEnumerable< Expr > terms, Expr conseq)
Propagate consequence true if the propagated expression is new for the solver; false if the propagati...
DecideEh Decide
Set decision callback.
Action Final
Set final callback.
The exception base class for error reporting from Z3.
Internal base class for interfacing with native Z3 objects. Should not be used externally.
Definition Z3Object.cs:33
Context Context
Access Context object.
Definition Z3Object.cs:111
System.IntPtr voidp
Definition OnClause.cs:32
System.IntPtr Z3_context
Definition Context.cs:29
System.IntPtr Z3_ast
System.IntPtr Z3_solver
System.IntPtr Z3_solver_callback