Advertisement
Guest User

Untitled

a guest
May 2nd, 2016
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.76 KB | None | 0 0
  1. import networkx as nx
  2. from time import time
  3. import numpy as np
  4. from collections import defaultdict
  5. import random
  6.  
  7.  
  8. total_penalty = 0
  9.  
  10. def simple_cycles(G):
  11.     """Find simple cycles (elementary circuits) of a directed graph.
  12.    A `simple cycle`, or `elementary circuit`, is a closed path where
  13.    no node appears twice. Two elementary circuits are distinct if they
  14.    are not cyclic permutations of each other.
  15.    This is a nonrecursive, iterator/generator version of Johnson's
  16.    algorithm [1]_.  There may be better algorithms for some cases [2]_ [3]_.
  17.    Parameters
  18.    ----------
  19.    G : NetworkX DiGraph
  20.       A directed graph
  21.    Returns
  22.    -------
  23.    cycle_generator: generator
  24.       A generator that produces elementary cycles of the graph.
  25.       Each cycle is represented by a list of nodes along the cycle.
  26.    Examples
  27.    --------
  28.    >>> G = nx.DiGraph([(0, 0), (0, 1), (0, 2), (1, 2), (2, 0), (2, 1), (2, 2)])
  29.    >>> len(list(nx.simple_cycles(G)))
  30.    5
  31.    To filter the cycles so that they don't include certain nodes or edges,
  32.    copy your graph and eliminate those nodes or edges before calling
  33.    >>> copyG = G.copy()
  34.    >>> copyG.remove_nodes_from([1])
  35.    >>> copyG.remove_edges_from([(0, 1)])
  36.    >>> len(list(nx.simple_cycles(copyG)))
  37.    3
  38.    Notes
  39.    -----
  40.    The implementation follows pp. 79-80 in [1]_.
  41.    The time complexity is `O((n+e)(c+1))` for `n` nodes, `e` edges and `c`
  42.    elementary circuits.
  43.    References
  44.    ----------
  45.    .. [1] Finding all the elementary circuits of a directed graph.
  46.       D. B. Johnson, SIAM Journal on Computing 4, no. 1, 77-84, 1975.
  47.       http://dx.doi.org/10.1137/0204007
  48.    .. [2] Enumerating the cycles of a digraph: a new preprocessing strategy.
  49.       G. Loizou and P. Thanish, Information Sciences, v. 27, 163-182, 1982.
  50.    .. [3] A search strategy for the elementary cycles of a directed graph.
  51.       J.L. Szwarcfiter and P.E. Lauer, BIT NUMERICAL MATHEMATICS,
  52.       v. 16, no. 2, 192-204, 1976.
  53.    See Also
  54.    --------
  55.    cycle_basis
  56.    """
  57.     def _unblock(thisnode,blocked,B):
  58.         stack=set([thisnode])
  59.         while stack:
  60.             node=stack.pop()
  61.             if node in blocked:
  62.                 blocked.remove(node)
  63.                 stack.update(B[node])
  64.                 B[node].clear()
  65.  
  66.     # Johnson's algorithm requires some ordering of the nodes.
  67.     # We assign the arbitrary ordering given by the strongly connected comps
  68.     # There is no need to track the ordering as each node removed as processed.
  69.     subG = type(G)(G.edges()) # save the actual graph so we can mutate it here
  70.                               # We only take the edges because we do not want to
  71.                               # copy edge and node attributes here.
  72.     sccs = list(nx.strongly_connected_components(subG))
  73.     while sccs:
  74.         scc=sccs.pop()
  75.         # order of scc determines ordering of nodes
  76.         startnode = scc.pop()
  77.         # Processing node runs "circuit" routine from recursive version
  78.         path=[startnode]
  79.         blocked = set() # vertex: blocked from search?
  80.         closed = set() # nodes involved in a cycle
  81.         blocked.add(startnode)
  82.         B=defaultdict(set) # graph portions that yield no elementary circuit
  83.         stack=[ (startnode,list(subG[startnode])) ]  # subG gives component nbrs
  84.         while stack:
  85.             thisnode,nbrs = stack[-1]
  86.             if nbrs:
  87.                 nextnode = nbrs.pop()
  88. #                    print thisnode,nbrs,":",nextnode,blocked,B,path,stack,startnode
  89. #                    f=raw_input("pause")
  90.                 if nextnode == startnode:
  91.                     yield path[:]
  92.                     closed.update(path)
  93. #                        print "Found a cycle",path,closed
  94.                 elif nextnode not in blocked and len(stack) < 5:
  95.                     path.append(nextnode)
  96.                     stack.append( (nextnode,list(subG[nextnode])) )
  97.                     closed.discard(nextnode)
  98.                     blocked.add(nextnode)
  99.                     continue
  100.             # done with nextnode... look for more neighbors
  101.             if not nbrs:  # no more nbrs
  102.                 if thisnode in closed:
  103.                     _unblock(thisnode,blocked,B)
  104.                 else:
  105.                     for nbr in subG[thisnode]:
  106.                         if thisnode not in B[nbr]:
  107.                             B[nbr].add(thisnode)
  108.                 stack.pop()
  109. #                assert path[-1]==thisnode
  110.                 path.pop()
  111.         # done processing this node
  112.         subG.remove_node(startnode)
  113.         H=subG.subgraph(scc)  # make smaller to avoid work in SCC routine
  114.         sccs.extend(list(nx.strongly_connected_components(H)))
  115.  
  116.  
  117. def is_node_disjoint(cycles, cycle):
  118.     """ returns if any node in cycle is in any cycle in cycles"""
  119.  
  120.     nodes_in_cycles = set()
  121.     nodes_in_cycle = set()
  122.     for c in cycles:
  123.         for edge in c:
  124.             for node in edge:
  125.                 nodes_in_cycles.add(node)
  126.  
  127.     for edge in cycle:
  128.         for node in edge:
  129.             nodes_in_cycle.add(node)
  130.  
  131.     return len(nodes_in_cycles.intersection(nodes_in_cycle)) == 0
  132.  
  133. def temp_is_node_disjoint(cycles, cycle):
  134.     nodes_in_cycles = set()
  135.     nodes_in_cycle = set(cycle)
  136.     for cycle in cycles:
  137.         for node in cycle:
  138.             nodes_in_cycles.add(node)
  139.     return len(nodes_in_cycle.intersection(nodes_in_cycles)) == 0
  140.  
  141. def penalty(treated_cycles, children, num_vertices):
  142.  
  143.     output = num_vertices + len(children)
  144.     #print "Total possible penalty: " + str(output)
  145.     #print "Treated cycles: " + str(treated_cycles)
  146.     for cycle in treated_cycles:
  147.         for edge in cycle:
  148.             if edge[0] in children:
  149.                 output -= 2
  150.             else:
  151.                 output -= 1
  152.     return output
  153.  
  154. def temp_penalty(treated_cycles, children, num_vertices):
  155.  
  156.     output = num_vertices + len(children)
  157.     #print "Total possible penalty: " + str(output)
  158.     #print "Treated cycles: " + str(treated_cycles)
  159.     for cycle in treated_cycles:
  160.         for node in cycle:
  161.             if node in children:
  162.                 output -= 2
  163.             else:
  164.                 output -= 1
  165.     return output
  166.  
  167. def write_simple_cycles_to_file(treated_cycles, f):
  168.  
  169.     line = ""
  170.     if len(treated_cycles) == 0:
  171.         f.write("None\n")
  172.         return
  173.     for cycle in treated_cycles:
  174.         for node in cycle:
  175.             line = line + str(node) + " "
  176.         # remove trailing space
  177.         line = line[:-1]
  178.         line += "; "
  179.     # remove trailing ;
  180.     f.write(line[:-2] + "\n")
  181.  
  182. def write_dfs_cycles_to_file(treated_cycles, f):
  183.     line = ""
  184.     if len(treated_cycles) == 0:
  185.         f.write("None\n")
  186.         return
  187.     for cycle in treated_cycles:
  188.         for edge in cycle:
  189.             line = line + str(edge[0]) + " "
  190.         line = line[:-1]
  191.         line += "; "
  192.     # remove trailing ;
  193.     f.write(line[:-2] + "\n")
  194.  
  195. solutions = open("solutions.out", "w")
  196.  
  197. files = range(1, 493)
  198. for w in files:
  199.     print 'Processing file %s' % (w)
  200.     f = open('phase1-processed/' + str(w) + '.in', 'r')
  201.     n = int(f.readline()[:-1])
  202.  
  203.    
  204.  
  205.     children_line = f.readline()[:-1].strip()
  206.     if len(children_line) > 0:
  207.         children = np.array(map(int, children_line.split(" ")))
  208.     else:
  209.         children = np.array([])
  210.     adults = np.setdiff1d(np.arange(n), children)
  211.     adj = np.ndarray(shape=(n,n))
  212.     for i in range(n):
  213.         adj[i] = np.array(f.readline().split(' ')[:n])
  214.     f.close()
  215.    
  216.     G = nx.DiGraph()
  217.  
  218.     G.add_nodes_from(adults, weight=1)
  219.     G.add_nodes_from(children, weight=2)
  220.     for i in range(adj.shape[0]):
  221.         for j in range(adj.shape[1]):
  222.             if adj[i][j] == 1:
  223.                 G.add_edge(i,j)
  224.  
  225.  
  226.     treated_cycles = []
  227.     alternate_treated_cycles = []
  228.     untreated_cycles = []
  229.     untreated_vertices = set(range(n))
  230.     treated_vertices = set()
  231.    
  232.        
  233.  
  234.     # use Johnson's to find all cycles
  235.     if n < 50:
  236.         all_cycles = list(simple_cycles(G))
  237.         valid_cycles = [cycle for cycle in all_cycles if len(cycle) <= 5]
  238.         valid_cycles = sorted(valid_cycles, key=lambda x : -len(x))
  239.  
  240.         # greedily add all cycles that don't share vertices
  241.         longest_cycle_passed = False
  242.         for cycle in valid_cycles:
  243.  
  244.             if temp_is_node_disjoint(treated_cycles, cycle):
  245.                 treated_cycles.append(cycle)
  246.                 for node in cycle:
  247.                     if node in untreated_vertices:
  248.                         untreated_vertices.remove(node)
  249.                     treated_vertices.add(node)
  250.             if longest_cycle_passed and temp_is_node_disjoint(alternate_treated_cycles, cycle):
  251.                 alternate_treated_cycles.append(cycle)
  252.             else:
  253.                 untreated_cycles.append(cycle)
  254.  
  255.             longest_cycle_passed = True
  256.  
  257.  
  258.         instance_penalty = min(temp_penalty(treated_cycles, children, n), \
  259.                                temp_penalty(alternate_treated_cycles, children, n))
  260.         total_penalty += instance_penalty
  261.         #print "Penalty: " + str(instance_penalty)
  262.         write_simple_cycles_to_file(treated_cycles, solutions)
  263.  
  264.     else:
  265.  
  266.         valid_cycles = []
  267.         for node in random.sample(children, len(children)):
  268.             try:
  269.                 cycle = list(nx.find_cycle(G, source=node))
  270.                 G.remove_edges_from(cycle)  
  271.                 if len(cycle) <= 5:
  272.                     valid_cycles.append(cycle)
  273.             except:
  274.                 pass
  275.         for node in random.sample(adults, len(adults)):
  276.             try:
  277.                 cycle = list(nx.find_cycle(G, source=node))
  278.                 G.remove_edges_from(cycle)  
  279.                 if len(cycle) <= 5:
  280.                     valid_cycles.append(cycle)
  281.             except:
  282.                 pass
  283.  
  284.         longest_cycle_passed = False
  285.         for cycle in valid_cycles:
  286.  
  287.             if is_node_disjoint(treated_cycles, cycle):
  288.                 treated_cycles.append(cycle)
  289.                 for node in cycle:
  290.                     if node in untreated_vertices:
  291.                         untreated_vertices.remove(node)
  292.                     treated_vertices.add(node)
  293.             if longest_cycle_passed and is_node_disjoint(alternate_treated_cycles, cycle):
  294.                 alternate_treated_cycles.append(cycle)
  295.             else:
  296.                 untreated_cycles.append(cycle)
  297.  
  298.             longest_cycle_passed = True
  299.  
  300.         instance_penalty = min(penalty(treated_cycles, children, n),\
  301.                                penalty(alternate_treated_cycles, children, n))
  302.         total_penalty += instance_penalty
  303.  
  304.         write_dfs_cycles_to_file(treated_cycles, solutions)
  305.         #print "Penalty: " + str(instance_penalty)
  306.  
  307.  
  308.  
  309. print total_penalty
  310. solutions.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement