def test_output(self): # To write to an output file, create a new solver and pass it the name of a file to write to # All constraints created in that new solver will be copied to that file test_file = tempfile.NamedTemporaryFile() filename = test_file.name test_file.close() monosat.Monosat().newSolver(output_file=filename) a = monosat.Var() b = monosat.Var() c = monosat.Or(a, monosat.Not(b)) monosat.Assert(c) monosat.Assert(monosat.Not(c)) # trivial contradition, so result should be UNSAT result = monosat.Solve() self.assertFalse(result) monosat.Monosat().newSolver( ) # create a new solver, this time without any output file set. # solver now has no constraints, so it should be SAT self.assertTrue(monosat.Solve()) # read in the previously saved constraints (these can also be read in on the command line, eg ./monosat tutorial.gnf monosat.Monosat().loadConstraints(filename) result2 = monosat.Solve() self.assertEqual(result, result2) os.remove(filename)
def test_setOutputFile(self): # this tests the deprecated setOutputFile interface test_file = tempfile.NamedTemporaryFile() filename = test_file.name test_file.close() monosat.Monosat().newSolver(arguments="-decide-theories") with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") monosat.Monosat().setOutputFile(output_file=filename) self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) self.assertTrue("deprecated" in str(w[-1].message)) a = monosat.Var() b = monosat.Var() c = monosat.Or(a, monosat.Not(b)) monosat.Assert(c) monosat.Assert(monosat.Not(c)) # trivial contradition, so result should be UNSAT result = monosat.Solve() self.assertFalse(result) monosat.Monosat().newSolver( ) # create a new solver, this time without any output file set. # solver now has no constraints, so it should be SAT self.assertTrue(monosat.Solve()) # read in the previously saved constraints (these can also be read in on the command line, eg ./monosat tutorial.gnf monosat.Monosat().loadConstraints(filename) result2 = monosat.Solve() self.assertEqual(result, result2) os.remove(filename)
def test_maximumFlow_geq(self): monosat.Monosat().newSolver() g = monosat.Graph() for i in range(4): g.addNode() # create a directed square graph with one diagonal edge # # 0 *--* 1 # |/ | # 2 *--* 3 e_0_1 = g.addEdge(0, 1, monosat.BitVector(4, 1)) e_0_2 = g.addEdge(0, 2, monosat.BitVector(4, 1)) e_1_3 = g.addEdge(1, 3, monosat.BitVector(4, 1)) e_1_2 = g.addEdge(1, 2, monosat.BitVector(4, 2)) e_2_3 = g.addEdge(2, 3, monosat.BitVector(4, 1)) cmp = monosat.BitVector(4) f = g.maxFlowGreaterOrEqualTo(0, 3, cmp) self.assertTrue(monosat.Solve(f)) self.assertFalse(monosat.Solve(f, cmp.eq(3))) self.assertTrue(monosat.Solve(f, cmp.eq(2))) self.assertTrue(monosat.Solve(f, cmp.eq(1))) self.assertTrue(monosat.Solve(f, e_0_1.Not(), e_2_3.Not())) self.assertFalse(monosat.Solve(f, e_0_1.Not(), e_2_3.Not(), cmp.eq(1))) self.assertTrue(monosat.Solve(f, e_0_2.Not(), e_1_3.Not())) self.assertTrue(monosat.Solve(f))
def test_reachesBack(self): monosat.Monosat().newSolver() g = monosat.Graph() for i in range(4): g.addNode() # create a directed square graph with one diagonal edge # # 0 *--* 1 # |/ | # 2 *--* 3 e_0_1 = g.addEdge(0, 1) e_0_2 = g.addEdge(0, 2) e_1_3 = g.addEdge(1, 3) e_1_2 = g.addEdge(1, 2) e_2_3 = g.addEdge(2, 3) r = g.reachesBackward(3, 0) r2 = g.reachesBackward(0, 3) self.assertTrue(monosat.Solve(r)) self.assertFalse(monosat.Solve(r2)) self.assertTrue(monosat.Solve(r)) self.assertFalse(monosat.Solve(r, e_0_1.Not(), e_2_3.Not())) self.assertTrue(monosat.Solve(r, e_0_2.Not(), e_1_3.Not())) self.assertFalse( monosat.Solve(r, e_0_2.Not(), e_1_3.Not(), e_2_3.Not())) self.assertTrue(monosat.Solve(r, e_0_2.Not(), e_1_3.Not())) # There should only be one solution to this: 0->1, 1->2, 2->3 nodes = g.getPath(r, False) edges = g.getPath(r, True) self.assertEqual(len(edges), 3) self.assertEqual(len(nodes), 4) self.assertEqual(edges[2], e_0_1) self.assertEqual(edges[1], e_1_2) self.assertEqual(edges[0], e_2_3) self.assertTrue(e_0_1.value()) self.assertTrue(e_1_2.value()) self.assertTrue(e_2_3.value()) self.assertFalse(e_0_2.value()) self.assertFalse(e_1_3.value()) self.assertTrue(monosat.Solve(r))
def test_acyclicUndirected(self): monosat.Monosat().newSolver() g = monosat.Graph() for i in range(4): g.addNode() # create a directed square graph with two diagonal edges # # 0 *--* 1 # |/\| # 2 *--* 3 e_0_1 = g.addEdge(0, 1) e_0_2 = g.addEdge(0, 2) e_1_3 = g.addEdge(1, 3) e_1_2 = g.addEdge(1, 2) e_2_3 = g.addEdge(2, 3) e_3_0 = g.addEdge(3, 0) r = g.acyclic(False) self.assertTrue(monosat.Solve(r)) self.assertTrue(monosat.Solve(r, e_0_1.Not(), e_2_3.Not())) self.assertTrue(monosat.Solve(r, e_0_2.Not(), e_1_3.Not())) self.assertTrue(monosat.Solve(r, e_0_2.Not(), e_1_3.Not(), e_2_3.Not())) self.assertFalse(monosat.Solve(r, e_0_1, e_1_2, e_2_3, e_3_0)) self.assertTrue(monosat.Solve(r)) self.assertTrue(monosat.Solve(r.Not())) # valid undirected cycle: e_3_0 -> e_0_2 -> e_1_2 -> e_1_3 self.assertTrue(monosat.Solve(r.Not(), e_0_1.Not(), e_2_3.Not())) self.assertFalse( monosat.Solve(r.Not(), e_0_1.Not(), e_2_3.Not(), e_1_3.Not())) self.assertTrue(monosat.Solve(r.Not(), e_0_2.Not(), e_1_3.Not())) self.assertFalse( monosat.Solve(r.Not(), e_0_2.Not(), e_1_3.Not(), e_2_3.Not())) self.assertTrue(monosat.Solve(r.Not(), e_0_1, e_1_2, e_2_3, e_3_0)) self.assertTrue(monosat.Solve(r.Not())) self.assertTrue(monosat.Solve(r))
def test_distance(self): monosat.Monosat().newSolver() g = monosat.Graph() for i in range(4): g.addNode() # create a directed square graph with one diagonal edge # # 0 *--* 1 # |/ | # 2 *--* 3 e_0_1 = g.addEdge(0, 1, monosat.BitVector(4, 1)) e_0_2 = g.addEdge(0, 2, monosat.BitVector(4, 1)) e_1_3 = g.addEdge(1, 3, monosat.BitVector(4, 1)) e_1_2 = g.addEdge(1, 2, monosat.BitVector(4, 2)) e_2_3 = g.addEdge(2, 3, monosat.BitVector(4, 1)) dist = monosat.BitVector(4) d = g.distance_leq(0, 3, dist) monosat.AssertTrue(d) self.assertTrue(monosat.Solve(dist.gt(0))) self.assertFalse(monosat.Solve(dist.eq(0))) self.assertFalse(monosat.Solve(dist.eq(1))) self.assertTrue(monosat.Solve(dist.eq(2))) self.assertTrue(monosat.Solve(dist.eq(3))) self.assertFalse(monosat.Solve(e_0_1, e_0_2, e_1_3, e_2_3, dist.eq(1))) self.assertTrue(monosat.Solve(e_0_1, e_0_2, e_1_3, e_2_3, dist.eq(2))) self.assertTrue(monosat.Solve(e_0_1, e_0_2, e_1_3, e_2_3, dist.eq(3))) self.assertFalse(monosat.Solve(e_0_1.Not(), e_2_3.Not())) self.assertTrue(monosat.Solve(e_0_2.Not(), e_1_3.Not())) self.assertFalse( monosat.Solve(e_0_2.Not(), e_1_3.Not(), e_2_3.Not(), dist.eq(1)))
def route(fab, des, model, verbose=False): ''' attempt to globally (doesn't consider track widths and allows sharing wires) route all of the placed components ''' g, CBr, CBb, SB, CBedges = build_mgraph(fab, des.components) dist = total_L1(des.components, model) print('Placed components have a total L1 distance = ', dist) #if made false, still not necessarily unroutable, just unroutable for the given netlist ordering successful_routes = [] heuristic_routable = True for pc in des.get_sorted_components(True): #keeps track of edges used by this component #to allow fanout, only increments edges once for each component #TODO: verify electrical correctness used_edges = set() for wire in pc.outputs_list: reaches = g.reaches(fab.getNode(wire.src),fab.getNode(wire.dst)) dist = __dist_factor*comp_dist(wire.src, wire.dst, model) + __dist_freedom dist_constraint = g.distance_leq(fab.getNode(wire.src),fab.getNode(wire.dst), dist) c = excl_constraints(wire.src, wire.dst, des.components, fab, g) c.append(reaches) c.append(dist_constraint) sys.stdout = open(os.devnull, 'w') result = ms.Solve(ms.And(c)) sys.stdout = sys.__stdout__ #for now, using one smaller relaxations #variable_dist_factor = 2*__dist_factor if not result: if verbose: print('Not routable with given distance constraint, relaxing distance and trying again') del c[-1] dist = 2*comp_dist(wire.src, wire.dst, model) + __dist_freedom dist_constraint = g.distance_leq(fab.getNode(wire.src),fab.getNode(wire.dst), dist) c.append(dist_constraint) sys.stdout = open(os.devnull, 'w') result = ms.Solve(ms.And(c)) sys.stdout = sys.__stdout__ # variable_dist_factor = 2*variable_dist_factor #do a complete relaxation if not routed if not result: if verbose: print('Not routable with given distance constraint, relaxing distance and trying again') del c[-1] sys.stdout = open(os.devnull, 'w') result = ms.Solve(ms.And(c)) sys.stdout = sys.__stdout__ if result: #If the result is SAT, you can find the nodes that make up a satisfying path: path_node_names = [] for node in g.getPath(reaches): path_node_names.append(g.names[node]) if node in CBedges: for e in CBedges[node]: used_edges.add(e) if verbose: print("Satisfying path (as a list of nodes): " + str(path_node_names)) #save path successful_routes.append(path_node_names) else: heuristic_routable = False #TODO: if fail to route, need to reorder and possibly re-place if verbose: print('Failed to route') print(g.names[fab.getNode(wire.src)]) print(g.names[fab.getNode(wire.dst)]) #increment the edge counts for edge in used_edges: fab.incrementEdge(edge) #generate names CBrnames = set() for row in CBr: for col in row: CBrnames.add(g.names[col]) CBbnames = set() for row in CBb: for col in row: CBbnames.add(g.names[col]) SBnames = set() for row in SB: for col in row: SBnames.add(g.names[col]) return heuristic_routable, successful_routes, CBrnames, CBbnames, SBnames
def solve(self, *args): # ms.Assert(self.And(self.constraints)) self.sat = ms.Solve(*args) return self.sat
def solve(self): ms.Assert(self.And(self.constraints)) self.sat = ms.Solve() return self.sat