def backtrack_color(G, coloring = None, level = 1, chro_num = None): ''' Backtracking algorithm. G is a NetworkX graph, coloring is an ordered dictionary, level is an integer count of the recursive depth, and chro_num is the chromatic number of graph G. ''' global colorings #If this is the first call, set up the things: if level == 1: #Setting up results list: colorings = [] #Setting up coloring dictionary: coloring = OrderedDict() #Populating coloring dictionary: index = 0 for node in G: #Color first node with color 0 if index == 0: coloring[node] = 0 index += 1 #Color other nodes with nothing else: coloring[node] = None #Finding chromatic number of graph G, for future recursive calls chro_num = gp.chromatic_number(G) #Move to node 2 level += 1 #For all nodes in the graph: #for node in G.nodes: ### node_list = list(G.nodes) #For all valid colors: for color in range(0, chro_num): #DEBUG #print("checking " + str(color)) #If the node has no neighbors with the color, color it and continue: if legal_color(node_list[level-1], color, coloring): #DEBUG #print("coloring " + str(node_list[level-1]) + " " + str(color)) coloring[node_list[level-1]] = color #If not all nodes have been colored, increment level and recurse: if level < G.number_of_nodes(): backtrack_color(G, coloring, (level+1), chro_num) #If all nodes have been colored, we have reached an optimal solution #(optimal since we only permitted colors up to the chromatic number) else: #Add the solution to the list colorings.append(coloring.copy())
import sys sys.path.append('../') import grinpy as gp import numpy as np G = gp.circular_ladder_graph(10) chromatic_number = gp.chromatic_number(G, method='ilp') print('Chromatic number (ILP): {}'.format(chromatic_number))
def main(): '''Driver program''' args = parse_args() log('Starting...') # load graphs, or generate them if they don't exist if not os.path.exists(str(GRAPH_DIR)): os.mkdir(str(GRAPH_DIR)) if not os.path.exists(str(GRAPH_DIR / SML_NAME)): record_graphs(gen_rand_graphs(SML), str(GRAPH_DIR / SML_NAME)) if not os.path.exists(str(GRAPH_DIR / MED_NAME)): record_graphs(gen_rand_graphs(MED), str(GRAPH_DIR / MED_NAME)) if not os.path.exists(str(GRAPH_DIR / LRG_NAME)): record_graphs(gen_rand_graphs(LRG), str(GRAPH_DIR / LRG_NAME)) if args.n < 1: log('Must select at least one graph.') raise SystemExit graphs = load_graphs(args.mode, args.n) # ground truth graphs start = time.time() if args.gtskip: gt_graphs = {graph: None for graph in graphs} else: log('Calculating ground truth...') gt_graphs = {graph: gp.chromatic_number(graph) for graph in graphs} log(f'{round(time.time() - start, 3)} seconds') # color each graph with each algorithm # each algorithm will predict the chi of the graph and this will form new # mappings of graph -> chi log('Calculating greedy colorings...') start = time.time() gr_graphs = {graph: greedy_color(graph) for graph in graphs} log(f'{round(time.time() - start, 3)} seconds') log('Calculating differential evolution colorings...') start = time.time() de_graphs = compute_chi(de, graphs) log(f'{round(time.time() - start, 3)} seconds') log('Calculating particle swarm optimization colorings...') start = time.time() pso_graphs = compute_chi(pso, graphs) log(f'{round(time.time() - start, 3)} seconds') log('Calculating firefly algorithm colorings...') start = time.time() ff_graphs = compute_chi(ff, graphs) log(f'{round(time.time() - start, 3)} seconds') # print results table_1 = tab.tabulate( zip(list(range(len(graphs))), gt_graphs.values(), gr_graphs.values(), de_graphs.values(), pso_graphs.values(), ff_graphs.values()), headers=['id', 'truth', 'greedy', 'de', 'pso', 'firefly']) log(f'\nChromatic numbers for graphs:\n{table_1}') min_chi = min([ min(gr_graphs.values()), min(de_graphs.values()), min(pso_graphs.values()), min(ff_graphs.values()) ]) max_chi = max([ max(gr_graphs.values()), max(de_graphs.values()), max(pso_graphs.values()), max(ff_graphs.values()) ]) gr_modes = [ list(gr_graphs.values()).count(idx) for idx in range(min_chi, max_chi + 1) ] de_modes = [ list(de_graphs.values()).count(idx) for idx in range(min_chi, max_chi + 1) ] pso_modes = [ list(pso_graphs.values()).count(idx) for idx in range(min_chi, max_chi + 1) ] firefly_mode = [ list(ff_graphs.values()).count(idx) for idx in range(min_chi, max_chi + 1) ] table_2 = tab.tabulate(zip(list(range(min_chi, max_chi + 1)), gr_modes, de_modes, pso_modes, firefly_mode), headers=['chi', 'greedy', 'de', 'pso', 'firefly']) log(f'\nFrequency of chromatic numbers:\n{table_2}') log('...finished.') return 0
def test_chromatic_number_of_complete_graph_is_order(): for i in range(1, 11): G = gp.complete_graph(i) assert (gp.chromatic_number(G, method='ram-rama') == G.order()) assert (gp.chromatic_number(G, method='ilp') == G.order())
def test_chromatic_number_of_petersen_graph_is_3(): G = gp.petersen_graph() assert (gp.chromatic_number(G, method='ram-rama') == 3) assert (gp.chromatic_number(G, method='ilp') == 3)
import sys sys.path.append('../') import grinpy as gp import numpy as np G = gp.circular_ladder_graph(10) chromatic_number = gp.chromatic_number(G, method='ram-rama') print('Chromatic number (Ram-Rama): {}'.format(chromatic_number))
def test_chromatic_number_of_complete_graph_is_order(): for i in range(1, 11): G = gp.complete_graph(i) assert gp.chromatic_number(G, method="ram-rama") == G.order() assert gp.chromatic_number(G, method="ilp") == G.order()
def test_chromatic_number_of_petersen_graph_is_3(): G = gp.petersen_graph() assert gp.chromatic_number(G, method="ram-rama") == 3 assert gp.chromatic_number(G, method="ilp") == 3