Ejemplo n.º 1
0
class GraphOntoRectangularGrid(object):
    """
        Locations in the grid are tuples (x, y), 0-based.
        Each vertex maps to one grid location.
        It is possible for a grid location to map to multiple vertices.
    """
    def __init__(self, width, height=None):
        height = height or width
        assert width > 0 and height > 0
        self._width = width
        self._height = height
        self._graph = SimpleGraph()
        self._locationMap = {}  # vertex : location
        for x, y in product(range(self._width), range(self._height)):
            v = self.pushVertex((x, y))
            if x > 0:
                self._graph.addEdge(v, self.singleVertexAt((x - 1, y)))
            if y > 0:
                self._graph.addEdge(v, self.singleVertexAt((x, y - 1)))

    @property
    def width(self):
        return self._width

    @property
    def height(self):
        return self._height

    @property
    def graph(self):
        return self._graph.asReadOnly()

    def getLocationMap(self):
        return dict((v, tuple(c)) for v, c in self._locationMap.items())

    def pushVertex(self, xy):
        x, y = xy
        assert 0 <= x < self._width
        assert 0 <= y < self._height
        v = self._graph.pushVertex()
        self._locationMap[v] = xy
        return v

    def removeVertex(self, v):
        self._graph.removeVertex(v)
        del self._locationMap[v]

    def removeVertexAt(self, xy):
        self.removeVertex(self.singleVertexAt(xy))

    def addEdge(self, v1, v2):
        self._graph.addEdge(v1, v2)

    def removeUniqueEdge(self, xy1, xy2):
        v1, v2 = map(self.singleVertexAt, (xy1, xy2))
        self._graph.removeEdge(v1, v2)

    def verticesAt(self, xy):
        """Get the set of any/all vertices mapped to location."""
        return set(k for k, v in self._locationMap.items() if v == xy)

    def singleVertexAt(self, xy):
        """Get the single vertex mapped to location. Error if not 1-to-1."""
        v = self.verticesAt(xy)
        assert len(v) == 1
        return v.pop()

    def adjacenciesAt(self, xy):
        return self._graph.adjacencies(self.singleVertexAt(xy))

    def orthogonalAdjacencies(self, xy):
        x, y = xy
        a = self.adjacenciesAt(xy)
        xa = a & (self.verticesAt((x - 1, y)) | self.verticesAt((x + 1, y)))
        ya = a & (self.verticesAt((x, y - 1)) | self.verticesAt((x, y + 1)))
        return xa, ya
Ejemplo n.º 2
0
def _testGraph():
    g = SimpleGraph()
    assert isinstance(g, QueryableSimpleGraph)
    assert not isinstance(g.asReadOnly(), SimpleGraph)
    assert isinstance(g.asReadOnly(), QueryableSimpleGraph)
    g.assertSimple()
    verts = []
    for i in range(10):
        verts.append(g.pushVertex())
    try:
        g.addVertex(verts[0])
        raise AssertionError
    except ValueError:
        pass
    assert len(set(verts)) == len(verts)
    for v in verts:
        assert not g.adjacencies(v)
        assert g.connectedComponent(v) == {v}
        assert not g.isSeparator(v)
        assert g.isConnectedSet([v])
    parts = g.disjointPartitions()
    assert len(parts) == len(verts)
    s = set()
    for p in parts:
        assert len(p) == 1
        s.add(p.pop())
    assert s == set(verts)
    edgeCount = 0
    assert g.edgeCount() == edgeCount
    assert g.edgeCount(without=set()) == g.edgeCount()
    for i in range(len(verts) - 1):
        edgeCount += 1
        g.addEdge(verts[i], verts[i + 1])
        for v in verts[i + 2:]:
            assert not g.connected(verts[i + 1], v)
            assert not g.connected(v, verts[i + 1])
        for j in range(i + 1):
            if j > 0:
                assert g.connected(verts[0], verts[j])
                assert g.connected(verts[j], verts[0])
            assert g.connectedComponent(verts[j]) == set(verts[:i + 2])
        assert g.edgeCount() == edgeCount
    assert g.edgeCount(without=set()) == g.edgeCount()
    assert g.edgeCount(mask=verts) == g.edgeCount()
    for v in verts:
        assert g.edgeCount(mask={v}) == 0
        assert g.connectedComponent(v) == set(verts)
    assert g.isConnectedSet(verts)
    assert g.isConnectedSet([verts[2], verts[4]], verts[2:5])
    assert not g.isConnectedSet([verts[2], verts[4]], [verts[2], verts[4]])
    assert g.isConnectedSet(verts[:4] + verts[5:])
    assert not g.isConnectedSet(verts[:4] + verts[5:], verts[:4] + verts[5:])
    assert not g.isSeparator(verts[0])
    assert not g.isSeparator(verts[-1])
    assert all(g.isSeparator(v) for v in verts[1:-1])
    assert g.shortestPath(verts[0], verts[-1]) == verts
    assert g.shortestPath(verts[-1], verts[0]) == list(reversed(verts))
    assert g.shortestPath(verts[3], verts[3]) == [verts[3]]

    shortcut = g.pushVertex()
    edgeCount += 2
    g.addEdge(verts[0], shortcut)
    g.addEdge(verts[-1], shortcut)
    assert g.shortestPath(verts[0], verts[-1]) == \
        [verts[0], shortcut, verts[-1]]

    assert verts[0] == 0
    edgeCount -= 1
    g.removeEdge(verts[-1], shortcut)
    assert g.shortestPath(shortcut, verts[1]) == [shortcut, verts[0], verts[1]]
    edgeCount -= len(g.adjacencies(shortcut))
    assert g.edgeCount(without={shortcut}) == edgeCount
    g.removeVertex(shortcut)
    assert g.edgeCount() == edgeCount
    # noinspection PyUnusedLocal
    edgeCount = None

    g.addEdge(verts[0], verts[-1])
    assert g.shortestPath(verts[0], verts[-1]) == [verts[0], verts[-1]]
    assert not any(g.isSeparator(v) for v in verts)
    g.removeEdge(verts[0], verts[-1])
    g.asReadOnly()
    mask = verts[:2] + verts[3:]
    parts = g.disjointPartitions(mask)
    assert len(parts) == 2
    assert not parts[0].intersection(parts[1])
    assert g.isConnectedSet(parts[0])
    assert g.isConnectedSet(parts[1])
    for v1 in parts[0]:
        for v2 in parts[1]:
            assert g.shortestPath(v1, v2, mask) == []
    assert not g.isConnectedSet(mask, mask)
    assert verts[2] not in parts[0].union(parts[1])
    assert parts[0].union(parts[1]) == set(verts) - set(verts[2:3])
    drops = [verts[i] for i in [2, 5, 8]]
    for v in drops:
        g.removeVertex(v)
        verts.remove(v)
    assert not g.adjacencies(verts[-1])
    for v in verts[:-1]:
        assert len(g.adjacencies(v)) == 1
        assert not g.isSeparator(v)
    g.assertSimple()
    assert len(g.disjointPartitions()) == 4
    assert len(g.disjointPartitions(verts[1:])) == 4
    assert len(g.disjointPartitions(verts[2:])) == 3
    assert g.connectedComponent(verts[-1]) == set(verts[-1:])
    assert g.connectedComponent(verts[1], verts[1:]) == set(verts[1:2])
    backbone = [list(p)[0] for p in g.disjointPartitions()]
    for i in range(len(backbone) - 1):
        g.addEdge(backbone[i], backbone[i + 1])
    g.addEdge(backbone[0], backbone[-1])
    assert len(g.disjointPartitions()) == 1
    assert g.connectedComponent(verts[0]) == set(verts)
    assert g.connected(verts[0], verts[-1])
    assert g.isConnectedSet(set(verts[:1] + verts[-1:]))
    assert g.edgeCount(without={3, 6}) == g.edgeCount() - 5
    assert g.edgeCount(without={0, 9}) == g.edgeCount() - 4