Esempio n. 1
0
def find_mincycle(graph):
    # size = graph.size()
    # mincycle = []
    # mincycle.append(np.inf)
    # matr = graph.to_matrix()
    # dist = graph.to_matrix()
    # for i in range(size):
    #     for j in range(size):
    #         if matr[i][j] == 0:
    #             matr[i][j] = dist[i][j] = np.inf
    # for k in range(size):
    #     for i in range(k):
    #         for j in range(i):
    #             mincycle[0] = min(mincycle[0], dist[i][j] + matr[j][k] + matr[k][i])
    #
    #     for i in range(size):
    #         for j in range(i):
    #             temp = dist[i][k] + dist[k][j]
    #             if temp < dist[i][j]:
    #                 dist[i][j] = dist[j][i] = temp

    # if graph.oriented:
    #     mincycle -= 1
    g = nx.Graph()
    nx.Graph()
    size = graph.size()
    matr = graph.to_matrix()
    for i in range(1, size + 1):
        g.add_node(i)
        for j in range(1, size + 1):
            if matr[i - 1][j - 1] is not 0:
                g.add_edge(i, j)
    return nx.minimum_cycle_basis(g)[0]
Esempio n. 2
0
def task_b(G):
    gr = nx.Graph(G)
    print("|E| = " + str(gr.number_of_edges()))
    print("|V| = " + str(gr.number_of_nodes()))
    min = 100
    max = -100
    gr = maximum_connected_component(gr)
    for i in gr.nodes:
        if gr.degree[i] < min:
            min = gr.degree[i]
        if gr.degree[i] > max:
            max = gr.degree[i]
    print("𝛿(G) = " + str(min))
    print("Δ(G) = " + str(max))
    print("rad(G) = " + str(nx.radius(gr)))
    print("diam(G) = " + str(nx.diameter(gr)))
    print("girth(G) = " + str(len(nx.minimum_cycle_basis(G)[0])) + ", " + str(nx.minimum_cycle_basis(G)[0]))
    print("center(G) = " + str(nx.center(gr)))
    print("𝜅(G) = " + str(nx.node_connectivity(gr)))
    print("𝜆(G) = " + str(nx.edge_connectivity(gr)))
Esempio n. 3
0
def get_cycle_descriptors(graph):
    """Get descriptors for the cycles in a graph"""
    cycles = nx.minimum_cycle_basis(graph)

    lengths = count_sublist_lengths(cycles)

    memberships = get_cycle_memberships(graph, cycles, lengths)

    return {
        "cycles": cycles,
        "lengths": lengths,
        "memberships": memberships,
    }
Esempio n. 4
0
    def __init__(self, graph):
        """
        this is the schema for molecule with fused rings

        :param graph:
        """
        super().__init__(graph)
        self.rings = nx.minimum_cycle_basis(self.graph)  # technically sssr
        self.rings = sorted(self.rings, key=lambda x: len(x))
        self.nrings = len(self.rings)
        if self.nrings < 1:
            warnings.warn('you are init a MolGraph with no ring!')

        self.ring_graph = nx.Graph()
        for ij in itertools.combinations(range(self.nrings), 2):
            i, j = ij
            ri = self.rings[i]
            rj = self.rings[j]
            shared_nodes = set(ri) & set(rj)
            ni_connected_to_rj = [
                ni for ni in ri
                if len(set(self.graph.neighbors(ni))
                       & set(rj)) == 1 and ni not in rj
            ]
            # we set len(shared_nodes) > 0 to avoid breaking spiro bicycle
            if len(shared_nodes) > 0 or len(ni_connected_to_rj) > 0:
                self.ring_graph.add_edge(i,
                                         j,
                                         nshare=len(shared_nodes),
                                         nconnect=len(ni_connected_to_rj))

        self.connected_rings = self.get_rings(
            'nconnect', 1)  # for rubrene len(self.connected_rings[0]) == 8
        self.fused_rings = self.get_rings(
            'nshare', 2)  # for rubrene len(self.fused_rings[0]) == 4
        # notice if two rings share2 then they must connect1
        try:
            self.lgcr = self.connected_rings[0]
        except IndexError:
            try:
                self.lgcr = [self.rings[0]]
            except IndexError:
                raise GraphError('no rings in the MolGraph!')

        try:
            self.lgfr = self.fused_rings[0]
        except IndexError:
            try:
                self.lgfr = [self.rings[0]]
            except IndexError:
                raise GraphError('no rings in the MolGraph!')
    def test_cycle_length(self):
        g = HypergraphGrammar.load('hyper_grammar.pickle')
        for r in g.rules:
            if r is not None:
                g = r.to_nx()
                cycles = nx.minimum_cycle_basis(g)
                if len(cycles) > 0:
                    maxlen = max([len(c) for c in cycles])
                    if maxlen > 7:
                        print(maxlen)

                cc = nx.number_connected_components(g)
                if cc > 1:
                    print(cc)
Esempio n. 6
0
def solve_b(G):
    Graph = nx.Graph(G)
    print("|V| = " + str(len(Graph.nodes)))
    print("|E| = " + str(len(Graph.edges)))
    Graph = biggest_component(G)
    max_degree = -1
    min_degree = 1000
    for ISO in Graph.nodes:
        if Graph.degree[ISO] > max_degree:
            max_degree = Graph.degree[ISO]
        if Graph.degree[ISO] < min_degree:
            min_degree = Graph.degree[ISO]
    print("Min deg = " + str(min_degree))
    print("Max deg = " + str(max_degree))

    print("Radius = " + str(nx.radius(Graph)))
    print("Diameter = " + str(nx.diameter(Graph)))
    print("Girth = " + str(len(nx.minimum_cycle_basis(G)[0])) + ". Example: " +
          str(nx.minimum_cycle_basis(G)[0]))
    print("Center: " + str(nx.center(Graph)))

    print("Edge connectivity = " + str(nx.edge_connectivity(Graph)))
    print("Node connectivity = " + str(nx.node_connectivity(Graph)))
Esempio n. 7
0
    def _find_bonds_and_rings(self, qm_out):
        """Setup networkx graph """
        self.graph = nx.Graph()
        for i_idx, i_elem in enumerate(self.elements):
            self.graph.add_node(i_idx,
                                elem=i_elem,
                                n_bonds=qm_out.n_bonds[i_idx],
                                q=qm_out.point_charges[i_idx],
                                lone_e=qm_out.lone_e[i_idx],
                                coords=self.coords[i_idx])
            # add bonds
            for j_idx, j_elem in enumerate(self.elements):
                b_order = qm_out.b_orders[i_idx, j_idx]
                if b_order > 0.3:
                    id1, id2 = sorted([i_elem, j_elem])
                    b_order_half_rounded = np.round(b_order * 2) / 2
                    vec = self.coords[i_idx] - self.coords[j_idx]
                    dist = np.sqrt((vec**2).sum())
                    self.graph.add_edge(
                        i_idx,
                        j_idx,
                        vector=vec,
                        length=dist,
                        order=b_order,
                        type=f'{id1}({b_order_half_rounded}){id2}',
                        n_rings=0)
            if qm_out.n_bonds[i_idx] > ELE_MAXB[i_elem]:
                print(
                    f"WARNING: Atom {i_idx+1} ({ATOM_SYM[i_elem]}) has too many",
                    " ({qm_out.n_bonds[i_idx]}) bonds?")
            elif qm_out.n_bonds[i_idx] == 0:
                print(
                    f"WARNING: Atom {i_idx+1} ({ATOM_SYM[i_elem]}) has no bonds"
                )
        # add rings
        self.rings = nx.minimum_cycle_basis(self.graph)
        self.rings3 = [r for r in self.rings if len(r) == 3]

        for i in range(self.n_atoms):
            self.node(i)['n_ring'] = sum([i in ring for ring in self.rings])
        #
        for atoms in self.graph.edges:
            ring_members = [
                set(atoms).issubset(set(ring)) for ring in self.rings
            ]
            self.edge(*atoms)['n_rings'] = sum(ring_members)
            self.edge(*atoms)['in_ring'] = any(ring_members)
            self.edge(*atoms)['in_ring3'] = any(
                set(atoms).issubset(set(ring)) for ring in self.rings3)
Esempio n. 8
0
    def __init__(self, graph: nx.Graph, joints: dict, partition_scheme: str):
        """
        fragment is a BasicGraph with joints

        I feel it's not necessary to add parent BasicGraph as an attribute, but I maybe wrong

        :param graph:
        :param joints: a dict, keys are nodes in the subgraph that have parent graph edges not in this subgraph
        """
        super().__init__(graph)
        self.partition_scheme = partition_scheme
        self.graph = graph
        self.joints = joints
        self.rings = nx.minimum_cycle_basis(self.graph)  # technically sssr
        self.rings = sorted(self.rings, key=lambda x: len(x))
Esempio n. 9
0
def getCycles(graph, grid):
    cycles = nx.minimum_cycle_basis(graph)
    finalCycles = [cycles[0]]
    append = True
    for i in range(len(cycles)):
        append = True
        for j in range(len(finalCycles)):
            if (intersection(cycles[i], finalCycles[j]) != []):
                append = False
        if (append and cycles[i] not in finalCycles):
            finalCycles.append(cycles[i])
    finalCycles = [
        rearangeCycle(finalCycles[i], grid) for i in range(len(finalCycles))
    ]
    return finalCycles
Esempio n. 10
0
    def get_cycle_basis(self, minimum=True):
        """
        A wrapper for networkx cycle basis finder
        :param minimum: True (default), if minimum cycle basis is sought
        :param nxG: networkX graph
        :return: list of edge lists, such as [[(0, 1), (1, 2), (2, 3)]...]
                 or []
                 and the number of self-loops discarded in the conversion from multi-graph to graph
        """
        if self.multigraph:
            G, N = self.convert_multigraph_to_graph()
        else:
            G = self.nxGraph
            N = 0
        # A list of cycle lists. Each cycle list is a list of nodes which forms a cycle (loop) in G.
        # The nodes are not necessarily returned in a order by which they appear in the cycle...
        if minimum:
            basis = nx.minimum_cycle_basis(G)
        else:
            basis = nx.cycle_basis(G)

        # convert into edge lists...
        edge_lists = []
        for node_list in basis:
            edges = []
            start = node_list[0]
            p = start
            node_list.remove(p)
            while node_list:
                p_neighbors = {nbor for a, nbor in G.edges(p)}
                for q in p_neighbors:
                    if q in node_list:
                        # edge between p and q
                        edges.append((p, q))
                        node_list.remove(q)
                        p = q
                        break
            edges.append((p, start))  # return to origin
            edge_lists.append(edges)
        return edge_lists, N
Esempio n. 11
0
    def cycles(self, calculate_every=1, exclude_zeros=False):
        cycles_number = []
        cycles_mean_length = []

        for reactions in list(self.reactions.values()):
            print('.', end='')
            self._reset_graph()
            cycles_number.append([])
            cycles_mean_length.append([])
            i = 0
            for reaction in reactions:
                node1 = (reaction[0], reaction[2])
                node2 = (reaction[1], reaction[3])
                self.G.add_edge(node1, node2)
                if i % calculate_every != 0:
                    i += 1
                    continue
                i += 1
                cycles = nx.minimum_cycle_basis(self.G)
                number = len(cycles)
                mean_length = 0
                if number > 0:
                    mean_length = sum(len(x) for x in cycles) / float(number)
                cycles_number[-1].append(number)
                cycles_mean_length[-1].append(mean_length)
        print('')

        self.cycles_number = np.array(cycles_number)
        self.cycles_mean_length = np.array(cycles_mean_length)

        # mean_number_ave = np.mean(number_ave_data, axis=0)
        # mean_weight_ave = np.mean(weight_ave_data, axis=0)

        mean_cycles_number = self._mean(cycles_number)
        mean_cycles_mean_length = self._mean(cycles_mean_length,
                                             exclude_zeros=True)

        self.topology_data["cycles_number"] = mean_cycles_number
        self.topology_data["cycles_mean_length"] = mean_cycles_mean_length
def compute_bonds(structures, molecules):
    out_name = []
    out_a0 = []
    out_a1 = []
    out_n = []
    out_dist = []
    out_error = []
    out_type = []
    cycle_name = []
    cycle_index = []
    cycle_seq = []
    cycle_atom_index = []
    charge_name = []
    charge_atom_index = []
    charge_value = []
    for imol, name in tqdm(list(enumerate(molecules))):
        molecule = structures.loc[name]
        error = 0
        atoms = molecule.atom.values
        atoms_idx = molecule.atom_index.values

        n_avail = np.asarray([VALENCE_STD[a] for a in atoms])
        n_charge = np.zeros(len(atoms), dtype=np.float16)
        isleaf = np.zeros(
            len(atoms),
            dtype=np.bool)  # is the atom in the leafs of connection tree?
        coords = molecule[['x', 'y', 'z']].values
        kdt = KDTree(
            coords)  # use an optimized structure for closest match query
        nbond = {}
        connected = {i: {} for i in atoms_idx}

        # select Hydrogen first to avoid butadyne-like ordering failures (molecule_name=dsgdb9nsd_000023)
        ordered_atoms_index = list(atoms_idx)
        ordered_atoms_index.sort(key=lambda i: BOND_ORDER[atoms[i]])
        ordered_atoms_index = np.asarray(ordered_atoms_index)

        # STEP 1: 1-bond connect each atom with closest match
        #         only one bond for each atom pair is done in step 1
        for a0 in ordered_atoms_index:
            search_bonds(kdt,
                         n_avail,
                         nbond,
                         connected,
                         isleaf,
                         coords,
                         atoms,
                         atoms_idx,
                         a0,
                         connect_once=True,
                         VALENCE=VALENCE_STD)

        # STEP 2: greedy connect n-bonds, progressing from leafs of connection tree
        while (((n_avail > 0).sum() > 0) and isleaf).sum() > 0:
            progress = False
            for a0 in ordered_atoms_index:
                #print("leaF/Trunk & avail: " + ", ".join([f"{i}:{atoms[i]}={leaflabel[leaf[i]]}{n_avail[i]}"
                #                                          for i in ordered_atoms_index]))
                if (n_avail[a0] > 0) and isleaf[a0]:
                    for a1 in connected[a0]:
                        if (n_avail[a0] > 0) and (n_avail[a1] > 0):
                            add_bond(n_avail, nbond, a0, a1)
                            progress = True
                            if (n_avail[a0] == 0) or (n_avail[a1] == 0):
                                isleaf[a0] = 1
                                isleaf[a1] = 1
            if not progress:
                break

        # gather remaining multiple bonds
        if n_avail.sum() > 0:
            for key in nbond.keys():
                a0, a1 = key
                while (n_avail[a0] > 0) and (n_avail[a1] > 0):
                    add_bond(n_avail, nbond, a0, a1)

        # STEP 3: search for known ionized radicals
        if n_avail.sum() > 0:
            for (i, a) in zip(atoms_idx, atoms):
                if a == 'N':
                    # NH3+
                    bonded_str, bonded_idx = get_bonded_atoms(atoms, nbond, i)
                    if (bonded_str == "HHH") and (n_avail[i] == 0):
                        # add a valence unit and search a dangling bond nearby
                        n_avail[i] += 1
                        n_charge[i] += 1
                        if search_bonds(kdt,
                                        n_avail,
                                        nbond,
                                        connected,
                                        isleaf,
                                        coords,
                                        atoms,
                                        atoms_idx,
                                        i,
                                        connect_once=False,
                                        VALENCE=VALENCE_MAX):
                            print(f"++ NH3+ found for {name} atom_index={i}")
                        else:
                            print(
                                f"** NH3+ bonding failure for {name} atom_index={i}"
                            )

                elif (a == 'O') and (n_avail[i] == 1):
                    # COO-
                    bonded_str, bonded_idx = get_bonded_atoms(atoms, nbond, i)
                    if bonded_str == "C":
                        C_i = bonded_idx[0]
                        C_bonded_str, C_bonded_idx = get_bonded_atoms(
                            atoms, nbond, C_i)
                        if ("OO" in C_bonded_str):
                            has_2CO = False
                            #print (C_bonded_str, C_bonded_idx, nbond, name)
                            for a1, i1 in zip(C_bonded_str, C_bonded_idx):
                                key = tuple(sorted((C_i, i1)))
                                if (a1 == 'O') and (nbond[key][0] == 2):
                                    has_2CO = True
                            if (len(C_bonded_idx) == 3) and has_2CO:
                                # found carboxyle!
                                n_avail[i] -= 1
                                print(
                                    f"**  COO- found for {name} C_atom_index={C_i}"
                                )
                                for a1, i1 in zip(C_bonded_str, C_bonded_idx):
                                    if a1 == 'O':
                                        n_charge[i1] = -0.5
                                        key = tuple(sorted((C_i, i1)))
                                        nbond[key][0] = 1.5

        # detect cycles : algo complexity in O(m^2 * n)
        #    paper : https://link.springer.com/article/10.1007/s00453-007-9064-z
        #    nx doc: https://networkx.github.io/documentation/latest/reference/algorithms/generated/networkx.algorithms.cycles.minimum_cycle_basis.html
        graph = nx.Graph([bond for bond in nbond.keys()])
        unordered_cycles = nx.minimum_cycle_basis(graph)

        # index atoms by their sequential order in the cycle: i.e follow bonds
        # Note: this code can be written in a much cleaner way!
        if len(unordered_cycles) > 0:
            for icycle, c in enumerate(unordered_cycles):
                available = {i: 1 for i in c}
                a0 = c[0]
                cycle = [a0]
                del (available[a0])
                for index in range(1, len(c)):
                    # get atoms bonded to a0
                    bonded = [b for b in nbond.keys() if a0 in b]
                    bonded = list(
                        map(lambda b: b[0] if b[1] == a0 else b[1], bonded))

                    # get next atom and remove it from cycle
                    assert (len(bonded) > 0)
                    found = False
                    for a1 in bonded:
                        if (a1 in bonded) and (a1 in available):
                            cycle.append(a1)
                            del (available[a1])
                            a0 = a1
                            found = True
                            break
                    assert (found)

                # and add cycles found to the cycle dataframe lists
                cycle_name.extend([name] * len(cycle))
                cycle_index.extend([icycle] * len(cycle))
                cycle_seq.extend(np.arange(len(cycle)))
                cycle_atom_index.extend(cycle)

        # display info on failed molecules
        if n_avail.sum() > 0:
            error = 1
            print(
                f"   Remaining bondings={n_avail.sum()} for molecule_name={name}, atoms: "
                + ", ".join(
                    [f"{i}:{atoms[i]}" for i in atoms_idx if n_avail[i] > 0]))

        # inputs for DataFrame bonds
        for (a0, a1), (n, dist) in nbond.items():
            # append to python lists which is 7x faster than toa pd.DataFrame
            out_name.append(name)
            out_a0.append(a0)
            out_a1.append(a1)
            out_n.append(n)
            out_dist.append(dist)
            out_error.append(error)
            out_type.append(f"{n:0.1f}" +
                            "".join(sorted(f"{atoms[a0]}{atoms[a1]}")))

        # inputs for DataFrame charges
        charge_name.extend([name] * len(atoms))
        charge_atom_index.extend(molecule.atom_index.values)
        charge_value.extend(n_charge)

    bonds = pd.DataFrame({
        'molecule_name': out_name,
        'atom_index_0': out_a0,
        'atom_index_1': out_a1,
        'nbond': out_n,
        'L2dist': out_dist,
        'error': out_error,
        'bond_type': out_type
    })
    charges = pd.DataFrame({
        'molecule_name': charge_name,
        'atom_index': charge_atom_index,
        'charge': charge_value
    })
    cycles = pd.DataFrame({
        'molecule_name': cycle_name,
        'cycle_index': cycle_index,
        'cycle_seq': cycle_seq,
        'atom_index': cycle_atom_index
    })
    return bonds, charges, cycles
Esempio n. 13
0
 def calculate(graph):
     if nx.is_connected(graph):
         return len(nx.minimum_cycle_basis(graph))
     else:
         return 10**10
Esempio n. 14
0
    def make_graph(self):
        """Generate edge information to create a graph

             Using the intersection of each face, create edge information that makes up the face

             Args:
                 self.new_line_info: List of aligned floor points
                 self.new_line_info2: List of aligned intersections points
             Returns:
                 new_edges: List of edge information
                 pointcloud_i: Index information of PointCloud including each surface
         """
        ceiling, floor, wall = [], [], []
        self.make_line_info()
        if len(self.index_value) > 0:
            G = nx.Graph()
            # Making the graph using index_value list
            G.add_edges_from(self.index_value)
            # Finding the minimum cycle from the Graph
            cycles_list = nx.minimum_cycle_basis(G)

            if len(cycles_list) >= 1:
                delete_edges = []
                temp_delete = []

                # Finding the overlapping edges between generated cycles

                for each_cycle in cycles_list:
                    # First making original edge information the each cycles node and self.index_value
                    # eahc_cycle is not sorted
                    for each_cycle_i in range(len(each_cycle) - 1):
                        for each_edge in self.index_value:
                            if each_cycle[each_cycle_i] in each_edge:
                                index_node = each_edge.index(
                                    each_cycle[each_cycle_i])
                                for each_cycle_j in range(
                                        each_cycle_i + 1, len(each_cycle)):
                                    if each_cycle[each_cycle_j] in each_edge:
                                        if index_node == 0:
                                            temp_edge = [
                                                each_cycle[each_cycle_i],
                                                each_cycle[each_cycle_j]
                                            ]
                                        else:
                                            temp_edge = [
                                                each_cycle[each_cycle_j],
                                                each_cycle[each_cycle_i]
                                            ]

                                        temp_delete.append(temp_edge)

                delete_dup_edges = list(set(map(tuple, temp_delete)))

                if len(delete_dup_edges) > 0:
                    for delete_edge in delete_dup_edges:
                        # Second checking the duplicate edges
                        if temp_delete.count([delete_edge[0], delete_edge[1]
                                              ]) > 1:
                            delete_edges.append(
                                [delete_edge[0], delete_edge[1]])

                # After removing the duplicate edges, finding all cycles included from the Graph
                if len(delete_edges) > 0:
                    G.remove_edges_from(delete_edges)
                    new_cycles = nx.minimum_cycle_basis(G)
                    ceiling, floor, wall = self.get_newGraph(G, new_cycles)
                else:
                    ceiling, floor, wall = self.get_newGraph(G, cycles_list)
        return ceiling, floor, wall
				g=np.ndarray.tolist(gnp)
				
				tr1=numTriangles(g)
				# print(tr1)
				len_trlist=len(tr1)
				if(len_trlist==0):
					print("triangles removed from graph")
				else:
					continue

			if(nx.is_connected(graph)==False):
				print("removing triangles causes disconnection!")
				continue
			
			# cycl_list=nx.cycle_basis(graph, 0)
			cycl_list=nx.minimum_cycle_basis(graph)

			if(len(cycl_list)):
				# girthObtained=len(min(cycl_list, key=len))
				girthObtained=len(cycl_list[0])
				girthCycle=cycl_list[0]
				# girthCycle=min(cycl_list, key=len)
				print("girth = "+str(girthObtained))
			else:
				print("no cycles")
				continue

			if (girthObtained!=girth):
				print("girth doesn't match")
				continue
			else:
Esempio n. 16
0
def __create_loop_relationships__(G, initial_cycle_weight, cycle_weight,
                                  edge_attribute):
    """
	helper function to determine child parent relationship for loops (or any other structural components)

	Input
		networkx graph G

		edge_attribute str, the name of the edge weight to be considered for type cycle

		cycle_weight
			the weight based on which edge are removed
			max: edge with the highest edge weight
			min: edge with the lowest edge weight
			betweenness_max: edge with the highest betweenness value
			betweenness_min: edge with the lowest betweenness value

		initial_cycle_weight
			if true then the initial cycle basis is estimated based on edge weight 
				with https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.cycles.minimum_cycle_basis.html#networkx.algorithms.cycles.minimum_cycle_basis
			else the initial cycles are estimated based on steps only
				with https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.cycles.cycle_basis.html#networkx.algorithms.cycles.cycle_basis

		Output
			dict of final loops

			dict of relationships

			dict of all loops

	"""
    if initial_cycle_weight:
        cycles = nx.minimum_cycle_basis(G)
    else:
        cycles = nx.cycle_basis(G)
    #print("cycles", cycles)
    #convert cycles into dict & edge list
    cycles_dict = __convert_cycles__(cycles)
    #print("cycles", cycles_dict)

    #construct dict to save cycles and give them id which is saved in tree
    #append each new created loop to dict
    save_loops = {}
    all_loops = {}
    for i in range(len(cycles_dict)):
        all_loops[i] = cycles_dict[i]
        save_loops[i] = cycles_dict[i]

    #2nd dict that stores loop id and  child nodes in list
    #initialize leave nodes
    relationship = {}
    for loop in all_loops:
        relationship[loop] = [None, None]

    #merged cycles - stores cycles already merged
    merged_nodes = []

    print("start creating hierarchical tree")

    while len(G.edges()) > 0:

        #community weight functions are used to find the most valuable edge

        if cycle_weight == "max":
            to_remove = __by_weight__(G, w_max=True, attribute=edge_attribute)

        elif cycle_weight == "min":
            to_remove = __by_weight__(G, w_max=False, attribute=edge_attribute)

        elif cycle_weight == "betweenness_max":
            to_remove = __by_centrality__(G,
                                          w_max=True,
                                          attribute=edge_attribute,
                                          type="betweenness")

        elif cycle_weight == "betweenness_min":
            to_remove = __by_centrality__(G,
                                          w_max=False,
                                          attribute=edge_attribute,
                                          type="betweenness")

        else:
            print("cycle weight not known, please select another one")
            return None
            break

        #remove edge from graph
        G.remove_edge(to_remove[0], to_remove[1])

        children = []
        cycle = []
        for loop_ID, loop in all_loops.items():
            #compare edges (independent of direction (x,y) == (y,x))
            #print(loop)
            #print(to_remove)
            if ((to_remove in loop) or ((to_remove[1], to_remove[0]) in loop)):

                children.append(loop_ID)
                merged_nodes.append(loop_ID)

                #new cycle is made up of all child edges except the removed edge
                for edge in loop:
                    if ((edge not in cycle)
                            and ((edge[1], edge[0]) not in cycle)):
                        if edge != to_remove and edge != (to_remove[1],
                                                          to_remove[0]):
                            cycle.append(edge)

        new_key = int(sorted(save_loops.keys())[-1]) + 1
        all_loops[new_key] = cycle
        save_loops[new_key] = cycle

        #and remove merged loops
        for child in children:
            del all_loops[child]

        #add parent child connection to relationship
        new_stage = int(sorted(relationship.keys())[-1]) + 1
        #find ID of children

        relationship[new_key] = children

    print("finished edge removal")

    return all_loops, relationship, save_loops
Esempio n. 17
0
from bmpga.utils.io_utils import XYZReader

reader = XYZReader()

XYZs = glob("test_data/*.xyz")

print(XYZs)

for xyz in XYZs:
    print(xyz)
    cluster = reader.read(xyz, return_clusters=True)[0]
    print(cluster.molecules)

    graph = cluster.molecules[0].to_graph()

    nodes = graph.nodes

    for node in nodes:
        print(node.__dict__)

    print(graph.nodes)

    print(graph.edges)

    cycles = nx.cycle_basis(graph)

    print(cycles)
    print(len(cycles))

    print(nx.minimum_cycle_basis(graph))
Esempio n. 18
0
def get_cycle_lengths(graph):
    """Get the length of cycles in a graph"""
    cycles = nx.minimum_cycle_basis(graph)
    lengths = count_sublist_lengths(cycles)
    return lengths