예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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))
예제 #4
0
    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))
예제 #5
0
    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))
예제 #6
0
    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)))
예제 #7
0
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
예제 #8
0
    def solve(self, *args):
#        ms.Assert(self.And(self.constraints))
        self.sat = ms.Solve(*args)
        return self.sat
예제 #9
0
파일: solvers.py 프로젝트: leonardt/SMT-PNR
 def solve(self):
     ms.Assert(self.And(self.constraints))
     self.sat = ms.Solve()
     return self.sat