From b5deba84263ebe3c9dc2aae73d7c11cafb572124 Mon Sep 17 00:00:00 2001
From: rainoftime <995204576@qq.com>
Date: Wed, 10 Nov 2021 03:05:10 +0800
Subject: [PATCH] add EFSMT solving example (#5654)

Co-authored-by: rainoftime <rainoftime@gmail.com>
---
 examples/python/efsmt.py | 47 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 examples/python/efsmt.py

diff --git a/examples/python/efsmt.py b/examples/python/efsmt.py
new file mode 100644
index 000000000..53c83c02e
--- /dev/null
+++ b/examples/python/efsmt.py
@@ -0,0 +1,47 @@
+from z3 import *
+from z3.z3util import get_vars
+
+'''
+Modified from the example in  pysmt
+https://github.com/pysmt/pysmt/blob/97088bf3b0d64137c3099ef79a4e153b10ccfda7/examples/efsmt.py
+'''
+def efsmt(y, phi, maxloops=None):
+    """Solving exists x. forall y. phi(x, y)"""
+    vars = get_vars(phi)
+    x = [item for item in vars if item not in y]
+    esolver = Solver()
+    fsolver = Solver()
+    esolver.add(BoolVal(True))
+    loops = 0
+    while maxloops is None or loops <= maxloops:
+        loops += 1
+        eres = esolver.check()
+        if eres == unsat:
+            return unsat
+        else:
+            emodel = esolver.model()
+            tau = [emodel.eval(var, True) for var in x]
+            sub_phi = phi
+            for i in range(len(x)):
+                sub_phi = simplify(substitute(sub_phi, (x[i], tau[i])))
+            fsolver.add(Not(sub_phi))
+            if fsolver.check() == sat:
+                fmodel = fsolver.model()
+                sigma = [fmodel.eval(v, True) for v in y]
+                sub_phi = phi
+                for j in range(len(y)):
+                    sub_phi = simplify(substitute(sub_phi, (y[j], sigma[j])))
+                esolver.add(sub_phi)
+            else:
+                return sat
+    return unknown
+
+
+def test():
+    x, y, z = Reals("x y z")
+    fmla = Implies(And(y > 0, y < 10), y - 2 * x < 7)
+    fmlb = And(y > 3, x == 1)
+    print(efsmt([y], fmla))
+    print(efsmt([y], fmlb))
+    
+test()