Exemplo n.º 1
0
 def operate_on(self, G):
     # Operates on the graph G by contracting an edge and unifying the adjacent vertices.
     image = []
     for (i, e) in enumerate(G.edges(labels=False)):
         (u, v) = e
         # print("contract", u, v)
         pp = Shared.permute_to_left((u, v), range(0,
                                                   self.domain.n_vertices))
         sgn = self.domain.perm_sign(G, pp)
         G1 = copy(G)
         G1.relabel(pp, inplace=True)
         Shared.enumerate_edges(G1)
         previous_size = G1.size()
         G1.merge_vertices([0, 1])
         if (previous_size - G1.size()) != 1:
             continue
         # print(sgn)
         G1.relabel(list(range(0, G1.order())), inplace=True)
         if not self.domain.even_edges:
             # p = [j for (a, b, j) in G1.edges()]
             # sgn *= Permutation(p).signature()
             sgn *= Shared.shifted_edge_perm_sign(G1)
         else:
             sgn *= -1  # TODO overall sign for even edges
         image.append((G1, sgn))
     return image
Exemplo n.º 2
0
 def operate_on(self,G):
     # Operate on a hairy graph by deleting an edge and adding a hair to one of the vertices adjacent to the
     # deleted edge.
     sgn0 = -1 if G.order() % 2 else 1
     image=[]
     for (i, e) in enumerate(G.edges(labels=False)):
         (u, v) = e
         # Only edges not connected to a hair-vertex can be cut
         if u >= self.domain.n_vertices or v >= self.domain.n_vertices:
             continue
         G1 = copy(G)
         if not self.domain.even_edges:
             Shared.enumerate_edges(G1)
             e_label = G1.edge_label(u, v)
         G1.delete_edge((u, v))
         new_hair_idx = self.domain.n_vertices + self.domain.n_hairs
         G1.add_vertex(new_hair_idx)
         G2 = copy(G1)
         G1.add_edge((u, new_hair_idx))
         G2.add_edge((v, new_hair_idx))
         if not self.domain.even_edges:
             G1.set_edge_label(u, new_hair_idx, e_label)
             G2.set_edge_label(v, new_hair_idx, e_label)
             sgn1 = Shared.edge_perm_sign(G1)
             sgn2 = Shared.edge_perm_sign(G2)
         else:
             sgn1 = 1
             sgn2 = -1
         image.append((G1, sgn1*sgn0))
         image.append((G2, sgn2*sgn0))
     return image
Exemplo n.º 3
0
    def operate_on(self, G):
        # Operate on a bi colored hairy graph by deleting an edge and adding a hair of colour a to one of the adjacent
        # vertices and a hair of colour b to the other adjacent vertex.
        sgn0 = -1 if G.order() % 2 else 1
        image = []
        for (i, e) in enumerate(G.edges(labels=False)):
            (u, v) = e
            # Only edges not connected to a hair-vertex can be split.
            if u >= self.domain.n_vertices or v >= self.domain.n_vertices:
                continue
            G1 = copy(G)
            if not self.domain.even_edges:
                Shared.enumerate_edges(G1)
                e_label = G1.edge_label(u, v)
            G1.delete_edge((u, v))

            new_hair_idx_1 = self.domain.n_vertices + self.domain.n_hairs
            new_hair_idx_2 = new_hair_idx_1 + 1

            G1.add_vertex(new_hair_idx_1)
            G1.add_edge((u, new_hair_idx_1))
            G1.add_vertex(new_hair_idx_2)
            G1.add_edge((v, new_hair_idx_2))
            G2 = copy(G1)

            vertices = list(range(0, self.domain.n_vertices))
            vertices = [] if vertices is None else vertices
            start_idx_a = self.domain.n_vertices
            start_idx_b = self.domain.n_vertices + self.domain.n_hairs_a + 1
            hairs_a = list(range(start_idx_a + 1, start_idx_b))
            hairs_a = [] if hairs_a is None else hairs_a
            hairs_b = list(range(start_idx_b, new_hair_idx_2))
            hairs_b = [] if hairs_b is None else hairs_b
            p = vertices + hairs_a + hairs_b

            p1 = p + [start_idx_a, new_hair_idx_2]
            G1.relabel(p1)
            p2 = p + [new_hair_idx_2, start_idx_a]
            G2.relabel(p2)

            if not self.domain.even_edges:
                G1.set_edge_label(u, start_idx_a, e_label)
                G1.set_edge_label(v, new_hair_idx_2, G1.size() - 1)
                sgn1 = Shared.edge_perm_sign(G1)
                G2.set_edge_label(v, start_idx_a, e_label)
                G2.set_edge_label(u, new_hair_idx_2, G2.size() - 1)
                sgn2 = Shared.edge_perm_sign(G2)
            else:
                sgn1 = 1
                sgn2 = -1
            image.append((G1, sgn1 * sgn0))
            image.append((G2, sgn2 * sgn0))
        return image
Exemplo n.º 4
0
 def perm_sign(self, G, p):
     if self.even_edges:
         # The sign is (induced sign on vertices) * (induced sign edge orientations)
         sign = Shared.Perm(p).signature()
         for (u, v) in G.edges(labels=False):
             # We assume the edge is always directed from the larger to smaller index
             if (u < v and p[u] > p[v]) or (u > v and p[u] < p[v]):
                 sign *= -1
         return sign
     else:
         # The sign is (induced sign of the edge permutation)
         # We assume the edges are always lexicographically ordered
         # For the computation we use that G.edges() returns the edges in lex ordering
         # We first label the edges on a copy of G lexicographically
         G1 = copy(G)
         Shared.enumerate_edges(G1)
         # We permute the graph, and read of the new labels
         G1.relabel(p, inplace=True)
         return Shared.Perm([j for (u, v, j) in G1.edges()]).signature()
Exemplo n.º 5
0
 def operate_on(self,G):
     # Operates on the graph G by contracting an edge and unifying the adjacent vertices.
     image=[]
     for (i, e) in enumerate(G.edges(labels=False)):
         (u, v) = e
         # only edges not connected to a hair-vertex can be contracted
         if u >= self.domain.n_vertices or v >= self.domain.n_vertices:
             continue
         pp = Shared.permute_to_left((u, v), range(0, self.domain.n_vertices + self.domain.n_hairs))
         sgn = self.domain.perm_sign(G, pp)
         G1 = copy(G)
         G1.relabel(pp, inplace=True)
         Shared.enumerate_edges(G1)
         previous_size = G1.size()
         G1.merge_vertices([0, 1])
         if (previous_size - G1.size()) != 1:
             continue
         G1.relabel(list(range(0, G1.order())), inplace=True)
         if not self.domain.even_edges:
             sgn *= Shared.shifted_edge_perm_sign(G1)
         image.append((G1, sgn))
     return image
Exemplo n.º 6
0
    def operate_on(self, G):
        # Operates on the graph G by contracting an edge and unifying the adjacent vertices.
        image = []
        for (i, e) in enumerate(G.edges(labels=False)):
            (u, v) = e
            # only edges not connected to a numbered hair-vertex can be contracted
            if u >= self.domain.n_vertices + 2 or v >= self.domain.n_vertices + 2:
                continue

            # ensure u<v (this should be always true anyway actually)
            if u > v:
                u, v = v, u

            sgn = 1 if i % 2 == 0 else -1
            previous_size = G.size()
            previous_has_tadpole = (previous_size - self.domain.n_vertices -
                                    self.domain.n_hairs < self.domain.n_loops)
            sgn *= -1 if previous_has_tadpole else 1
            G1 = copy(G)
            # label all edges to determine sign later
            Shared.enumerate_edges(G1)

            # we always delete the lower index vertex. This ensures that the extra vertices are never deleted
            if v <= self.domain.n_vertices:
                G1.merge_vertices([v, u])
                if (previous_size - G1.size()) != 1:
                    continue
                G1.relabel(range(
                    0, self.domain.n_vertices + 1 + self.domain.n_hairs),
                           inplace=True)
                # find edge permutation sign
                sgn *= Shared.shifted_edge_perm_sign2(G1)
                image.append((G1, sgn))
            elif v == self.domain.n_vertices + 1:
                # the second vertex is now omega, so we need to merge the vertex with the eps vertex
                # after reonnecting one of the edges to omega
                # we assume that u != eps, because this is forbidden in our graphs
                G1.delete_edge(u, v)
                # special care must be taken since a tadpole could be created at eps
                # and this is true iff there is an edge u-eps
                eps = self.domain.n_vertices
                new_has_tadpole = G1.has_edge(u, eps)
                # double tadpole => zero
                if new_has_tadpole and previous_has_tadpole:
                    continue
                if new_has_tadpole:
                    # remove the edge and compute the appropriate sign
                    k = G1.edge_label(u, eps)
                    G1.delete_edge(u, eps)
                    sgn *= 1 if ((k % 2 == 0) == (k < i)) else -1
                # loop over other neighbors w to be connected to omega
                for w in G1.neighbors(u):
                    G2 = copy(G1)
                    sgn2 = sgn
                    # reconnect the w-v-edge to omega (i.e., to v)
                    old_label = G2.edge_label(u, w)
                    G2.delete_edge(u, w)
                    G2.add_edge(w, v, old_label)

                    # now merge u and eps
                    G2.merge_vertices([eps, u])
                    # in case we have too few edges some double edges have been created => zero
                    if (previous_size -
                            G2.size()) != (2 if new_has_tadpole else 1):
                        continue
                    G2.relabel(range(
                        0, self.domain.n_vertices + 1 + self.domain.n_hairs),
                               inplace=True)
                    # find edge permutation sign
                    sgn2 *= Shared.shifted_edge_perm_sign2(G2)
                    image.append((G2, sgn2))

        return image