Source code for snarlpy.cycle_sampling

# @Author: Felix Kramer <felix>
# @Date:   2022-07-27T15:50:36+02:00
# @Email:  felixuwekramer@proton.me
# @Filename: cycle_sampling.py
# @Last modified by:   felix
# @Last modified time: 2022-07-28T15:16:36+02:00
import networkx as nx
import numpy as np
import numpy.random as nr
import random as rd
import itertools as it
import snarlpy.edge_algebra as edge_algebra


[docs]def generate_random_coordinate(nullity): """ Generate a binary sequence vector of length 'nullity'. Args: nullity (int): \n The cyclomatic number determining the length of the binary vector. Returns: list: \n A binary vector for cycle sampling from a set of cardinality 'nullity'. """ while True: k = nr.rand(nullity) r = np.round(k, 0) if not np.all(r == 0): break return r.astype(int)
[docs]def generate_random_index(nullity): """ Generate an index vector for sampling from a cycle basis of cardinality 'nullity'. Args: nullity (int): \n The cyclomatic number determining the length of the binary vector. Returns: list: \n An index vector for cycle sampling from a set of cardinality 'nullity'. """ k = generate_random_coordinate(nullity) idx = [i for i in range(nullity) if k[i] == 1] return idx.astype(int)
[docs]def get_keyNumbers_forBinary(null, iteration): """ Sample a random index from the cycle space of a graph with nullity 'null'. Args: null (int): \n The cyclomatic number determining the the exponential size of the cycle space. iteration (int): \n Sample size. Returns: iterable: \n An index vector for cycle sampling from a set of basis cardinality 'null'. """ exp = (2**null)-1 rnd_num = it.product( [rd.randint(1, exp) for i in range(iteration)], [null] ) return rnd_num
[docs]def grab_cycles_from_space(*args): """ Generate random cycle space coefficient vectors. Args: args (list): \n A list of cyclomatic numbers. Returns: iterable: \n A list of binary vectors for further cycle sampling processes. """ coeff = [generate_random_coordinate(a) for a in args] return coeff
[docs]def grab_all_cycles_from_space(*args): """ Generate and catch all cycle space coefficient vectors. (CAREFUL CYCLE SPACES HAVE EXPONENTIAL COMPLEXITY, ONLY USE FOR SMALL CYCLOMATIC NUMBERS) Args: args (list): \n A list of cyclomatic numbers. Returns: iterable: \n A list of binary vectors for further cycle sampling processes. """ aux = [] for i, a in enumerate(args): exp = 2**a tmp = [get_binary(j, a) for j in range(1, exp)] aux.append(tmp[:]) if len(args) > 1: total_key_set = it.product(*aux) else: total_key_set = aux[0] return list(total_key_set)
[docs]def get_binary(j, a): """ Generate a binary sequence vector of length a. Args: j (int): \n The j-th binary to generate. a (int): \n The cyclomatic number deterining the vector length/scope. Returns: list: \n A binary vector for further cycle sampling processes. """ # binNumb=format(j,'#0'+str(a)+'b') # binNumb = binNumb[2:] binNumb = f'{j:0{a}b}' seq = [int(b) for b in binNumb] return seq
[docs]def generate_networkx_cycle_from_edges(edge_set, input_graph): """ Generate networkx.Graph object representing a basis cycle from a given edge subset. Args: edge_set (list): \n The binary edge vector representing the cycle. input_graph (networkx.Graph): \n The original simple graph used for reduction. Returns: networkx.Graph: \n A simple eulerian cycle. """ nx_cycle = nx.Graph() edge_bunch = [ e for i, e in enumerate(input_graph.edges()) if edge_set[i] == 1 ] nx_cycle.add_edges_from(edge_bunch) return nx_cycle
[docs]def get_new_cycle(new_key, cycle_matrix, backbone_graph): """ Generate a new networkx.Graph object, representing a cycle from a given graph, its cycle basis and a binary coefficient vector. Args: new_key (int): \n The binary coefficient vectorto generate a cycle superpostion. cycle_matrix (int): \n The graph's mesh matrix for a given cycle basis. backbone_graph (int): \n The input graph used to reconstruct a full networkx.Graph object Returns: networkx.Graph: \n A simple eulerian cycle. """ new_edges = edge_algebra.get_cycle_superpositions_edge_vector( new_key, cycle_matrix ) new_cycle = generate_networkx_cycle_from_edges(new_edges, backbone_graph) return new_cycle
[docs]def get_new_cycle_components(edge_set, edge_matrix, nx_cycle, backbone_graph): """ Generate a new networkx.Graph object, representing a cycle from a given graph, its cycle basis and a binary coefficient vector. Args: edge_set (list): \n A list of all edges in the simple graph. edge_matrix (list): \n The binary mesh matrix of the graph. nx_cycle (networkx.Graph): \n The networx.Graph object representing a Eulerian cycle. backbone_graph (networkx.Graph): \n The original simple graph used for reduction. Returns: ndarray: \n The coefficient vector for given cycle in the current cycle basis. networkx.Graph: \n The rebuild of the given Eulerian cycle for simplification. """ es = edge_algebra.edge_column_binary(nx_cycle, edge_set) new_key = edge_algebra.get_component_key(es, edge_matrix) new_cycle = get_new_cycle(new_key, edge_matrix, backbone_graph) return new_key, new_cycle
[docs]def get_new_cycle_components_gamma(edge_set, edge_matrix, key, backbone_graph): """ Generate a new networkx.Graph object, representing a cycle from a given graph, its cycle basis and a binary coefficient vector. Args: edge_set (list): \n A list of all edges in the simple graph. edge_matrix (list): \n The binary mesh matrix of the graph. key (networkx.Graph): \n An index list indicating which cycles are to be superimposed. backbone_graph (networkx.Graph): \n The original simple graph used for reduction. Returns: ndarray: \n The coefficient vector for given cycle in the current cycle basis. networkx.Graph: \n The rebuild of the given Eulerian cycle for simplification. """ new_edges = edge_algebra.get_cycle_superpositions_edge_vector( key, edge_matrix ) new_key = edge_algebra.get_component_key(new_edges, edge_matrix) new_cycle = get_new_cycle(new_key, edge_matrix, backbone_graph) return new_key, new_cycle