Z3
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
40 public class UserPropagator
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(ref Expr term, ref uint idx, ref int phase);
67
68 // access managed objects through a static array.
69 // thread safety is ignored for now.
70 GCHandle gch;
71 Solver solver;
72 Context ctx;
73 Z3_solver_callback callback = IntPtr.Zero;
74 int callbackNesting = 0;
75 FixedEh fixed_eh;
76 Action final_eh;
77 EqEh eq_eh;
78 EqEh diseq_eh;
79 CreatedEh created_eh;
80 DecideEh decide_eh;
81
82 Native.Z3_push_eh push_eh;
83 Native.Z3_pop_eh pop_eh;
84 Native.Z3_fresh_eh fresh_eh;
85
86 Native.Z3_fixed_eh fixed_wrapper;
87 Native.Z3_final_eh final_wrapper;
88 Native.Z3_eq_eh eq_wrapper;
89 Native.Z3_eq_eh diseq_wrapper;
90 Native.Z3_decide_eh decide_wrapper;
91 Native.Z3_created_eh created_wrapper;
92
93 void Callback(Action fn, Z3_solver_callback cb)
94 {
95 this.callbackNesting++;
96 this.callback = cb;
97 try
98 {
99 fn();
100 }
101 catch
102 {
103 // TBD: add debug log or exception handler
104 }
105 finally
106 {
107 callbackNesting--;
108 if (callbackNesting == 0) // callbacks can be nested (e.g., internalizing new element in "created")
109 this.callback = IntPtr.Zero;
110 }
111 }
112
113
114 static void _push(voidp ctx, Z3_solver_callback cb)
115 {
116 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
117 prop.Callback(() => prop.Push(), cb);
118 }
119
120 static void _pop(voidp ctx, Z3_solver_callback cb, uint num_scopes)
121 {
122 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
123 prop.Callback(() => prop.Pop(num_scopes), cb);
124 }
125
126 static voidp _fresh(voidp _ctx, Z3_context new_context)
127 {
128 var prop = (UserPropagator)GCHandle.FromIntPtr(_ctx).Target;
129 var ctx = new Context(new_context);
130 var prop1 = prop.Fresh(prop.ctx);
131 return GCHandle.ToIntPtr(prop1.gch);
132 }
133
134 static void _fixed(voidp ctx, Z3_solver_callback cb, Z3_ast _term, Z3_ast _value)
135 {
136 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
137 using var term = Expr.Create(prop.ctx, _term);
138 using var value = Expr.Create(prop.ctx, _value);
139 prop.Callback(() => prop.fixed_eh(term, value), cb);
140 }
141
142 static void _final(voidp ctx, Z3_solver_callback cb)
143 {
144 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
145 prop.Callback(() => prop.final_eh(), cb);
146 }
147
148 static void _eq(voidp ctx, Z3_solver_callback cb, Z3_ast a, Z3_ast b)
149 {
150 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
151 using var s = Expr.Create(prop.ctx, a);
152 using var t = Expr.Create(prop.ctx, b);
153 prop.Callback(() => prop.eq_eh(s, t), cb);
154 }
155
156 static void _diseq(voidp ctx, Z3_solver_callback cb, Z3_ast a, Z3_ast b)
157 {
158 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
159 using var s = Expr.Create(prop.ctx, a);
160 using var t = Expr.Create(prop.ctx, b);
161 prop.Callback(() => prop.diseq_eh(s, t), cb);
162 }
163
164 static void _created(voidp ctx, Z3_solver_callback cb, Z3_ast a)
165 {
166 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
167 using var t = Expr.Create(prop.ctx, a);
168 prop.Callback(() => prop.created_eh(t), cb);
169 }
170
171 static void _decide(voidp ctx, Z3_solver_callback cb, ref Z3_ast a, ref uint idx, ref int phase)
172 {
173 var prop = (UserPropagator)GCHandle.FromIntPtr(ctx).Target;
174 var t = Expr.Create(prop.ctx, a);
175 var u = t;
176 prop.callback = cb;
177 prop.decide_eh(ref t, ref idx, ref phase);
178 prop.callback = IntPtr.Zero;
179 if (u != t)
180 a = t.NativeObject;
181 }
182
187 {
188 gch = GCHandle.Alloc(this);
189 solver = s;
190 ctx = solver.Context;
191 push_eh = _push;
192 pop_eh = _pop;
193 fresh_eh = _fresh;
194 Native.Z3_solver_propagate_init(ctx.nCtx, solver.NativeObject, GCHandle.ToIntPtr(gch), push_eh, pop_eh, fresh_eh);
195 }
196
201 {
202 gch = GCHandle.Alloc(this);
203 solver = null;
204 ctx = _ctx;
205 }
206
211 {
212 gch.Free();
213 if (solver == null)
214 ctx.Dispose();
215 }
216
220 public virtual void Push() { throw new Z3Exception("Push method should be overwritten"); }
221
225 public virtual void Pop(uint n) { throw new Z3Exception("Pop method should be overwritten"); }
226
230 public virtual UserPropagator Fresh(Context ctx) { return new UserPropagator(ctx); }
231
235 public void Conflict(params Expr[] terms)
236 {
237 Propagate(terms, ctx.MkFalse());
238 }
239
243 public void Conflict(IEnumerable<Expr> terms)
244 {
245 Propagate(terms, ctx.MkFalse());
246 }
247
251 public void Propagate(IEnumerable<Expr> terms, Expr conseq)
252 {
253 var nTerms = Z3Object.ArrayToNative(terms.ToArray());
254 Native.Z3_solver_propagate_consequence(ctx.nCtx, this.callback, (uint)nTerms.Length, nTerms, 0u, null, null, conseq.NativeObject);
255 }
256
257
262 {
263 set
264 {
265 this.fixed_wrapper = _fixed;
266 this.fixed_eh = value;
267 if (solver != null)
268 Native.Z3_solver_propagate_fixed(ctx.nCtx, solver.NativeObject, fixed_wrapper);
269 }
270 }
271
275 public Action Final
276 {
277 set
278 {
279 this.final_wrapper = _final;
280 this.final_eh = value;
281 if (solver != null)
282 Native.Z3_solver_propagate_final(ctx.nCtx, solver.NativeObject, final_wrapper);
283 }
284 }
285
289 public EqEh Eq
290 {
291 set
292 {
293 this.eq_wrapper = _eq;
294 this.eq_eh = value;
295 if (solver != null)
296 Native.Z3_solver_propagate_eq(ctx.nCtx, solver.NativeObject, eq_wrapper);
297 }
298 }
299
303 public EqEh Diseq
304 {
305 set
306 {
307 this.diseq_wrapper = _diseq;
308 this.diseq_eh = value;
309 if (solver != null)
310 Native.Z3_solver_propagate_diseq(ctx.nCtx, solver.NativeObject, diseq_wrapper);
311 }
312 }
313
318 {
319 set
320 {
321 this.created_wrapper = _created;
322 this.created_eh = value;
323 if (solver != null)
324 Native.Z3_solver_propagate_created(ctx.nCtx, solver.NativeObject, created_wrapper);
325 }
326 }
327
332 {
333 set
334 {
335 this.decide_wrapper = _decide;
336 this.decide_eh = value;
337 if (solver != null)
338 Native.Z3_solver_propagate_decide(ctx.nCtx, solver.NativeObject, decide_wrapper);
339 }
340 }
341
342
346 public void NextSplit(Expr e, uint idx, int phase)
347 {
348 Native.Z3_solver_next_split(ctx.nCtx, this.callback, e.NativeObject, idx, phase);
349 }
350
354 public void Register(Expr term)
355 {
356 if (this.callback != IntPtr.Zero)
357 {
358 Native.Z3_solver_propagate_register_cb(ctx.nCtx, callback, term.NativeObject);
359 }
360 else
361 {
362 Native.Z3_solver_propagate_register(ctx.nCtx, solver.NativeObject, term.NativeObject);
363 }
364 }
365 }
366}
The main interaction with Z3 happens via the Context.
Definition: Context.cs:34
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
delegate void CreatedEh(Expr term)
Delegate type for when a new term using a registered function symbol is created internally
void Propagate(IEnumerable< Expr > terms, Expr conseq)
Propagate consequence
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.
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.
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
void NextSplit(Expr e, uint idx, int phase)
Set the next decision
virtual void Push()
Virtual method for push. It must be overwritten by inherited class.
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.
DecideEh Decide
Set decision callback
Action Final
Set final callback
delegate void DecideEh(ref Expr term, ref uint idx, ref int phase)
Delegate type for callback into solver's branching A bit-vector or Boolean used for branchingIf the t...
The exception base class for error reporting from Z3
Definition: Z3Exception.cs:32
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:120
System.IntPtr Z3_context
Definition: Context.cs:29
System.IntPtr voidp
System.IntPtr Z3_ast
System.IntPtr Z3_solver
System.IntPtr Z3_solver_callback