Ejemplo n.º 1
0
    def components(self):
        """
        Returns a list of the connected components of the multicurve
        corresponding to the 1-cycle, each given as a OneCycle.

        Assumes for simplicity that the weights are at most one and
        the support of the cycle is a simple multicurve.
        """
        assert all(abs(w) <= 1 for w in self.weights)
        D = self.cellulation
        G = Graph(multiedges=True)
        for edge in D.edges:
            if self.weights[edge.index] != 0:
                i, j = [v.index for v in edge.vertices]
                G.add_edge(i, j, edge.index)

        assert G.num_verts() == G.num_edges()

        ans = []
        for H in G.connected_components_subgraphs():
            weights = len(self.weights) * [0]
            for i in H.edge_labels():
                weights[i] = self.weights[i]
            ans.append(OneCycle(self.cellulation, weights))
        return ans
Ejemplo n.º 2
0
    def sage(self):
        from sage.all import Graph
        G = Graph(multiedges=True, loops=True)

        vertices = map(tuple, self.vertices())
        edges = map(tuple, self.edges())
        embedding = {}
        for vertex in vertices:
            vertex_order = []
            for label in vertex:
                for edge in edges:
                    if label in edge:
                        break
                G.add_edge(vertex, edge)
                vertex_order.append(edge)
            embedding[vertex] = vertex_order

        for edge in edges:
            edge_order = []
            for label in edge:
                for vertex in vertices:
                    if label in vertex:
                        break
                edge_order.append(vertex)
            embedding[edge] = edge_order

        G.set_embedding(embedding)
        return G
Ejemplo n.º 3
0
def tree_to_graph(tree):
    """
	returns the corresponding cograph of the tree
	"""
    g = Graph()
    tree_to_graph_rec(tree, g)
    return g
Ejemplo n.º 4
0
    def cycle_has_orthogonal_diagonals(self, cycle):
        r"""
        Return if the NAC-coloring implies orthogonal diagonals for a given 4-cycle.

        EXAMPLE::

            sage: from flexrilog import GraphGenerator
            sage: K33 = GraphGenerator.K33Graph()
            sage: [[delta.name(), [cycle for cycle in K33.four_cycles() if delta.cycle_has_orthogonal_diagonals(cycle)]] for delta in K33.NAC_colorings()]
            [['omega5', []],
             ['omega3', []],
             ['omega1', []],
             ['omega6', []],
             ['epsilon56', [(1, 2, 3, 4)]],
             ['epsilon36', [(1, 2, 5, 4)]],
             ['epsilon16', [(2, 3, 4, 5)]],
             ['omega4', []],
             ['epsilon45', [(1, 2, 3, 6)]],
             ['epsilon34', [(1, 2, 5, 6)]],
             ['epsilon14', [(2, 3, 6, 5)]],
             ['omega2', []],
             ['epsilon25', [(1, 4, 3, 6)]],
             ['epsilon23', [(1, 4, 5, 6)]],
             ['epsilon12', [(3, 4, 5, 6)]]]
        """
        if len(cycle) != 4:
            raise exceptions.ValueError('The cycle must be a 4-cycle.')
        if self.path_is_unicolor(list(cycle) + [cycle[0]]):
            if self.is_red(cycle[0], cycle[1]):
                subgraph = Graph([
                    self._graph.vertices(),
                    [list(e) for e in self.blue_edges()]
                ],
                                 format='vertices_and_edges')
            else:
                subgraph = Graph([
                    self._graph.vertices(),
                    [list(e) for e in self.red_edges()]
                ],
                                 format='vertices_and_edges')
            if subgraph.shortest_path(cycle[0],
                                      cycle[2]) and subgraph.shortest_path(
                                          cycle[1], cycle[3]):
                return True
            else:
                return False
        return False
Ejemplo n.º 5
0
 def sage_graph(self):
     sage_edges = [(e[0], e[1], {
         'weight': w,
         'sign': s,
         'index': i
     }) for (
         i, e), w, s in zip(enumerate(self.edges), self.weights, self.signs)
                   ]
     return Graph([list(range(self.nvertices)), sage_edges],
                  loops=True,
                  multiedges=True)
Ejemplo n.º 6
0
def read_graph(filename: str) -> Graph:
    g_file = open(filename)

    first_line = g_file.readline()
    num_verts = int(first_line)

    g = Graph(num_verts)

    for line in g_file:
        u, v, w = map(int, line.split())
        g.add_edge(u, v, w)

    return g
Ejemplo n.º 7
0
    def __init__(self, edges, loops, kappa):
        '''
        Construct a Labeled Stable Graph -- the canonical representative of the labeled stable graph given by edges, loops and           kappa, where:

        - ``edges``  -- tuple of triples, where a triple (v1,v2,m) means that the vertices v1 and v2 are connected by m edges
        - ``loops``  -- tuple, where an integer loops[i] is the number of loops associated to the vertex i
        - ``kappa``  -- tuple of tuples, a partition of stratum into subpartitions, where kappa[i] is a subpartition of orders of zeroes associated to the vertex i
        
        Lists can be used instead of tuples, as they will be automatically converted to be immutable.
        '''
        if not edges:
            graph = Graph(weighted=True, loops=False, multiedges=False)
            graph.add_vertex()
        else:
            graph = Graph(list(edges),
                          loops=False,
                          multiedges=False,
                          weighted=True)
        self.edges, self.loops, self.kappa, self.graph = canonical(
            graph.edges(), loops, kappa, graph)
        self.genera = [(sum(self.kappa[v]) - 2 * self.vertex_deg(v) -
                        4 * self.loops[v] + 4) / ZZ(4)
                       for v in self.graph.vertices()]
Ejemplo n.º 8
0
    def __init__(self, strataG):
        self.strataG = strataG
        self.sageG = Graph([list(range(1,
                                       strataG.num_vertices() + 1)), []],
                           multiedges=True,
                           loops=True)
        self.edge_label_to_edge = dict()
        self.vertex_to_marks = {
            v: []
            for v in range(1,
                           self.strataG.num_vertices() + 1)
        }
        self._has_marks = False

        for e in range(1, strataG.num_edges() + 1):
            edge_done = False
            if self.strataG.M[0, e] != 0:  #it is a half edge
                for v in range(1, strataG.num_vertices() + 1):
                    if self.strataG.M[v, e][0] == 1:
                        self.vertex_to_marks[v].append((e, self.strataG.M[0,
                                                                          e]))
                        edge_done = True
                        self._has_marks = True
                        break
            else:  #it is a whole edge

                vert_touching_e = []

                for v in range(1, strataG.num_vertices() + 1):
                    if strataG.M[v, e][0] == 2:
                        #add a loop
                        self.sageG.add_edge((v, v, e))
                        self.edge_label_to_edge[e] = (v, v, e)
                        edge_done = True
                        break
                    if strataG.M[v, e][0] == 1:
                        vert_touching_e.append(v)
                        if len(vert_touching_e) == 2:
                            break

            if edge_done:
                continue
            if len(vert_touching_e) == 2:
                self.sageG.add_edge(
                    (vert_touching_e[0], vert_touching_e[1], e))
                self.edge_label_to_edge[e] = (vert_touching_e[0],
                                              vert_touching_e[1], e)
            else:
                raise Exception("Unexpected here!")
Ejemplo n.º 9
0
    def graph(self):
        r""" Return the weighted graph underlying this resolution graph.

        Output: An undirected, weighted Sage Graph.

        The vertices are labeled by the integers `0,\ldots,n-1`. The weight
        of an edge is the intersection number of the components corresponding
        to the vertices connected by the edge.

        """
        if not hasattr(self, "_graph"):
            M = copy(self._intersection_matrix)
            for i in self.components():
                M[i, i] = 0
            self._graph = Graph(M, format='weighted_adjacency_matrix')
        return self._graph
Ejemplo n.º 10
0
    def graph(self):
        """ Return a graphical representation of self.

        OUTPUT:

        G, vert_dict,

        where G is a graph object and vert_dict is a dictionary associating
        to a vertex of G the corresponding vertex of self.
        """

        G = Graph()
        G.add_vertex(0)
        vert_dict = {}
        create_graph_recursive(self, G, vert_dict, 0)
        return G, vert_dict
Ejemplo n.º 11
0
    def labeled_graph(self):
        r""" Return the labeled graph underlying this resolution graph.

        OUTPUT: An undirected, weighted Sage Graph.

        The vertices are labeled by pairs `(i,-a_i)`, where `-a_i=E_i.E_i`
        is the self intersection number of the component `E_i`. The weight
        of an edge is the intersection number of the components corresponding
        to the vertices connected by the edge.

        """
        G = self.graph()
        a = [self.self_intersection(i) for i in self.components()]
        edges = G.edges()
        new_edges = []
        for i, j, w in edges:
            new_edges.append(((i, a[i]), (j, a[j]), w))
        return Graph(new_edges)
Ejemplo n.º 12
0
    def is_NAC_coloring(self):
        r"""
        Return if the coloring is a NAC-coloring.

        The implementation uses Lemma 2.4 in [GLS2018]_.

        EXAMPLES::

            sage: from flexrilog import NACcoloring, GraphGenerator
            sage: G = GraphGenerator.SmallestFlexibleLamanGraph(); G
            SmallestFlexibleLamanGraph: FlexRiGraph with the vertices [0, 1, 2, 3, 4] and edges [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 4), (3, 4)]
            sage: delta = NACcoloring(G,[[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)], [(2, 4), (3, 4)]], check=False)
            sage: delta.is_NAC_coloring()
            True

        NAC-coloring must be surjective::

            sage: delta = NACcoloring(G,[[], [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 4), (3, 4)]], check=False)
            sage: delta.is_NAC_coloring()
            False

        And it has to satisfy the cycle conditions::

            sage: delta = NACcoloring(G,[[(0, 1), (0, 2)], [(0, 3), (1, 2), (1, 3), (2, 4), (3, 4)]], check=False)
            sage: delta.is_NAC_coloring()
            False

        """
        self._check_edges()

        if len(self._red_edges) == 0 or len(self._blue_edges) == 0:
            return False
        for one_color_subgraph in [self.red_subgraph(), self.blue_subgraph()]:
            for component in one_color_subgraph.connected_components():
                if (len(
                        Graph(self._graph).subgraph(component).edges(
                            labels=False)) - len(
                                one_color_subgraph.subgraph(component).edges(
                                    labels=False))):
                    return False
        return True
    def graph_with_same_edge_lengths(self, motion_types, plot=True):
        r"""
        Return a graph with edge labels corresponding to same edge lengths.

        INPUT:
        
        - `plot` -- if `True` (default), then plot of the graph is returned. 
        
        OUTPUT:
        
        The edge labels of the output graph are same for if the edge lengths
        are same due to `motion_types`. 
        """
        H = {self._edge_ordered(u,v):None for u,v in self._graph.edges(labels=False)}
        self._set_same_lengths(H, motion_types)
        G_labeled = Graph([[u,v,H[(u,v)]] for u,v in H])
        G_labeled._pos = self._graph._pos
        if plot:
            return G_labeled.plot(edge_labels=True, color_by_label=True)
        else:
            return G_labeled
Ejemplo n.º 14
0
    def __init__(self, strataG):
        #make the graph

        G = Graph()

        for v in range(1, strataG.num_vertices()):
            G.add_vertex(v)
            for expon, coef in strataG.M[v, 0].dict().items():
                if expon[0] == 1:
                    genus = coef
                else:
                    pass

        self.decorations = dict()

        dec_items = list(self.decorations.items())
        dec_items.sort(lambda x: x[1])

        parts = []
        prev = None
        dec_list = []

        for a in dec_items:
            if a != prev:
                dec_list.append(a[1])
                parts.append(new_part)
                new_part = [a[0]]
            else:
                new_part.append(a[0])

        self.dec_list = tuple(dec_list)

        self.graph, cert = graphUncan.canonical_labeling(parts).copy(
            immutable=True)

        self.parts = tuple(
            (tuple([cert[i] for i in part_j].sort) for part_j in parts))
Ejemplo n.º 15
0
 def CnSymmetricGridConstruction(cls, G, delta):
     def Cn_symmetric_k_points(n,k, alpha=Integer(1) ):   
         n = Integer(n)
         k = Integer(k) 
         if not mod(k,n) in [Integer(0) ,Integer(1) ]:
             raise ValueError('Only possible if k mod n in {{0,1}}, here {} mod {} = {}.'.format(k,n,mod(k,n)))
         res = {
                 i : vector([RR(cos(RR(Integer(2) *pi*i)/n)),RR(sin(RR(Integer(2) *pi*i)/n))]) for i in range(Integer(0) ,n)
             }
         N = k
         if mod(k,n)==Integer(1) :
             res[N-Integer(1) ] = vector([Integer(0) ,Integer(0) ])
             N = N-Integer(1) 
         for i in range(n,N):
             r = (i-i%n)/n +Integer(1) 
             res[i] = r*res[i%n]
         for i in res:
             res[i] = alpha*vector([res[i][Integer(0) ], res[i][Integer(1) ]])
         return [res[i] for i in sorted(res.keys())]
 
     n = delta.n
     a = Cn_symmetric_k_points(n, len(delta._noninvariant_components['red']))
     a += [vector([Integer(0) ,Integer(0) ]) for _ in range(len(delta._partially_invariant_components['red']))]
     b = Cn_symmetric_k_points(n, len(delta._noninvariant_components['blue']))
     b += [vector([Integer(0) ,Integer(0) ]) for _ in range(len(delta._partially_invariant_components['blue']))]
     ab = [b, a]
     M = GraphMotion.GridConstruction(G, delta,
          check=False, zigzag=ab,
          red_components_ordered=delta._noninvariant_components['red']+delta._partially_invariant_components['red'],
          blue_components_ordered=delta._noninvariant_components['blue']+delta._partially_invariant_components['blue'])
 
     for comp in delta._partially_invariant_components['red']+delta._partially_invariant_components['blue']:
         if len(comp)>Integer(1) :
             M.fix_edge(Graph(G).subgraph(comp).edges(labels=False)[Integer(0) ])
             break
     return M
Ejemplo n.º 16
0
 def XXXrunTest(self):
     g = Graph()
     g.add_edges([(1, 3), (5, 6), (3, 5), (1, 6), (1, 5), (3, 6)])
     l = OrientedRotationSystem.from_graph(g)
     self.assertItemsEqual(l[0].vertices(), [1, 3, 5, 6])
Ejemplo n.º 17
0
    def Q1Graph(old_labeling=False):
        r"""
        Return the graph $Q_1$.

        EXAMPLE::

            sage: from flexrilog import GraphGenerator
            sage: GraphGenerator.Q1Graph()
            Q_1: FlexRiGraph with 7 vertices and 11 edges

        .. PLOT::
            :scale: 70

            from flexrilog import GraphGenerator
            G = GraphGenerator.Q1Graph()
            sphinx_plot(G)
        """
        if old_labeling:
            return FlexRiGraph(
                [(0, 1), (0, 2), (0, 6), (1, 2), (1, 4), (1, 5), (2, 3),
                 (3, 4), (3, 5), (4, 6), (5, 6)],
                pos={
                    5: (0.500, 0.866),
                    4: (-0.500, 0.866),
                    6: (-1.00, 0.000),
                    3: (1.00, 0.000),
                    2: (0.500, -0.866),
                    0: (-0.500, -0.866),
                    1: (0.000, 0.000)
                },
                name='Q_1')
        G = FlexRiGraph(
            [[5, 6], [5, 7], [6, 7], [1, 5], [2, 6], [2, 4], [1, 3], [3, 7],
             [4, 7], [1, 4], [2, 3]],
            pos={
                4: (0.500, 0.866),
                3: (-0.500, 0.866),
                1: (-1.00, 0.000),
                2: (1.00, 0.000),
                6: (0.500, -0.866),
                5: (-0.500, -0.866),
                7: (0.000, 0.000)
            },
            name='Q_1')
        for cls in G.NAC_colorings_isomorphism_classes():
            if len(cls) == 1:
                delta = cls[0]
                if len(delta.blue_edges()) in [4, 7]:
                    delta.set_name('eta')
                else:
                    delta.set_name('zeta')
            else:
                for delta in cls:
                    for edges in [delta.red_edges(), delta.blue_edges()]:
                        if len(cls) == 4 and len(edges) == 7:
                            u, v = [
                                comp
                                for comp in Graph([list(e) for e in edges
                                                   ]).connected_components()
                                if len(comp) == 2
                            ][0]
                            delta.set_name('epsilon' + (
                                str(u) + str(v) if u < v else str(v) + str(u)))
                            break
                        if len(edges) == 3:
                            vertex = edges[0].intersection(
                                edges[1]).intersection(edges[2])[0]
                            name = 'phi' if [
                                w for w in G.neighbors(vertex)
                                if G.degree(w) == 4
                            ] else 'psi'
                            delta.set_name(name + str(vertex))
                            break
                        if len(edges) == 5:
                            u, v = [
                                comp
                                for comp in Graph([list(e) for e in edges
                                                   ]).connected_components()
                                if len(comp) == 2
                            ][0]
                            delta.set_name('gamma' + str(min(u, v)))
                            break
        return G
Ejemplo n.º 18
0
def zeta_function(type,
                  L,
                  objects=None,
                  optimise_basis=False,
                  ncpus=None,
                  alt_ncpus=None,
                  strategy=None,
                  profile=None,
                  verbose=False,
                  optlevel=None,
                  addmany_dispatcher=None,
                  mode=None,
                  debug=None,
                  **kwargs):

    if type not in ['p-adic', 'topological']:
        raise ValueError('Unknown type of zeta function')

    if type == 'p-adic':
        if common.count is None:
            raise RuntimeError(
                'LattE/count is required in order to compute p-adic zeta functions'
            )
        elif __SERIES_BUG:
            raise RuntimeError(
                'power series expansions in this version of Sage cannot be trusted'
            )

    # Multiprocessing.
    if ncpus is None:
        ncpus = Infinity
    from multiprocessing import cpu_count
    common.ncpus = min(ncpus, cpu_count())

    if alt_ncpus is None:
        alt_ncpus = common.ncpus
    common._alt_ncpus = alt_ncpus

    if addmany_dispatcher is None:
        addmany_dispatcher = 'numerator'
    common.addmany_dispatcher = addmany_dispatcher

    common.debug = False if debug is None else debug

    if optlevel is None:
        optlevel = 1
    common.optimisation_level = optlevel

    # Reduction strategies.
    if strategy is None:
        strategy = Strategy.NORMAL

    # Memory profiles.
    if profile is None:
        profile = Profile.NORMAL
    if profile not in [Profile.SAVE_MEMORY, Profile.NORMAL, Profile.SPEED]:
        raise ValueError('Invalid profile')
    if profile == Profile.SAVE_MEMORY:
        common.save_memory = True
        common.plumber = True
    elif profile == Profile.NORMAL:
        common.save_memory = False
        common.plumber = True
    elif profile == Profile.SPEED:
        common.save_memory = False
        common.plumber = False

    if verbose:
        from logging import INFO, DEBUG
        loglevels = [
            (logger, INFO),
            (smurf.logger, INFO),
            (surf.logger, INFO),
            (torus.logger, INFO),
            (abstract.logger, DEBUG),
            (cycrat.logger, INFO),
            (triangulate.logger, INFO),
            (reps.logger, INFO),
            (subobjects.logger, INFO),
            (ask.logger, INFO),
            (cico.logger, DEBUG),
            (addmany.logger, INFO),
        ]
        oldlevels = []

        for m, level in loglevels:
            old = m.getEffectiveLevel()
            oldlevels.append(old)
            m.setLevel(min(old, level))

    if util.is_graph(L):
        if L.has_multiple_edges():
            raise ValueError('parallel edges not supported')

    if (util.is_matrix(L) or
            util.is_graph(L)) and objects not in ['ask', 'cico', 'adj', 'inc']:
        raise ValueError('invalid objects specified for given input')

    elif util.is_polynomial(L):
        # Turn a polynomial into a list of polynomials.
        L = [L]
    elif util.is_string(L):
        L = lookup(L)

    if objects in ['poly', 'igusa']:
        proc = IgusaProcessor(*L)
    elif objects in ['subalgebras', 'ideals']:
        proc = SubobjectZetaProcessor(L, objects, strategy=strategy)
    elif objects == 'reps':
        proc = RepresentationProcessor(L)
    elif objects == 'ask':
        if util.is_graph(L):
            signs = kwargs.get('signs', -1)
            if signs not in [+1, -1]:
                raise ValueError('invalid signs')
            proc = AskProcessor(
                util.graph_to_generic_matrix(
                    L, 'antisymmetric' if signs == -1 else 'symmetric'))
        else:
            proc = AskProcessor(L, mode=mode)
    elif objects == 'cico':
        proc = CicoProcessor(L, **kwargs)
    elif objects == 'adj':
        if not util.is_graph(L) and util.is_matrix(L):
            try:
                L = Graph(L)
            except:
                raise ValueError(
                    'input is not a graph or an adjacency matrix of a graph')
        proc = CicoProcessor(L, **kwargs)
    elif objects == 'inc':
        try:
            n = int(L)
            mu = kwargs.get('mu', {})
            A = cico.incidence_matrix_from_multiplicities(n, mu)
        except:
            A = Matrix(L)

        proc = IncidenceProcessor(A)
    elif objects == 'orbits':
        # NOTE: we don't currently check if L really spans a matrix Lie algebra
        proc = AskProcessor(util.matlist_to_mat(
            util.basis_of_matrix_algebra(L, product='Lie')),
                            mode=mode)
    elif objects == 'cc':
        if not L.is_Lie() and not L.is_nilpotent():
            logger.warning('not a nilpotent Lie algebra')
            # raise ValueError('need a nilpotent Lie algebra in order to enumerate conjugacy classes')
        proc = AskProcessor(util.matlist_to_mat(L._adjoint_representation()),
                            mode=mode)
    else:
        raise ValueError('unknown objects [%s]' % objects)

    if optimise_basis:
        logger.info('Searching for a good basis...')
        proc.optimise()
        logger.info('Picked a basis.')

    if verbose:
        print(proc)

    try:
        if type == 'p-adic':
            return proc.padically_evaluate(shuffle=True)
        elif type == 'topological':
            return proc.topologically_evaluate(shuffle=True)
    finally:
        if verbose:
            for ((m, _), level) in zip(loglevels, oldlevels):
                m.setLevel(level)
        1: [3, 4, 5],
        2: [1],
        3: [2, 4, 5],
        4: [2],
        5: [4, 2],
        6: [7, 8, 9, 10],
        7: [8, 9, 10],
        8: [9, 10],
        10: [11, 12, 13, 14],
        11: [9, 10, 14],
        12: [9, 10, 11, 13],
        13: [9, 10, 11, 12],
        14: [9, 10, 11]
    }
    G = DiGraph(d)
    Gs = Graph()
    Gd = Graph()
    H = Graph()
    find_sym_struct(G, Gs, Gd, H)
    TGs = modular_decomposition(Gs)
    TGd = modular_decomposition(Gd)
    Th = modular_decomposition(H)
    print TGs
    print TGd
    print Th
    # modular decomposition of Gs, Gd
    # factorizing permutation of the graph G is 1,...,14
    nodes = range(1, 15)
    parenthesized_fact_perm(nodes, G)
    print(" ")
    def check_orthogonal_diagonals(self, motion_types,  active_NACs, extra_cycles_orthog_diag=[]):
        r"""
        Check the necessary conditions for orthogonal diagonals.

        TODO:
        
        return orthogonality_graph
        """
        perp_by_NAC = [cycle for delta in active_NACs for cycle in self._orthogonal_diagonals[delta]]
        deltoids = [cycle for cycle, t in motion_types.items() if t in ['e','o']]

        orthogonalLines = []
        for perpCycle in perp_by_NAC + deltoids + extra_cycles_orthog_diag:
            orthogonalLines.append(Set([Set([perpCycle[0],perpCycle[2]]), Set([perpCycle[1],perpCycle[3]])]))

        orthogonalityGraph = Graph(orthogonalLines, format='list_of_edges', multiedges=False)
        n_edges = -1

        while  n_edges != orthogonalityGraph.num_edges():
            n_edges = orthogonalityGraph.num_edges()
            for perp_subgraph in orthogonalityGraph.connected_components_subgraphs():
                isBipartite, partition = perp_subgraph.is_bipartite(certificate=True)
                if isBipartite:
                    graph_0 = Graph([v.list() for v in partition if partition[v]==0])
                    graph_1 = Graph([v.list() for v in partition if partition[v]==1])
                    for comp_0 in graph_0.connected_components():
                        for comp_1 in graph_1.connected_components():
                            for e0 in Subsets(comp_0,2):
                                for e1 in Subsets(comp_1,2):
                                    orthogonalityGraph.add_edge([Set(e0), Set(e1)])
                else:
                    raise exceptions.RuntimeError('A component of the orthogonality graph is not bipartite!')

        self._orthogonality_graph = orthogonalityGraph
        check_again = False
        H = {self._edge_ordered(u,v):None for u,v in self._graph.edges(labels=False)}
        self._set_same_lengths(H, motion_types)

        for c in motion_types:
            if not orthogonalityGraph.has_edge(Set([c[0],c[2]]),Set([c[1],c[3]])):
                continue
            if motion_types[c]=='a':       # inconsistent since antiparallel motion cannot have orthogonal diagonals
                return False
            elif motion_types[c]=='p':     # this cycle must be rhombus
                self._set_two_edge_same_lengths(H, c[0], c[1], c[2], c[3], 0)
                self._set_two_edge_same_lengths(H, c[0], c[1], c[1], c[2], 0)
                self._set_two_edge_same_lengths(H, c[0], c[1], c[0], c[3], 0)
                check_again = True

        for c in motion_types:
            if motion_types[c]=='g':
                labels = [H[self._edge_ordered(c[i-1],c[i])] for i in range(0,4)]
                if (not None in labels
                    and ((len(Set(labels))==2 and labels.count(labels[0])==2)
                        or len(Set(labels))==1)):
                    return False
                if (orthogonalityGraph.has_edge(Set([c[0],c[2]]),Set([c[1],c[3]]))
                    and True in [(H[self._edge_ordered(c[i-1], c[i])]==H[self._edge_ordered(c[i-2], c[i-1])]
                                  and H[self._edge_ordered(c[i-1],c[i])]!= None) for i in range(0,4)]):
                    return False

        if check_again:
            for K23_edges in [Graph(self._graph).subgraph(k23_ver).edges(labels=False) for k23_ver in self._graph.induced_K23s()]:
                if MotionClassifier._same_edge_lengths(H, K23_edges):
                    return False

        return True
Ejemplo n.º 21
0
 def edge_graph(self):
     G = Graph()
     G.add_edges([[v.index for v in e.vertices] for e in self.edges])
     return G
Ejemplo n.º 22
0
    def __init__(self, p_list):
        
        # punc => +-1 ~ +- inf
        # pant_name => idx

        try:
            preparser(False)
        except:
            raise ValueError('Sage preparser issue')

        num_pants = len(p_list)
        punc_map = {}
        edge_ls = []
        #gluing_cnt = 0
        gluing_set = set()
        non_ori_punc_set = set()


        for i in range(len(p_list)):
            pant = p_list[i]
            if len(pant) != 3:
                raise ValueError('One pant should have three punctures')
            for punc in pant:
                if punc == 0:
                    raise ValueError('Punctures should be named as non-zero integer')
                punc_key = abs(punc)
                if punc in punc_map.keys() and punc_map[punc][0]:
                    weight = 1
                    non_ori_punc_set.add(punc)
                else:
                    weight = 0
                if punc_key in punc_map.keys():
                    if punc_map[punc_key][1] != None and punc_map[punc_key][0] != None:
                        raise ValueError("Each puncture can only be glued once")
                    #gluing_cnt += 1
                    gluing_set.add(punc_key)
                    if punc < 0:
                        punc_map[punc_key][1] = i
                    else:
                        punc_map[punc_key][0] = i
                    edge_ls.append((punc_map[punc_key][0], punc_map[punc_key][1], weight))
                    gluing_set.add(punc_key)
                else:
                    if punc < 0:
                        punc_map[punc_key] = [None, i]
                    else:
                        punc_map[punc_key] = [i, None]

        # check for connectedness
        #print edge_ls
        g = Graph(edge_ls)

        print g

        if not g.is_connected():
            raise ValueError('Invalid input. Surface should be connect')

        # orientation
        orientable = True ### DEBUG
        #orientable = PantsDecomposition._is_orientable(g) ### DEBUG

        euler_char = -1*num_pants 
        num_puncture = num_pants*3 - 2*len(gluing_set)
        super(PantsDecomposition,self).__init__(euler_char = euler_char, num_punctures = num_puncture, is_orientable = orientable)
        #print self.__repr__()
        self._p_list = p_list
        self._p_map = punc_map
        self._gluing_set = gluing_set
        self._non_ori_punc_set = non_ori_punc_set
Ejemplo n.º 23
0
    def height_function(self, vertex_edge_collisions, extra_layers=0, edge_edge_collisions=[]):
        r"""
        Return a height function of edges if possible for given vertex-edge collisions.

        WARNING:
        
        Costly, since it runs through all edge-colorings.
        """
        def e2s(e):
            return Set(e)
        for v in vertex_edge_collisions:
            vertex_edge_collisions[v] = Set([e2s(e) for e in vertex_edge_collisions[v]])
        collision_graph = Graph([[e2s(e) for e in self._graph.edges(labels=False)],[]],format='vertices_and_edges')
        for u in self._graph.vertices():
            collision_graph.add_edges([[e2s([u,v]),e2s([u,w]),''] for v,w in Subsets(self._graph.neighbors(u),2)])
        for e in collision_graph.vertices():
            for v in vertex_edge_collisions:
                if v in e:
                    for f in vertex_edge_collisions[v]:
                        collision_graph.add_edge([e2s(f), e2s(e), 'col'])
        for e, f in edge_edge_collisions:
            collision_graph.add_edge([e2s(f), e2s(e), 'e-e_col'])
        from sage.graphs.graph_coloring import all_graph_colorings
        optimal = False
        chrom_number = collision_graph.chromatic_number()
        for j in range(0, extra_layers + 1):
            i = 1
            res = []
            num_layers = chrom_number + j
            min_s = len(self._graph.vertices())*num_layers
            for col in all_graph_colorings(collision_graph,num_layers):
                if len(Set(col.keys()))<num_layers:
                    continue
                layers = {}
                for h in col:
                    layers[h] = [u for e in col[h] for u in e]
                col_free = True
                A = []
                for v in vertex_edge_collisions:
                    A_min_v = min([h for h in layers if v in layers[h]])
                    A_max_v = max([h for h in layers if v in layers[h]])
                    A.append([A_min_v, A_max_v])
                    for h in range(A_min_v+1,A_max_v):
                        if v not in layers[h]:
                            if len(Set(col[h]).intersection(vertex_edge_collisions[v]))>0:
                                col_free = False
                                break
                    if not col_free:
                        break
                if col_free:
                    s = 0
                    for v in self._graph.vertices():
                        A_min_v = min([h for h in layers if v in layers[h]])
                        A_max_v = max([h for h in layers if v in layers[h]])
                        s += A_max_v - A_min_v
                    if s<min_s:
                        min_s = s
                        res.append((col, s, A))
                        i += 1
                        if s==2*len(self._graph.edges())-len(self._graph.vertices()):
                            optimal = True
                            break
            if optimal:
                break
        if not res:
            return None
        vertex_coloring = min(res, key = lambda t: t[1])[0]
        h = {}
        for layer in  vertex_coloring:
            for e in vertex_coloring[layer]:
                h[e] = layer
        return h
Ejemplo n.º 24
0
 def red_subgraph(self):
     return Graph(
         [self._graph.vertices(), [list(e) for e in self._red_edges]],
         format='vertices_and_edges')
    def __init__(self, graph, four_cycles=[], separator='', edges_ordered=[]):
        if not (isinstance(graph, FlexRiGraph) or 'FlexRiGraph' in str(type(graph))):
            raise exceptions.TypeError('The graph must be of the type FlexRiGraph.')
        self._graph = graph

        if four_cycles == []:
            self._four_cycles = self._graph.four_cycles(only_with_NAC=True) 
        else:
            self._four_cycles = four_cycles

        if not self._graph.are_NAC_colorings_named():
            self._graph.set_NAC_colorings_names()

#        -----Polynomial Ring for leading coefficients-----
        ws = []
        zs = []
        lambdas = []
        ws_latex = []
        zs_latex = []
        lambdas_latex = []
        
        if edges_ordered==[]:
            edges_ordered = self._graph.edges(labels=False)
        else:
            if (Set([self._edge2str(e) for e in edges_ordered]) !=
                Set([self._edge2str(e) for e in self._graph.edges(labels=False)])):
                raise ValueError('The provided ordered edges do not match the edges of the graph.')

        for e in edges_ordered:
            ws.append('w' + self._edge2str(e))
            zs.append('z' + self._edge2str(e))
            lambdas.append('lambda' + self._edge2str(e))
            ws_latex.append('w_{' + self._edge2str(e).replace('_', separator) + '}')
            zs_latex.append('z_{' + self._edge2str(e).replace('_', separator) + '}')
            lambdas_latex.append('\\lambda_{' + self._edge2str(e).replace('_', separator) + '}')

        self._ringLC = PolynomialRing(QQ, names=lambdas+ws+zs) #, order='lex')
        self._ringLC._latex_names = lambdas_latex + ws_latex + zs_latex
        self._ringLC_gens = self._ringLC.gens_dict()

        self._ring_lambdas = PolynomialRing(QQ, names=lambdas + ['u'])
        self._ring_lambdas._latex_names = lambdas_latex + ['u']
        self._ring_lambdas_gens = self._ring_lambdas.gens_dict()
        self.aux_var = self._ring_lambdas_gens['u']
        
        xs = []
        ys = []
        xs_latex = []
        ys_latex = []
        for v in self._graph.vertices():
            xs.append('x' + str(v))
            ys.append('y' + str(v))
            xs_latex.append('x_{' + str(v) + '}')
            ys_latex.append('y_{' + str(v) + '}')
            
        self._ring_coordinates = PolynomialRing(QQ, names=lambdas+xs+ys)
        self._ring_coordinates._latex_names = lambdas_latex + xs_latex + ys_latex
        self._ring_coordinates_gens = self._ring_coordinates.gens_dict()
        
        
#        ----Ramification-----
#         if len(self._graph.NAC_colorings()) > 1: 
        self._ring_ramification = PolynomialRing(QQ,
                                                 [col.name() for col in self._graph.NAC_colorings()],
                                                 len(self._graph.NAC_colorings()))
#         else:
#             self._ring_ramification = PolynomialRing(QQ, self._graph.NAC_colorings()[0].name())
        self._ring_ramification_gens = self._ring_ramification.gens_dict()
        self._restriction_NAC_types = self.NAC_coloring_restrictions()

#        -----Graph of 4-cycles-----
        self._four_cycle_graph = Graph([self._four_cycles,[]], format='vertices_and_edges')

        for c1, c2 in Subsets(self._four_cycle_graph.vertices(), 2):
            intersection = self.cycle_edges(c1, sets=True).intersection(self.cycle_edges(c2, sets=True))
            if len(intersection)>=2 and len(intersection[0].intersection(intersection[1]))==1:
                common_vert = intersection[0].intersection(intersection[1])[0]
                self._four_cycle_graph.add_edge(c1, c2, common_vert)

#        -----Cycle with orthogonal diagonals due to NAC-----
        self._orthogonal_diagonals = {
                delta.name(): [cycle for cycle in self._four_cycle_graph if delta.cycle_has_orthogonal_diagonals(cycle)]
                for delta in self._graph.NAC_colorings()}
    def consistent_motion_types(self):#, cycles=[]):
        r"""
        Return the list of motion types consistent with 4-cycles.
        """
#         if cycles==[]:
        cycles = self.four_cycles_ordered()

        k23s = [Graph(self._graph).subgraph(k23_ver).edges(labels=False) for k23_ver in self._graph.induced_K23s()]

        aa_pp = [('a', 'a'), ('p', 'p')]
        ao = [('a','o'), ('o','a')]
        ae = [('a','e'), ('e','a')]
        oe = [('o', 'e'), ('e', 'o')]
        oo_ee = [('e','e'), ('o','o')]

        H = {self._edge_ordered(u,v):None for u,v in self._graph.edges(labels=False)}
        types_prev=[[{}, []]]
        
        self._num_tested_combinations = 0

        for i, new_cycle in enumerate(cycles):
            types_ext = []
            new_cycle_neighbors = [[c2,
                                    new_cycle.index(self._four_cycle_graph.edge_label(new_cycle, c2)),
                                    c2.index(self._four_cycle_graph.edge_label(new_cycle, c2)),
                                   ] for c2 in self._four_cycle_graph.neighbors(new_cycle) if c2 in cycles[:i]]
            for types_original, ramification_eqs_prev in types_prev:
                for type_new_cycle in ['g','a','p','o','e']:
                    self._num_tested_combinations +=1
                    types = deepcopy(types_original)
                    types[tuple(new_cycle)] = type_new_cycle
    #                 H = deepcopy(orig_graph)
                    inconsistent = False

                    for c2, new_index, c2_index in new_cycle_neighbors:
                        type_pair = (types[new_cycle], types[c2])
                        if (type_pair in aa_pp
                                or (type_pair in oe and new_index%2 == c2_index%2)
                                or (type_pair in oo_ee and new_index%2 != c2_index%2)):
                            inconsistent = True
                            break
                        if type_pair in ao:
                            ind_o = type_pair.index('o')
                            if [new_index, c2_index][ind_o] % 2 == 1:
                            # odd deltoid (1,2,3,4) is consistent with 'a' if the common vertex is odd,
                            # but Python lists are indexed from 0
                                inconsistent = True
                                break
                        if type_pair in ae:
                            ind_e = type_pair.index('e')
                            if [new_index, c2_index][ind_e] % 2 == 0:
                                inconsistent = True
                                break
                    if inconsistent:
                        continue

                    self._set_same_lengths(H, types)
                    for c in types:
                        if types[c]=='g':
                            labels = [H[self._edge_ordered(c[i-1],c[i])] for i in range(0,4)]
                            if (not None in labels
                                and ((len(Set(labels))==2 and labels.count(labels[0])==2)
                                    or len(Set(labels))==1)):
                                inconsistent = True
                                break
                    if inconsistent:
                        continue
                    for K23_edges in k23s:
                        if MotionClassifier._same_edge_lengths(H, K23_edges):
                            inconsistent = True
                            break
                    if inconsistent:
                        continue

                    ramification_eqs = ramification_eqs_prev + self.ramification_formula(new_cycle, type_new_cycle)
                    zero_variables, ramification_eqs = self.consequences_of_nonnegative_solution_assumption(ramification_eqs)
                    for cycle in types:
                        if inconsistent:
                            break
                        for t in self.motion_types2NAC_types(types[cycle]):
                            has_necessary_NAC_type = False
                            for delta in self._restriction_NAC_types[cycle][t]:
                                if not self.mu(delta) in zero_variables:
                                    has_necessary_NAC_type = True
                                    break
                            if not has_necessary_NAC_type:
                                inconsistent = True
                                break
                    if inconsistent:
                        continue

                    types_ext.append([types, ramification_eqs])

            types_prev=types_ext

        return [t for t, _ in types_prev]
Ejemplo n.º 27
0
        new_x, new_y = pt
        if new_x < curr_x - 1:
            not_in_inertia.update([(i, curr_y)
                                   for i in range(new_x + 1, curr_x)])
            not_in_inertia.update([(curr_y, i)
                                   for i in range(new_x + 1, curr_x)])
        curr_x, curr_y = new_x, new_y
    return not_in_inertia


def Zplus(G):
    return Z_pythonBitset(G, q=0)


from sage.all import Graph, graphs
G = Graph()
G.add_edges([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 1], [1, 4], [2, 5],
             [3, 6], [7, 1], [7, 2], [7, 3]])

G2 = graphs.CompleteGraph(4)
G2.subdivide_edges(G2.edges(), 1)

from sage.all import points


def plot_inertia_lower_bound(g):
    return points(list(Zq_inertia_lower_bound(g)),
                  pointsize=40,
                  gridlines=True,
                  ticks=[range(g.order()), range(g.order())],
                  aspect_ratio=1)
Ejemplo n.º 28
0
 def runTest(self):
     g = Graph(multiedges=True, loops=True)
     g.add_edge(1, 1)
     p = PebbleGame(g.vertices(), 2, 2)
     self.assertFalse(p.run(g))