def test_unsat(self): result = CheckSatisfiability(f_unsat, 0.001) self.assertEqual(result, None) b = Box([x, y, z]) b_copy = Box([x, y, z]) result = CheckSatisfiability(f_unsat, 0.001, b) self.assertEqual(result, False) self.assertEqual(b, b_copy) # Unchanged
def test_delta_sat(self): result = CheckSatisfiability(f_sat, 0.001) self.assertEqual(type(result), Box) b = Box([x, y, z]) result = CheckSatisfiability(f_sat, 0.001, b) self.assertEqual(result, True) self.assertTrue(b[x].diam() < 0.1) self.assertTrue(b[y].diam() < 0.1) self.assertTrue(b[z].diam() < 0.1)
def test_dreal_orthogonal_sat(): """ See whether a model initializes and can build correctly. """ model = Model("Test Model") ssalg = SmallStepAlg() dralg = DRealAlg() with model.build(): test.premade_models.find_orthogonal() model.gen_output_terms() model.run_algebra(ssalg) model.run_algebra(dralg) print(model_graraphviz_trans(model).source()) controls = list() for v in model.controls: controls.append(v.final['dreal_exp']) fun = forall( controls, logical_imply( logical_and(model.assumption_term().final['dreal_exp'], model.constraint_term().final['dreal_exp']), model.guarantee_term().final['dreal_exp'])) print(fun) result = CheckSatisfiability(fun, 0.01) print(result)
def inverterLoopTanh(numInverters, numSolutions="all", a=-5.0): epsilon = 1e-14 start = time.time() vs = [] for i in range(numInverters): vs.append(Variable("v" + str(i))) allConstraints = [] # Store rambus oscillator constraints for i in range(numInverters): allConstraints.append(vs[i] >= -1) allConstraints.append(vs[i] <= 1) inputInd = i outputInd = (i + 1) % numInverters allConstraints.append(tanh(a * vs[inputInd]) - vs[outputInd] == 0.0) allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break # Store constraints pruning search space so that # old hyperrectangles are not considered excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] for i in range(numInverters): singleExcludingConstraints.append(vs[i] < solution[i][0]) singleExcludingConstraints.append(vs[i] > solution[i][1]) excludingConstraints.append(singleExcludingConstraints) # Add all the rambus oscillator constraints f_sat = logical_and(*allConstraints) # Add constraints so that old hyperrectangles are not considered if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((numInverters, 2)) for i in range(numInverters): hyper[i, :] = [ result[vs[i]].lb() - 2 * epsilon, result[vs[i]].ub() + 2 * epsilon ] #print ("hyper", hyper) allSolutions.append(hyper) print("num solutions found", len(allSolutions)) end = time.time() print("time taken", end - start) return allSolutions
def inverterScMosfet(inputVoltage, numSolutions="all"): epsilon = 1e-14 start = time.time() Vdd = 1.0 sn = 3 sp = 2 * sn outputVolt = Variable("outputVolt") iP = Variable("iP") iN = Variable("iN") allConstraints = [] allConstraints.append(outputVolt >= 0.0) allConstraints.append(outputVolt <= Vdd) allConstraints.append(-iP - iN == 0) allConstraints += mvs_id("n", 0.0, inputVoltage, outputVolt, iN, sn) allConstraints += mvs_id("p", Vdd, inputVoltage, outputVolt, iP, sp) allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break # Store constraints pruning search space so that # old hyperrectangles are not considered excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] singleExcludingConstraints.append(outputVolt < solution[0][0]) singleExcludingConstraints.append(outputVolt > solution[0][1]) excludingConstraints.append(singleExcludingConstraints) #print ("allConstraints") #print (allConstraints) f_sat = logical_and(*allConstraints) if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((1, 2)) hyper[0, :] = [ result[outputVolt].lb() - 2 * epsilon, result[outputVolt].ub() + 2 * epsilon ] #print ("hyper", hyper) allSolutions.append(hyper) print("num solutions found", len(allSolutions)) end = time.time() print("time taken", end - start) return allSolutions
def exampleFun(numSolutions="all"): start = time.time() epsilon = 1e-14 lenV = 1 x = Variable('x') allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break allConstraints = [] allConstraints.append(2 * x * asin(cos(0.797) * sin(math.pi / x)) - 0.0331 * x >= 2 * math.pi - 2.097) allConstraints.append(x >= 3) allConstraints.append(x <= 64) excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] singleExcludingConstraints.append(x <= solution[0][0]) singleExcludingConstraints.append(x >= solution[0][1]) excludingConstraints.append(singleExcludingConstraints) #print ("allConstraints") #print (allConstraints) #print ("numConstraints", len(allConstraints)) f_sat = logical_and(*allConstraints) if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((1, 2)) hyper[0, :] = [ result[x].lb() - 2 * epsilon, result[x].ub() + 2 * epsilon ] print("hyper", hyper) allSolutions.append(hyper) print("num solutions found", len(allSolutions)) '''constraints = [] x = Variable('x') #constraints.append(x >= 0.0) #constraints.append(x <= 64.0) constraints.append(2*math.pi - 2*x*asin(cos(0.797)*sin(math.pi/x)) == 2.097 - 0.0331*x) f_sat = logical_and(*constraints) result = CheckSatisfiability(f_sat, epsilon) print (result)''' end = time.time() print("time taken", end - start)
def inverterTanh(inputVoltage, a=-5.0, numSolutions="all"): epsilon = 1e-14 start = time.time() outputVolt = Variable("outputVolt") allConstraints = [] allConstraints.append(outputVolt >= -1.0) allConstraints.append(outputVolt <= 1.0) allConstraints.append(tanh(a * inputVoltage) - outputVolt == 0) allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break # Store constraints pruning search space so that # old hyperrectangles are not considered excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] singleExcludingConstraints.append(outputVolt < solution[0][0]) singleExcludingConstraints.append(outputVolt > solution[0][1]) excludingConstraints.append(singleExcludingConstraints) #print ("allConstraints") #print (allConstraints) f_sat = logical_and(*allConstraints) if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((1, 2)) hyper[0, :] = [ result[outputVolt].lb() - 2 * epsilon, result[outputVolt].ub() + 2 * epsilon ] #print ("hyper", hyper) allSolutions.append(hyper) print("num solutions found", len(allSolutions)) end = time.time() print("time taken", end - start) return allSolutions
def test_boolean_if_then(): """ Tests whether boolean constraints work. True is '1', false is '0'. """ a = Variable('a', Variable.Int) b = Variable('b', Variable.Int) fun = logical_and( if_then_else(a == False, 20, -20) > 0, if_then_else(b == True, 13, -12) > 0) result = CheckSatisfiability(fun, 0.01) print(result)
def test_dreal_interface_othro(): """ Just an empty test to make pytest force a parse check. """ t = Variable('theta', Variable.Real) a = Variable('a', Variable.Bool) b = Variable('b', Variable.Bool) c = Variable('c', Variable.Bool) d = Variable('d', Variable.Bool) fun = forall( [t], logical_imply(logical_and(t < 3, t > -3), (((sin(t) * if_then_else(b == True, 1, -1) * if_then_else(a == True, sin(t), cos(t))) + (cos(t) * if_then_else(d == True, 1, -1) * if_then_else(c == True, sin(t), cos(t)))) == 0))) result = CheckSatisfiability(fun, 0.01) print(result) assert False
def test_minimize_via_forall(self): # To minimize f(X) s.t. φ(x), this test encodes # the problem into a first-order logic formula. # # ∃X. φ(X) ∧ [∀Y φ(Y) ⇒ (f(X) ≤ f(Y))] # # Here we use f(x) = sin(x)cos(x) # φ(X) = (0 ≤ x) ∧ (x ≤ π) def f(x): return sin(x) * cos(x) def phi(x): return logical_and(0 <= x, x <= math.pi) problem = logical_and( phi(x), forall([y], logical_and(logical_imply(phi(y), f(x) <= f(y))))) result = CheckSatisfiability(problem, 0.01) self.assertTrue(result) self.assertAlmostEqual(result[x].mid(), math.pi * 3 / 4, places=3)
def invoke_backend(self, _show): """Combine all of the SMT expressions into one expression to sent to dReal solver to determine solvability :param bool show: If true then the full SMT formula that was created is printed :returns: dReal model showing the values for each of the parameters """ formula = logical_and(*self.exprs) # Prints the generated formula in full, remove serialize for shortened if _show: # nx.draw(self.dg) # plt.show() print(formula) # Return None if not solvable, returns a dict-like structure giving the # range of values for each Variable model = CheckSatisfiability(formula, 10) if model: return model else: return "No solution found"
from dreal.symbolic import Variable, logical_and, sin, cos from dreal.api import CheckSatisfiability, Minimize x = Variable("x") y = Variable("y") z = Variable("z") f_sat = logical_and(0 <= x, x <= 10, 0 <= y, y <= 10, 0 <= z, z <= 10, sin(x) + cos(y) == z) result = CheckSatisfiability(f_sat, 0.001) print(result)
def rambusOscillatorTanh(numStages, g_cc=0.5, numSolutions="all", a=-5.0): epsilon = 1e-14 start = time.time() g_fwd = 1.0 lenV = numStages * 2 vs = [] vfwds = [] vccs = [] for i in range(lenV): vs.append(Variable("v" + str(i))) vfwds.append(Variable("vfwd" + str(i))) vccs.append(Variable("vcc" + str(i))) allConstraints = [] # Store rambus oscillator constraints for i in range(lenV): allConstraints.append(vs[i] >= -1) allConstraints.append(vs[i] <= 1) fwdInd = (i - 1) % lenV ccInd = (i + lenV // 2) % lenV allConstraints.append(vfwds[i] == tanh(a * vs[fwdInd])) allConstraints.append(vccs[i] == tanh(a * vs[ccInd])) allConstraints.append(g_fwd * vfwds[i] + (-g_fwd - g_cc) * vs[i] + g_cc * vccs[i] == 0) allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break # Store constraints pruning search space so that # old hyperrectangles are not considered excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] for i in range(lenV): singleExcludingConstraints.append(vs[i] < solution[i][0]) singleExcludingConstraints.append(vs[i] > solution[i][1]) excludingConstraints.append(singleExcludingConstraints) # Add all the rambus oscillator constraints f_sat = logical_and(*allConstraints) # Add constraints so that old hyperrectangles are not considered if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((lenV, 2)) for i in range(lenV): hyper[i, :] = [ result[vs[i]].lb() - 2 * epsilon, result[vs[i]].ub() + 2 * epsilon ] #print ("hyper", hyper) allSolutions.append(hyper) print("num solutions found", len(allSolutions)) end = time.time() print("time taken", end - start) return allSolutions
def schmittTriggerScMosfet(inputVoltage, numSolutions="all"): epsilon = 1e-14 start = time.time() lenV = 3 Vdd = 1.0 sn = 3 sp = 2 * sn vs = [] tIs = [] nIs = [] for i in range(lenV): vs.append(Variable("v" + str(i))) nIs.append(Variable("nI" + str(i))) for i in range(lenV * 2): tIs.append(Variable("tI" + str(i))) allConstraints = [] for i in range(lenV): allConstraints.append(vs[i] >= 0.0) allConstraints.append(vs[i] <= Vdd) allConstraints += mvs_id('n', 0.0, inputVoltage, vs[1], tIs[0], sn) allConstraints += mvs_id('n', vs[1], inputVoltage, vs[0], tIs[1], sn) allConstraints += mvs_id('n', vs[1], vs[0], Vdd, tIs[2], sn) allConstraints += mvs_id('p', Vdd, inputVoltage, vs[2], tIs[3], sp) allConstraints += mvs_id('p', vs[2], inputVoltage, vs[0], tIs[4], sp) allConstraints += mvs_id('p', vs[2], vs[0], 0.0, tIs[5], sp) allConstraints.append(nIs[0] == -tIs[4] - tIs[1]) allConstraints.append(nIs[1] == -tIs[0] + tIs[1] + tIs[2]) allConstraints.append(nIs[2] == -tIs[3] + tIs[5] + tIs[4]) for i in range(lenV): allConstraints.append(nIs[i] == 0.0) allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break # Store constraints pruning search space so that # old hyperrectangles are not considered excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] for i in range(lenV): singleExcludingConstraints.append(vs[i] < solution[i][0]) singleExcludingConstraints.append(vs[i] > solution[i][1]) excludingConstraints.append(singleExcludingConstraints) #print ("allConstraints") #print (allConstraints) f_sat = logical_and(*allConstraints) if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((lenV, 2)) for i in range(lenV): hyper[i, :] = [ result[vs[i]].lb() - 2 * epsilon, result[vs[i]].ub() + 2 * epsilon ] #print ("hyper", hyper) allSolutions.append(hyper) print("num solutions found", len(allSolutions)) end = time.time() print("time taken", end - start) return allSolutions
def test_nested_forall(): """ Test whether we can choose parameters for a system, such that there is a satisfying solution over an entire range of values. Basically, choose an origin (ox,oy) and the lengths of two arms (l1 & l2) so that there is an angle (t1 & t2) for each arm, that allows it to reach any point within a circle centered at (25,25) with radius 4. We want to make sure that the lengths and origin the tool chooses allows for > there should: > exists. l1 in (0,20) , l2 (0,20), ox (-20,20), oy (-20,20) > > such that: > for all. px in (20, 30), py in (20,30) > > given assumptions: > sqrt((25 - px)**2 + (25 - py)**2) <= 4 > > there should: > exists. t1 in (-pi, pi), t2 in (-pi,pi) > > with constraints: > t2 > t1 > > that meets the requirements: > (px == l2*sin(t1) + l2*sin(t2) + ox) > && (py == l1*cos(t1) + l2*cos(t2) + oy) """ # Parameters l1 = Variable('l1', Variable.Real) l2 = Variable('l2', Variable.Real) ox = Variable('ox', Variable.Real) oy = Variable('oy', Variable.Real) param_bounds = logical_and(l1 > 0, l1 < 20, l2 > 0, l2 < 20, ox > -20, ox < 20, oy > -20, oy < 20) # Independent Variables px = Variable('px', Variable.Real) py = Variable('py', Variable.Real) ivar_bounds = logical_and(px > 20, px < 30, py > 20, py < 30) ivar_assum = sqrt((25 - px)**2 + (25 - py)**2) < 4 # Dependent Variables t1 = Variable('t1', Variable.Real) t2 = Variable('t2', Variable.Real) dvar_bounds = logical_and(t1 >= -3.14, t1 <= 3.14, t2 >= -3.14, t2 <= 3.14, t1 >= t2) req = logical_and(px == l1 * sin(t1) + l2 * sin(t2) + ox, py == l1 * cos(t1) + l2 * cos(t2) + oy) def exists(vs, fun): return logical_not(forall(vs, logical_not(fun))) fun = logical_and( param_bounds, forall([px, py], logical_imply(logical_and(ivar_bounds, ivar_assum), exists([t1, t2], logical_and(dvar_bounds, req))))) result = CheckSatisfiability(fun, 0.01) print(result) assert False
def rambusOscillatorLcMosfet(numStages, numSolutions = "all", g_cc = 0.5, Vtp = -0.4, Vtn = 0.4, Vdd = 1.8, Kn = 270*1e-6, Kp = -90*1e-6, Sn = 3.0): epsilon = 1e-14 start = time.time() #print ("Vtp", Vtp, "Vtn", Vtn, "Vdd", Vdd, "Kn", Kn, "Kp", Kp, "Sn", Sn) g_fwd = 1.0 lenV = numStages*2 Sp = 2*Sn vs = [] ifwdNs = [] ifwdPs = [] iccNs = [] iccPs = [] for i in range(lenV): vs.append(Variable("v" + str(i))) ifwdNs.append(Variable("ifwdN" + str(i))) ifwdPs.append(Variable("ifwdP" + str(i))) iccNs.append(Variable("iccN" + str(i))) iccPs.append(Variable("iccP" + str(i))) allConstraints = [] for i in range(lenV): allConstraints.append(vs[i] >= 0.0) allConstraints.append(vs[i] <= Vdd) allConstraints.append(g_fwd*(-ifwdNs[i]-ifwdPs[i]) + g_cc*(-iccNs[i]-iccPs[i]) == 0) fwdInd = (i-1)%lenV ccInd = (i+lenV//2)%lenV fwdConstraints = nFet(Vtn, Vdd, Kn, Sn, 0.0, vs[fwdInd], vs[i], ifwdNs[i]) fwdConstraints += pFet(Vtp, Vdd, Kp, Sp, Vdd, vs[fwdInd], vs[i], ifwdPs[i]) ccConstraints = nFet(Vtn, Vdd, Kn, Sn, 0.0, vs[ccInd], vs[i], iccNs[i]) ccConstraints += pFet(Vtp, Vdd, Kp, Sp, Vdd, vs[ccInd], vs[i], iccPs[i]) allConstraints += fwdConstraints + ccConstraints allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break # Store constraints pruning search space so that # old hyperrectangles are not considered excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] for i in range(lenV): singleExcludingConstraints.append(vs[i] < solution[i][0]) singleExcludingConstraints.append(vs[i] > solution[i][1]) excludingConstraints.append(singleExcludingConstraints) #print ("allConstraints") #print (allConstraints) f_sat = logical_and(*allConstraints) if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((lenV,2)) for i in range(lenV): hyper[i,:] = [result[vs[i]].lb() - 1000*epsilon, result[vs[i]].ub() + 1000*epsilon] #print ("hyper", hyper) allSolutions.append(hyper) print ("num solutions found", len(allSolutions)) end = time.time() print ("time taken", end - start) return allSolutions
def inverterLoopLcMosfet(numInverters, numSolutions = "all", Vtp = -0.4, Vtn = 0.4, Vdd = 1.8, Kn = 270*1e-6, Kp = -90*1e-6, Sn = 3.0): epsilon = 1e-14 start = time.time() #print ("Vtp", Vtp, "Vtn", Vtn, "Vdd", Vdd, "Kn", Kn, "Kp", Kp, "Sn", Sn) Sp = 2*Sn vs = [] iNs = [] iPs = [] for i in range(numInverters): vs.append(Variable("v" + str(i))) iNs.append(Variable("iN" + str(i))) iPs.append(Variable("iP" + str(i))) allConstraints = [] for i in range(numInverters): allConstraints.append(vs[i] >= 0.0) allConstraints.append(vs[i] <= Vdd) allConstraints.append(-iNs[i]-iPs[i] == 0) inputInd = i outputInd = (i+1)%numInverters allConstraints += nFet(Vtn, Vdd, Kn, Sn, 0.0, vs[inputInd], vs[outputInd], iNs[i]) allConstraints += pFet(Vtp, Vdd, Kp, Sp, Vdd, vs[inputInd], vs[outputInd], iPs[i]) allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break # Store constraints pruning search space so that # old hyperrectangles are not considered excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] for i in range(numInverters): singleExcludingConstraints.append(vs[i] < solution[i][0]) singleExcludingConstraints.append(vs[i] > solution[i][1]) excludingConstraints.append(singleExcludingConstraints) #print ("allConstraints") #print (allConstraints) f_sat = logical_and(*allConstraints) if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((numInverters,2)) for i in range(numInverters): hyper[i,:] = [result[vs[i]].lb() - 1000*epsilon, result[vs[i]].ub() + 1000*epsilon] #print ("hyper", hyper) allSolutions.append(hyper) print ("num solutions found", len(allSolutions)) end = time.time() print ("time taken", end - start) return allSolutions
def schmittTriggerLcMosfet(inputVoltage, Vtp = -0.4, Vtn = 0.4, Vdd = 1.8, Kn = 270*1e-6, Kp = -90*1e-6, Sn = 3.0, numSolutions = "all"): epsilon = 1e-14 start = time.time() #print ("Vtp", Vtp, "Vtn", Vtn, "Vdd", Vdd, "Kn", Kn, "Kp", Kp, "Sn", Sn) Sp = Sn *2.0 lenV = 3 vs = [] tIs = [] nIs = [] for i in range(lenV): vs.append(Variable("v" + str(i))) nIs.append(Variable("nI" + str(i))) for i in range(lenV*2): tIs.append(Variable("tI" + str(i))) allConstraints = [] for i in range(lenV): allConstraints.append(vs[i] >= 0.0) allConstraints.append(vs[i] <= 1.8) allConstraints += nFetLeak(Vtn, Vdd, Kn, Sn, 0.0, inputVoltage, vs[1], tIs[0]) allConstraints += nFetLeak(Vtn, Vdd, Kn, Sn, vs[1], inputVoltage, vs[0], tIs[1]) allConstraints += nFetLeak(Vtn, Vdd, Kn, Sn, vs[1], vs[0], Vdd, tIs[2]) allConstraints += pFetLeak(Vtp, Vdd, Kp, Sp, Vdd, inputVoltage, vs[2], tIs[3]) allConstraints += pFetLeak(Vtp, Vdd, Kp, Sp, vs[2], inputVoltage, vs[0], tIs[4]) allConstraints += pFetLeak(Vtp, Vdd, Kp, Sp, vs[2], vs[0], 0.0, tIs[5]) allConstraints.append(nIs[0] == -tIs[4] - tIs[1]) allConstraints.append(nIs[1] == -tIs[0] + tIs[1] + tIs[2]) allConstraints.append(nIs[2] == -tIs[3] + tIs[5] + tIs[4]) for i in range(lenV): allConstraints.append(nIs[i] == 0.0) allSolutions = [] while True: if numSolutions != "all" and len(allSolutions) == numSolutions: break # Store constraints pruning search space so that # old hyperrectangles are not considered excludingConstraints = [] for solution in allSolutions: singleExcludingConstraints = [] for i in range(lenV): singleExcludingConstraints.append(vs[i] < solution[i][0]) singleExcludingConstraints.append(vs[i] > solution[i][1]) excludingConstraints.append(singleExcludingConstraints) #print ("allConstraints") #print (allConstraints) #print ("numConstraints", len(allConstraints)) f_sat = logical_and(*allConstraints) if len(excludingConstraints) > 0: for constraints in excludingConstraints: f_sat = logical_and(f_sat, logical_or(*constraints)) #print ("f_sat") #print (f_sat) result = CheckSatisfiability(f_sat, epsilon) #print (result) if result is None: break hyper = np.zeros((lenV,2)) for i in range(lenV): hyper[i,:] = [result[vs[i]].lb() - 1000*epsilon, result[vs[i]].ub() + 1000*epsilon] #print ("hyper", hyper) allSolutions.append(hyper) print ("num solutions found", len(allSolutions)) end = time.time() print ("time taken", end - start) return allSolutions