def queue_job(a, ready_queue): # We just crank out plans until we are terminated while True: b = a.copy() success = maxfield.maxFields(b) if success: for t in b.triangulation: t.markEdgesWithFields() maxfield.improveEdgeOrder(b) ready_queue.put((success, b))
def main(): description = ('Ingress FieldPlan - Maximize the number of links ' 'and fields, and thus AP, for a collection of ' 'portals in the game Ingress and create a convenient plan ' 'in Google Spreadsheets. Spin-off from Maxfield.') parser = argparse.ArgumentParser( description=description, prog='makePlan.py', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument( '-i', '--iterations', type=int, default=10000, help='Number of iterations to perform. More iterations may improve ' 'results, but will take longer to process.') parser.add_argument('-k', '--maxkeys', type=int, default=None, help='Limit number of keys required per portal ' '(may result in less efficient plans)') parser.add_argument( '-m', '--travelmode', default='walking', help='Travel mode (walking, bicycling, driving, transit).') parser.add_argument( '-s', '--sheetid', default=None, required=True, help='The Google Spreadsheet ID with portal definitions.') parser.add_argument( '-n', '--nosave', action='store_true', default=False, help='Do not attempt to save the spreadsheet, just calculate the plan.' ) parser.add_argument( '-p', '--plots', default=None, help='Save step-by-step PNGs of the workplan into this directory.') parser.add_argument( '--plotdpi', default=96, type=int, help='DPI to use for generating plots (try 144 for high-dpi screens)') parser.add_argument('-g', '--gmapskey', default=None, help='Google Maps API key (for better distances)') parser.add_argument('-f', '--faction', default='enl', help='Set to "res" to use resistance colours') parser.add_argument('-l', '--log', default=None, help='Log file where to log processing info') parser.add_argument('-d', '--debug', action='store_true', default=False, help='Add debug information to the logfile') parser.add_argument('-q', '--quiet', action='store_true', default=False, help='Only output errors to the stdout') args = parser.parse_args() if args.iterations < 0: parser.error('Number of extra samples should be positive') if args.plotdpi < 1: parser.error('%s is not a valid screen dpi' % args.plotdpi) if args.faction not in ('enl', 'res'): parser.error('Sorry, I do not know about faction "%s".' % args.faction) logger.setLevel(logging.DEBUG) if args.log: ch = logging.FileHandler(args.log) formatter = logging.Formatter( '{%(module)s:%(funcName)s:%(lineno)s} %(message)s') ch.setFormatter(formatter) if args.debug: ch.setLevel(logging.DEBUG) else: ch.setLevel(logging.INFO) logger.addHandler(ch) ch = logging.StreamHandler() formatter = logging.Formatter('%(message)s') ch.setFormatter(formatter) if args.quiet: ch.setLevel(logging.CRITICAL) else: ch.setLevel(logging.INFO) logger.addHandler(ch) gs = gsheets.setup() portals, blockers = gsheets.get_portals_from_sheet(gs, args.sheetid) logger.info('Considering %d portals', len(portals)) if len(portals) < 3: logger.critical('Must have more than 2 portals!') sys.exit(1) if len(portals) > _MAX_PORTALS_: logger.critical('Portal limit is %d', _MAX_PORTALS_) a = maxfield.populateGraph(portals) ab = None if blockers: ab = maxfield.populateGraph(blockers) (bestgraph, bestplan, bestdist) = maxfield.loadCache(a, ab) if bestgraph is None: # Use a copy, because we concat ab to a for blockers distances maxfield.genDistanceMatrix(a.copy(), ab, args.gmapskey, args.travelmode) bestkm = None else: bestkm = bestdist / float(1000) logger.info('Best distance of the plan loaded from cache: %0.2f km', bestkm) counter = 0 if args.maxkeys: logger.info('Finding an efficient plan with max %s keys', args.maxkeys) else: logger.info('Finding an efficient plan') logger.info('Ctrl-C to exit and use the latest best plan') failcount = 0 try: while counter < args.iterations: if failcount >= 100: logger.info('Too many consecutive failures, exiting early.') break b = a.copy() counter += 1 if not args.quiet: if bestkm is not None: sys.stdout.write('\r(%0.2f km best): %s/%s ' % (bestkm, counter, args.iterations)) sys.stdout.flush() failcount += 1 if not maxfield.maxFields(b): logger.debug('Could not find a triangulation') failcount += 1 continue for t in b.triangulation: t.markEdgesWithFields() maxfield.improveEdgeOrder(b) workplan = maxfield.makeWorkPlan(b, ab) if args.maxkeys: # do any of the portals require more than maxkeys sane_key_reqs = True for i in range(len(b.node)): if b.in_degree(i) > args.maxkeys: sane_key_reqs = False break if not sane_key_reqs: failcount += 1 logger.debug('Too many keys required, ignoring plan') continue sane_out_links = True for i in range(len(b.node)): if b.out_degree(i) > 8: sane_out_links = False break if not sane_out_links: failcount += 1 logger.debug('Too many outgoing links, ignoring plan') continue failcount = 0 totaldist = maxfield.getWorkplanDist(b, workplan) if totaldist < bestdist: counter = 0 bestplan = workplan bestgraph = b bestdist = totaldist bestkm = bestdist / float(1000) except KeyboardInterrupt: if not args.quiet: print() print('Exiting loop') if not args.quiet: print() if bestplan is None: logger.critical('Could not find a solution for this list of portals.') sys.exit(1) maxfield.saveCache(bestgraph, ab, bestplan, bestdist) if args.plots: animate.make_png_steps(bestgraph, bestplan, args.plots, args.faction, args.plotdpi) gs = gsheets.setup() gsheets.write_workplan(gs, args.sheetid, bestgraph, bestplan, args.faction, args.travelmode, args.nosave)
def main(): args = docopt(__doc__) # We will take many samples in an attempt to reduce number of keys to farm # This is the number of samples to take since the last improvement EXTRA_SAMPLES = 20 np = geometry.np #GREEN = 'g' #BLUE = 'b' GREEN = '#3BF256' # Actual faction text colors in the app BLUE = '#2ABBFF' #GREEN = (0.0 , 1.0 , 0.0 , 0.3) #BLUE = (0.0 , 0.0 , 1.0 , 0.3) COLOR = GREEN if args['-b']: COLOR = BLUE output_directory = '' if args['<output_directory>'] != None: output_directory = args['<output_directory>'] if output_directory[-1] != '/': output_directory += '/' output_file = 'lastPlan.pkl' if args['<output_file>'] != None: output_file = args['<output_file>'] if not output_file[-3:] == 'pkl': print 'WARNING: output file should end in "pkl" or you cannot use it as input later' nagents = int(args['-n']) if nagents < 0: print 'Numer of agents should be positive' exit() input_file = args['<input_file>'] if input_file[-3:] != 'pkl': a = nx.DiGraph() locs = [] i = 0 # each line should be id,name,lat,long,keys with open(input_file,'r') as fin: for line in fin: parts = line.split(',') if len(parts) < 3: break a.add_node(i) a.node[i]['name'] = parts[0].strip() locs.append( np.array(parts[1:3],dtype=int) ) if len(parts) < 4: a.node[i]['keys'] = 0 else: a.node[i]['keys'] = int(parts[3]) i += 1 n = a.order() # number of nodes locs = np.array(locs,dtype=float) # This part assumes we're working with E6 latitude-longitude data locs = geometry.e6LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs,xyz) for i in xrange(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz [i] a.node[i]['xy' ] = xy [i] # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf sinceImprove = 0 while sinceImprove<EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print 'Randomization failure\nThe program may work if you try again. It is more likely to work if you remove some protals.' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK if weightedlack < bestlack: sinceImprove = 0 print 'IMPROVEMENT:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print 'this time:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) if weightedlack == 0: print 'KEY PERFECTION' bestlack = weightedlack bestTK = TK bestMK = MK break if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): print 'All keys used. Improvement impossible' break print '%s tries since improvement'%sinceImprove if bestgraph == None: print 'EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!' print '' exit() print 'Choosing plan requiring %s additional keys, max of %s from single portal'%(bestTK,bestMK) a = bestgraph # Attach to each edge a list of fields that it completes for t in a.triangulation: t.markEdgesWithFields() agentOrder.improveEdgeOrder(a) with open(output_directory+output_file,'w') as fout: pickle.dump(a,fout) else: with open(input_file,'r') as fin: a = pickle.load(fin) # agentOrder.improveEdgeOrder(a) # with open(output_directory+output_file,'w') as fout: # pickle.dump(a,fout) PP = PlanPrinter.PlanPrinter(a,output_directory,nagents,COLOR) PP.keyPrep() PP.agentKeys() PP.planMap() PP.agentLinks()
def main(): description = ("Ingress Maxfield - Maximize the number of links " "and fields, and thus AP, for a collection of " "portals in the game Ingress.") parser = argparse.ArgumentParser(description=description, prog="makePlan.py") parser.add_argument('-v', '--version', action='version', version="Ingress Maxfield v{0}".format(_V_)) parser.add_argument('-g', '--google', action='store_true', help='Make maps with google maps API. Default: False') parser.add_argument('-a', '--api_key', default=None, help='Google API key for Google maps. Default: None') parser.add_argument('-n', '--num_agents', type=int, default='1', help='Number of agents. Default: 1') parser.add_argument('-s', '--samples', type=int, default=50, help="Number of iterations to " "perform. More iterations may improve " "results, but will take longer to process. " "Default: 50") parser.add_argument('input_file', help="Input semi-colon delimited portal file") parser.add_argument('-d', '--output_dir', default='', help="Directory for results. Default: " "this directory") parser.add_argument('-f', '--output_file', default='plan.pkl', help="Filename for pickle object. Default: " "plan.pkl") args = vars(parser.parse_args()) # Number of iterations to complete since last improvement EXTRA_SAMPLES = args["samples"] GREEN = '#3BF256' # Actual faction text colors in the app BLUE = '#2ABBFF' # Use google? useGoogle = args['google'] api_key = args['api_key'] output_directory = args["output_dir"] # add ending separator if output_directory[-1] != os.sep: output_directory += os.sep # create directory if doesn't exist if not os.path.isdir(output_directory): os.mkdir(output_directory) output_file = args["output_file"] if output_file[-4:] != '.pkl': output_file += ".pkl" nagents = args["num_agents"] if nagents < 0: sys.exit("Number of agents should be positive") EXTRA_SAMPLES = args["samples"] if EXTRA_SAMPLES < 0: sys.exit("Number of extra samples should be positive") elif EXTRA_SAMPLES > 100: sys.exit("Extra samples may not be more than 100") input_file = args['input_file'] if input_file[-3:] != 'pkl': # If the input file is a portal list, let's set things up a = nx.DiGraph() # network tool locs = [] # portal coordinates # each line should be name;intel_link;keys portals = pd.read_table(input_file, sep=';', comment='#', index_col=False, names=['name', 'link', 'keys'], dtype=str) portals = np.array(portals) portals = np.array([ portal for portal in portals if (isinstance(portal[0], basestring) and isinstance(portal[1], basestring)) ]) print "Found {0} portals in portal list.".format(len(portals)) if len(portals) < 3: sys.exit("Error: Must have more than 2 portals!") if len(portals) > _MAX_PORTALS_: sys.exit("Error: Portal limit is {0}".\ format(_MAX_PORTALS_)) for num, portal in enumerate(portals): if len(portal) < 3: print "Error! Portal ", portal[0], " has a formatting problem." sys.exit() a.add_node(num) a.node[num]['name'] = portal[0] coords = (portal[1].split('pll=')) if len(coords) < 2: print "Error! Portal ", portal[0], " has a formatting problem." sys.exit() coord_parts = coords[1].split(',') lat = int(float(coord_parts[0]) * 1.e6) lon = int(float(coord_parts[1]) * 1.e6) locs.append(np.array([lat, lon], dtype=float)) try: keys = int(portal[2]) a.node[num]['keys'] = keys except ValueError: a.node[num]['keys'] = 0 n = a.order() # number of nodes locs = np.array(locs, dtype=float) # Convert coords to radians, then to cartesian, then to # gnomonic projection locs = geometry.e6LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs, xyz) for i in xrange(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz[i] a.node[i]['xy'] = xy[i] # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single # portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf allTK = [] allMK = [] allWeights = [] sinceImprove = 0 while sinceImprove < EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print 'Randomization failure\nThe program may work if you try again. It is more likely to work if you remove some portals.' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j) - b.node[j]['keys'], 0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK + 2 * MK allTK.append(TK) allMK.append(MK) allWeights.append(weightedlack) if weightedlack < bestlack: sinceImprove = 0 print 'IMPROVEMENT:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print 'this time:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) if weightedlack <= 0: print 'KEY PERFECTION' bestlack = weightedlack bestTK = TK bestMK = MK break # if num agent keys is zero, this code isn't true... # if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): # print 'All keys used. Improvement impossible' # break print '%s tries since improvement' % sinceImprove if bestgraph == None: print 'EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!' print '' exit() print 'Choosing plan requiring %s additional keys, max of %s from single portal' % ( bestTK, bestMK) plt.clf() plt.scatter(allTK, allMK, c=allWeights, marker='o') plt.xlim(min(allTK) - 1, max(allTK) + 1) plt.ylim(min(allMK) - 1, max(allMK) + 1) plt.xlabel('Total keys required') plt.ylabel('Max keys required for a single portal') cbar = plt.colorbar() cbar.set_label('Optimization Weighting (lower=better)') plt.savefig(output_directory + 'optimization.png') a = bestgraph # Attach to each edge a list of fields that it completes # catch no triangulation (bad portal file?) try: for t in a.triangulation: t.markEdgesWithFields() except AttributeError: print "Error: problem with bestgraph... no triangulation...?" agentOrder.improveEdgeOrder(a) with open(output_directory + output_file, 'w') as fout: pickle.dump(a, fout) else: with open(input_file, 'r') as fin: a = pickle.load(fin) # agentOrder.improveEdgeOrder(a) # with open(output_directory+output_file,'w') as fout: # pickle.dump(a,fout) PP = PlanPrinterMap.PlanPrinter(a, output_directory, nagents, useGoogle=useGoogle, api_key=api_key) PP.keyPrep() PP.agentKeys() PP.planMap(useGoogle=useGoogle) PP.agentLinks() # These make step-by-step instructional images PP.animate(useGoogle=useGoogle) PP.split3instruct(useGoogle=useGoogle) print "Number of portals: {0}".format(PP.num_portals) print "Number of links: {0}".format(PP.num_links) print "Number of fields: {0}".format(PP.num_fields) portal_ap = (125 * 8 + 500 + 250) * PP.num_portals link_ap = 313 * PP.num_links field_ap = 1250 * PP.num_fields print "AP from portals capture: {0}".format(portal_ap) print "AP from link creation: {0}".format(link_ap) print "AP from field creation: {0}".format(field_ap) print "Total AP: {0}".format(portal_ap + link_ap + field_ap)
def main(): description=("Ingress Maxfield - Maximize the number of links " "and fields, and thus AP, for a collection of " "portals in the game Ingress.") parser = argparse.ArgumentParser(description=description, prog="makePlan.py") parser.add_argument('-v','--version',action='version', version="Ingress Maxfield v{0}".format(_V_)) parser.add_argument('-g','--google',action='store_true', help='Make maps with google maps API. Default: False') parser.add_argument('-a','--api_key',default=None, help='Google API key for Google maps. Default: None') parser.add_argument('-n','--num_agents',type=int,default='1', help='Number of agents. Default: 1') parser.add_argument('-s','--samples',type=int,default=50, help="Number of iterations to " "perform. More iterations may improve " "results, but will take longer to process. " "Default: 50") parser.add_argument('input_file', help="Input semi-colon delimited portal file") args = vars(parser.parse_args()) # Number of iterations to complete since last improvement EXTRA_SAMPLES = args["samples"] GREEN = '#3BF256' # Actual faction text colors in the app BLUE = '#2ABBFF' # Use google? useGoogle = True api_key = args['api_key'] input_file = args['input_file'] output_directory = os.path.expanduser('~') + "/Ingress/Fielding/{}".format(os.path.split(args['input_file'])[1][:-4]) print(output_directory) # add ending separator if output_directory[-1] != os.sep: output_directory += os.sep # create directory if doesn't exist if not os.path.exists(output_directory): os.makedirs(output_directory) output_file = (os.path.split(args['input_file'])[1][:-4]) print(output_file) if output_file[-4:] != '.pkl': output_file += ".pkl" nagents = args["num_agents"] if nagents < 0: sys.exit("Number of agents should be positive") EXTRA_SAMPLES = args["samples"] if EXTRA_SAMPLES < 0: sys.exit("Number of extra samples should be positive") elif EXTRA_SAMPLES > 100: sys.exit("Extra samples may not be more than 100") if input_file[-3:] != 'pkl': # If the input file is a portal list, let's set things up a = nx.DiGraph() # network tool locs = [] # portal coordinates # each line should be name;intel_link;keys portals = pd.read_table(input_file,sep=';', comment='#',index_col=False, names=['name','link','keys'],dtype=str) portals = np.array(portals) portals = np.array([portal for portal in portals if (isinstance(portal[0], basestring) and isinstance(portal[1], basestring))]) print ("Found {0} portals in portal list.".format(len(portals))) if len(portals) < 3: sys.exit("Error: Must have more than 2 portals!") if len(portals) > _MAX_PORTALS_: sys.exit("Error: Portal limit is {0}".\ format(_MAX_PORTALS_)) for num,portal in enumerate(portals): if len(portal) < 3: print ("Error! Portal ",portal[0]," has a formatting problem.") sys.exit() a.add_node(num) a.node[num]['name'] = portal[0] coords = (portal[1].split('pll=')) if len(coords) < 2: print ("Error! Portal ",portal[0]," has a formatting problem.") sys.exit() coord_parts = coords[1].split(',') lat = int(float(coord_parts[0]) * 1.e6) lon = int(float(coord_parts[1]) * 1.e6) locs.append(np.array([lat,lon],dtype=float)) try: keys = int(portal[2]) a.node[num]['keys'] = keys except ValueError: a.node[num]['keys'] = 0 n = a.order() # number of nodes locs = np.array(locs,dtype=float) # Convert coords to radians, then to cartesian, then to # gnomonic projection locs = geometry.e6LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs,xyz) for i in range(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz[i] a.node[i]['xy' ] = xy[i] # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single # portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf allTK = [] allMK = [] allWeights = [] sinceImprove = 0 while sinceImprove<EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print ('Randomization failure\nThe program may work if you try again. It is more likely to work if you remove some portals.') continue TK = 0 MK = 0 for j in range(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK allTK.append(TK) allMK.append(MK) allWeights.append(weightedlack) if weightedlack < bestlack: sinceImprove = 0 print ('IMPROVEMENT:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack)) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print ('this time:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack)) if weightedlack <= 0: print ('KEY PERFECTION') bestlack = weightedlack bestTK = TK bestMK = MK break # if num agent keys is zero, this code isn't true... # if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): # print 'All keys used. Improvement impossible' # break print ('%s tries since improvement'%sinceImprove) if bestgraph == None: print ('EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!') print ('') exit() print ('Choosing plan requiring %s additional keys, max of %s from single portal'%(bestTK,bestMK)) plt.clf() plt.scatter(allTK,allMK,c=allWeights,marker='o') plt.xlim(min(allTK)-1,max(allTK)+1) plt.ylim(min(allMK)-1,max(allMK)+1) plt.xlabel('Total keys required') plt.ylabel('Max keys required for a single portal') cbar = plt.colorbar() cbar.set_label('Optimization Weighting (lower=better)') plt.savefig(output_directory+'optimization.png') a = bestgraph # Attach to each edge a list of fields that it completes # catch no triangulation (bad portal file?) try: for t in a.triangulation: t.markEdgesWithFields() except AttributeError: print ("Error: problem with bestgraph... no triangulation...?") agentOrder.improveEdgeOrder(a) with open(output_directory+output_file,'wb') as fout: pickle.dump(a,fout) else: with open(input_file,'r') as fin: a = pickle.load(fin) # agentOrder.improveEdgeOrder(a) # with open(output_directory+output_file,'w') as fout: # pickle.dump(a,fout) PP = PlanPrinterMap.PlanPrinter(a,output_directory,nagents,color=BLUE,useGoogle=useGoogle, api_key=api_key) PP.keyPrep() PP.agentKeys() PP.planMap(useGoogle=useGoogle) PP.agentLinks() # These make step-by-step instructional images PP.animate(useGoogle=useGoogle) PP.split3instruct(useGoogle=useGoogle) print ("Number of portals: {0}".format(PP.num_portals)) print ("Number of links: {0}".format(PP.num_links)) print ("Number of fields: {0}".format(PP.num_fields)) portal_ap = (125*8 + 500 + 250)*PP.num_portals link_ap = 313 * PP.num_links field_ap = 1250 * PP.num_fields print ("AP from portals capture: {0}".format(portal_ap)) print ("AP from link creation: {0}".format(link_ap)) print ("AP from field creation: {0}".format(field_ap)) print ("Total AP: {0}".format(portal_ap+link_ap+field_ap))
def main(): args = docopt(__doc__) # We will take many samples in an attempt to reduce number of keys to farm # This is the number of samples to take since the last improvement EXTRA_SAMPLES = 20 np = geometry.np #GREEN = 'g' #BLUE = 'b' GREEN = '#3BF256' # Actual faction text colors in the app BLUE = '#2ABBFF' #GREEN = (0.0 , 1.0 , 0.0 , 0.3) #BLUE = (0.0 , 0.0 , 1.0 , 0.3) COLOR = BLUE if args['-b']: COLOR = GREEN output_directory = '' if args['<output_directory>'] != None: output_directory = args['<output_directory>'] if output_directory[-1] != '/': output_directory += '/' if( not os.path.isdir('./'+output_directory) ): print 'Output directory (%s) does not exist. Creating it.' % output_directory os.makedirs('./'+output_directory) output_file = 'lastPlan.pkl' if args['<output_file>'] != None: output_file = args['<output_file>'] if not output_file[-3:] == 'pkl': print 'WARNING: output file should end in "pkl" or you cannot use it as input later' nagents = int(args['-n']) if nagents < 0: print 'Numer of agents should be positive' exit() input_file = args['<input_file>'] if input_file[-3:] != 'pkl': a = nx.DiGraph() locs = [] i = 0 # each line should be id,name,lat,long,keys with open(input_file,'r') as fin: for line in fin: parts = line.split(',') if len(parts) < 3: break # allow masking of input csv file # note, if no 4th column, back to default behavior # unless you put "false" as the number of keys ;) use = parts[-1].strip().lower() if(use == "false"): continue a.add_node(i) a.node[i]['name'] = parts[0].strip() locs.append( np.array(parts[1:3],dtype=int) ) if len(parts) < 4: a.node[i]['keys'] = 0 else: a.node[i]['keys'] = int(parts[3]) i += 1 n = a.order() # number of nodes locs = np.array(locs,dtype=float) # This part assumes we're working with E6 latitude-longitude data locs = geometry.e6LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs,xyz) for i in xrange(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz [i] a.node[i]['xy' ] = xy [i] # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf sinceImprove = 0 while sinceImprove<EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print 'Randomization failure\nThe program may work if you try again. It is more likely to work if you remove some protals.' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK if weightedlack < bestlack: sinceImprove = 0 print 'IMPROVEMENT:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print 'this time:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) if weightedlack == 0: print 'KEY PERFECTION' bestlack = weightedlack bestTK = TK bestMK = MK break if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): print 'All keys used. Improvement impossible' break print '%s tries since improvement'%sinceImprove if bestgraph == None: print 'EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!' print '' exit() print 'Choosing plan requiring %s additional keys, max of %s from single portal'%(bestTK,bestMK) a = bestgraph # Attach to each edge a list of fields that it completes for t in a.triangulation: t.markEdgesWithFields() agentOrder.improveEdgeOrder(a) with open(output_directory+output_file,'w') as fout: pickle.dump(a,fout) else: with open(input_file,'r') as fin: a = pickle.load(fin) # agentOrder.improveEdgeOrder(a) # with open(output_directory+output_file,'w') as fout: # pickle.dump(a,fout) PP = PlanPrinter.PlanPrinter(a,output_directory,nagents,COLOR) PP.keyPrep() PP.agentKeys() PP.planMap() PP.agentLinks()
def main(args): start_time = time.time() if args.log is not None: sys.stdout = open(args.log,'w',0) GREEN = '#3BF256' # Actual faction text colors in the app BLUE = '#2ABBFF' if args.res: color=BLUE else: color=GREEN # Use google? useGoogle = args.google api_key = args.api_key output_directory = args.output_dir # add ending separator if output_directory[-1] != os.sep: output_directory += os.sep # create directory if doesn't exist if not os.path.isdir(output_directory): os.mkdir(output_directory) output_file = args.output_file if output_file[-4:] != '.pkl': output_file += ".pkl" nagents = args.num_agents if nagents <= 0: print "Number of agents should be greater than zero" raise ValueError("Number of agents should be greater than zero") input_file = args.input_file if input_file[-3:] != 'pkl': # If the input file is a portal list, let's set things up a = nx.DiGraph() # network tool locs = [] # portal coordinates # each line should be name;intel_link;keys portals = pd.read_table(input_file,sep=';', comment='#',index_col=False, names=['name','link','keys','sbla'], dtype=str) portals = np.array(portals) portals = np.array([portal for portal in portals if (isinstance(portal[0], basestring) and isinstance(portal[1], basestring))]) print "Found {0} portals in portal list.".format(len(portals)) if len(portals) < 3: print "Error: Must have more than 2 portals!" raise ValueError("Error: Must have more than 2 portals!") if len(portals) > _MAX_PORTALS_: print "Error: Portal limit is {0}".format(_MAX_PORTALS_) raise ValueError("Error: Portal limit is {0}".format(_MAX_PORTALS_)) for num,portal in enumerate(portals): if len(portal) < 3: print "Error! Portal ",portal[0]," has a formatting problem." raise ValueError("Error! Portal ",portal[0]," has a formatting problem.") # loop over columns. Four possibilities: # 0. First entry is always portal name # 1. contains "pll=" it is the Intel URL # 2. contains an intenger, it is the number of keys # 3. contains "sbla", it is an SBLA portal loc = None keys = 0 sbla = False for pind,pfoobar in enumerate(portal): if str(pfoobar) == 'nan': continue if pind == 0: # This is the name a.add_node(num) a.node[num]['name'] = pfoobar.strip() continue if 'pll=' in pfoobar: # this is the URL if loc is not None: print "Error! Already found URL for this portal: {0}".format(portal[0]) raise ValueError("Error! Already found URL for this portal: {0}".format(portal[0])) coords = (pfoobar.strip().split('pll=')) if len(coords) < 2: print "Error! Portal ",portal[0]," has a formatting problem." raise ValueError("Error! Portal ",portal[0]," has a formatting problem.") coord_parts = coords[1].split(',') lat = int(float(coord_parts[0]) * 1.e6) lon = int(float(coord_parts[1]) * 1.e6) loc = np.array([lat,lon],dtype=float) continue try: # this is the number of keys keys = int(pfoobar.strip()) continue except ValueError: pass try: # this is SBLA sbla = pfoobar.strip() sbla = (sbla.lower() == 'sbla') continue except ValueError: pass # we should never get here unless there was a bad column print "Error: bad data value here:" print portal print pfoobar raise ValueError() if loc is None: print "Formatting problem: {0}".format(portal[0]) raise ValueError("Formatting problem: {0}".format(portal[0])) locs.append(loc) a.node[num]['keys'] = keys a.node[num]['sbla'] = sbla if sbla: print "{0} has SBLA".format(portal[0]) n = a.order() # number of nodes locs = np.array(locs,dtype=float) # Convert coords to radians, then to cartesian, then to # gnomonic projection locs = geometry.LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs,xyz) for i in xrange(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz[i] a.node[i]['xy' ] = xy[i] # Below is remnants from "random optimization" technique """ # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single # portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf allTK = [] allMK = [] allWeights = [] sinceImprove = 0 while sinceImprove<EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print 'Randomization failure\nThe program may work if you try again. It is more likely to work if you remove some portals.' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK allTK.append(TK) allMK.append(MK) allWeights.append(weightedlack) if weightedlack < bestlack: sinceImprove = 0 print 'IMPROVEMENT:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print 'this time:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) if weightedlack <= 0: print 'KEY PERFECTION' bestlack = weightedlack bestTK = TK bestMK = MK break # if num agent keys is zero, this code isn't true... # if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): # print 'All keys used. Improvement impossible' # break print '%s tries since improvement'%sinceImprove if bestgraph == None: print 'EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!' print '' exit() print 'Choosing plan requiring %s additional keys, max of %s from single portal'%(bestTK,bestMK) plt.clf() plt.scatter(allTK,allMK,c=allWeights,marker='o') plt.xlim(min(allTK)-1,max(allTK)+1) plt.ylim(min(allMK)-1,max(allMK)+1) plt.xlabel('Total keys required') plt.ylabel('Max keys required for a single portal') cbar = plt.colorbar() cbar.set_label('Optimization Weighting (lower=better)') plt.savefig(output_directory+'optimization.png') a = bestgraph """ with open(output_directory+output_file,'w') as fout: pickle.dump(a,fout) else: with open(input_file,'r') as fin: a = pickle.load(fin) # Optimize the plan to get shortest walking distance best_plan = None best_PP = None best_time = 1.e9 for foobar in xrange(args.attempts): if not args.quiet: tdiff = time.time() - start_time hrs = int(tdiff/3600.) mins = int((tdiff-3600.*hrs)/60.) secs = tdiff-3600.*hrs-60.*mins sys.stdout.write("\r[{0:20s}] {1}% ({2}/{3} iterations) : {4:02}h {5:02}m {6:05.2f}s".\ format('#'*(20*foobar/args.attempts), 100*foobar/args.attempts, foobar,args.attempts, hrs,mins,secs)) b = copy.deepcopy(a) maxfield.maxFields(b,allow_suboptimal=(not args.optimal)) # Attach to each edge a list of fields that it completes # catch no triangulation (bad portal file?) try: for t in b.triangulation: t.markEdgesWithFields() except AttributeError: print "Error: problem with bestgraph... no triangulation...?" agentOrder.improveEdgeOrder(b) PP = PlanPrinterMap.PlanPrinter(b,output_directory,nagents,useGoogle=useGoogle, api_key=api_key,color=color) totalTime = b.walktime+b.linktime+b.commtime if totalTime < best_time: best_plan = b best_PP = copy.deepcopy(PP) best_time = totalTime if not args.quiet: tdiff = time.time() - start_time hrs = int(tdiff/3600.) mins = int((tdiff-3600.*hrs)/60.) secs = tdiff-3600.*hrs-60.*mins sys.stdout.write("\r[{0:20s}] {1}% ({2}/{3} iterations) : {4:02}h {5:02}m {6:05.2f}s".\ format('#'*(20), 100,args.attempts,args.attempts, hrs,mins,secs)) print "" # generate plan details and map best_PP.keyPrep() best_PP.agentKeys() best_PP.planMap(useGoogle=useGoogle) best_PP.agentLinks() # These make step-by-step instructional images if not args.skipplot: best_PP.animate(useGoogle=useGoogle) best_PP.split3instruct(useGoogle=useGoogle) print "" print "" print "" print "Found best plan after {0} iterations.".format(args.attempts) totalTime = best_plan.walktime+best_plan.linktime+best_plan.commtime print "Total time: {0} minutes".format(int(totalTime/60. + 0.5)) print "Number of portals: {0}".format(best_PP.num_portals) print "Number of links: {0}".format(best_PP.num_links) print "Number of fields: {0}".format(best_PP.num_fields) portal_ap = (125*8 + 500 + 250)*best_PP.num_portals link_ap = 313 * best_PP.num_links field_ap = 1250 * best_PP.num_fields print "AP from portals capture: {0}".format(portal_ap) print "AP from link creation: {0}".format(link_ap) print "AP from field creation: {0}".format(field_ap) print "Total AP: {0}".format(portal_ap+link_ap+field_ap) tdiff = time.time() - start_time hrs = int(tdiff/3600.) mins = int((tdiff-3600.*hrs)/60.) secs = tdiff-3600.*hrs-60.*mins print "Runtime: {0:02}h {1:02}m {2:05.2f}s".format(hrs,mins,secs) plt.close('all')
def main(args): start_time = time.time() if args.log is not None: sys.stdout = open(args.log, 'w', 0) GREEN = '#3BF256' # Actual faction text colors in the app BLUE = '#2ABBFF' if args.res: color = BLUE else: color = GREEN # Use google? useGoogle = args.google api_key = args.api_key output_directory = args.output_dir # add ending separator if output_directory[-1] != os.sep: output_directory += os.sep # create directory if doesn't exist if not os.path.isdir(output_directory): os.mkdir(output_directory) output_file = args.output_file if output_file[-4:] != '.pkl': output_file += ".pkl" nagents = args.num_agents if nagents <= 0: print "Number of agents should be greater than zero" raise ValueError("Number of agents should be greater than zero") input_file = args.input_file if input_file[-3:] != 'pkl': # If the input file is a portal list, let's set things up a = nx.DiGraph() # network tool locs = [] # portal coordinates # each line should be name;intel_link;keys portals = pd.read_table(input_file, sep=';', comment='#', index_col=False, names=['name', 'link', 'keys', 'sbla'], dtype=str) portals = np.array(portals) portals = np.array([ portal for portal in portals if (isinstance(portal[0], basestring) and isinstance(portal[1], basestring)) ]) print "Found {0} portals in portal list.".format(len(portals)) intel_url = "https://www.ingress.com/intel?z=17&" # setup url for intel map ll_set = False pls = [] if len(portals) < 3: print "Error: Must have more than 2 portals!" raise ValueError("Error: Must have more than 2 portals!") if len(portals) > _MAX_PORTALS_: print "Error: Portal limit is {0}".format(_MAX_PORTALS_) raise ValueError( "Error: Portal limit is {0}".format(_MAX_PORTALS_)) for num, portal in enumerate(portals): if len(portal) < 3: print "Error! Portal ", portal[0], " has a formatting problem." raise ValueError("Error! Portal ", portal[0], " has a formatting problem.") # loop over columns. Four possibilities: # 0. First entry is always portal name # 1. contains "pll=" it is the Intel URL # 2. contains an intenger, it is the number of keys # 3. contains "sbla", it is an SBLA portal loc = None keys = 0 sbla = False for pind, pfoobar in enumerate(portal): if str(pfoobar) == 'nan': continue if pind == 0: # This is the name a.add_node(num) a.node[num]['name'] = pfoobar.strip() continue if 'pll=' in pfoobar: # this is the URL if loc is not None: print "Error! Already found URL for this portal: {0}".format( portal[0]) raise ValueError( "Error! Already found URL for this portal: {0}". format(portal[0])) coords = (pfoobar.strip().split('pll=')) if len(coords) < 2: print "Error! Portal ", portal[ 0], " has a formatting problem." raise ValueError("Error! Portal ", portal[0], " has a formatting problem.") coord_parts = coords[1].split(',') lat = int(float(coord_parts[0]) * 1.e6) lon = int(float(coord_parts[1]) * 1.e6) pls.append(coord_parts[0] + "," + coord_parts[1]) loc = np.array([lat, lon], dtype=float) if not ll_set: # use coordinates from first portal to center the map intel_url += "ll=" + coord_parts[ 0] + "," + coord_parts[1] + "&" ll_set = True continue try: # this is the number of keys keys = int(pfoobar.strip()) continue except ValueError: pass try: # this is SBLA sbla = pfoobar.strip() sbla = (sbla.lower() == 'sbla') continue except ValueError: pass # we should never get here unless there was a bad column print "Error: bad data value here:" print portal print pfoobar raise ValueError() if loc is None: print "Formatting problem: {0}".format(portal[0]) raise ValueError("Formatting problem: {0}".format(portal[0])) locs.append(loc) a.node[num]['keys'] = keys a.node[num]['sbla'] = sbla if sbla: print "{0} has SBLA".format(portal[0]) n = a.order() # number of nodes locs = np.array(locs, dtype=float) # Convert coords to radians, then to cartesian, then to # gnomonic projection locs = geometry.LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs, xyz) for i in xrange(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz[i] a.node[i]['xy'] = xy[i] # build portal list for intel_url intel_url += "pls=" json_output = [] for p in xrange(len(pls)): if p < len(pls) - 1: intel_url += pls[p] + "," + pls[p + 1] intel_url += "_" json_output.append({ "type": "polyline", "latLngs": [{ "lat": pls[p].split(',')[0], "lng": pls[p].split(',')[1] }, { "lat": pls[p + 1].split(',')[0], "lng": pls[p + 1].split(',')[1] }], "color": "#a24ac3" }) elif p == len(pls) - 1: intel_url += pls[p] + "," + pls[0] json_output.append({ "type": "polyline", "latLngs": [{ "lat": pls[p].split(',')[0], "lng": pls[p].split(',')[1] }, { "lat": pls[0].split(',')[0], "lng": pls[0].split(',')[1] }], "color": "#a24ac3" }) print intel_url print json.dumps(json_output, indent=4) # Below is remnants from "random optimization" technique """ # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single # portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf allTK = [] allMK = [] allWeights = [] sinceImprove = 0 while sinceImprove<EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print 'Randomization failure\nThe program may work if you try again. It is more likely to work if you remove some portals.' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK allTK.append(TK) allMK.append(MK) allWeights.append(weightedlack) if weightedlack < bestlack: sinceImprove = 0 print 'IMPROVEMENT:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print 'this time:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) if weightedlack <= 0: print 'KEY PERFECTION' bestlack = weightedlack bestTK = TK bestMK = MK break # if num agent keys is zero, this code isn't true... # if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): # print 'All keys used. Improvement impossible' # break print '%s tries since improvement'%sinceImprove if bestgraph == None: print 'EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!' print '' exit() print 'Choosing plan requiring %s additional keys, max of %s from single portal'%(bestTK,bestMK) plt.clf() plt.scatter(allTK,allMK,c=allWeights,marker='o') plt.xlim(min(allTK)-1,max(allTK)+1) plt.ylim(min(allMK)-1,max(allMK)+1) plt.xlabel('Total keys required') plt.ylabel('Max keys required for a single portal') cbar = plt.colorbar() cbar.set_label('Optimization Weighting (lower=better)') plt.savefig(output_directory+'optimization.png') a = bestgraph """ with open(output_directory + output_file, 'w') as fout: pickle.dump(a, fout) else: with open(input_file, 'r') as fin: a = pickle.load(fin) # Optimize the plan to get shortest walking distance best_plan = None best_PP = None best_time = 1.e9 for foobar in xrange(args.attempts): if not args.quiet: tdiff = time.time() - start_time hrs = int(tdiff / 3600.) mins = int((tdiff - 3600. * hrs) / 60.) secs = tdiff - 3600. * hrs - 60. * mins sys.stdout.write("\r[{0:20s}] {1}% ({2}/{3} iterations) : {4:02}h {5:02}m {6:05.2f}s".\ format('#'*(20*foobar/args.attempts), 100*foobar/args.attempts, foobar,args.attempts, hrs,mins,secs)) b = copy.deepcopy(a) maxfield.maxFields(b, allow_suboptimal=(not args.optimal)) # Attach to each edge a list of fields that it completes # catch no triangulation (bad portal file?) try: for t in b.triangulation: t.markEdgesWithFields() except AttributeError: print "Error: problem with bestgraph... no triangulation...?" agentOrder.improveEdgeOrder(b) PP = PlanPrinterMap.PlanPrinter(b, output_directory, nagents, useGoogle=useGoogle, api_key=api_key, color=color) totalTime = b.walktime + b.linktime + b.commtime if totalTime < best_time: best_plan = b best_PP = copy.deepcopy(PP) best_time = totalTime b = best_plan agentOrder.improveEdgeOrderMore(b) # Re-run to fix the animations and stars of edges that can be done early # (improveEdgeOrderMore may have modified the completion order) try: first = True for t in b.triangulation: t.markEdgesWithFields(clean=first) first = False except AttributeError: print "Error: problem with bestgraph... no triangulation...?" best_PP = PlanPrinterMap.PlanPrinter(b, output_directory, nagents, useGoogle=useGoogle, api_key=api_key, color=color) best_time = b.walktime + b.linktime + b.commtime if not args.quiet: tdiff = time.time() - start_time hrs = int(tdiff / 3600.) mins = int((tdiff - 3600. * hrs) / 60.) secs = tdiff - 3600. * hrs - 60. * mins sys.stdout.write("\r[{0:20s}] {1}% ({2}/{3} iterations) : {4:02}h {5:02}m {6:05.2f}s".\ format('#'*(20), 100,args.attempts,args.attempts, hrs,mins,secs)) print "" # generate plan details and map best_PP.keyPrep() best_PP.agentKeys() best_PP.planMap(useGoogle=useGoogle) best_PP.agentLinks() # These make step-by-step instructional images if not args.skipplot: best_PP.animate(useGoogle=useGoogle) best_PP.split3instruct(useGoogle=useGoogle) print "" print "" print "" print "Found best plan after {0} iterations.".format(args.attempts) totalTime = best_plan.walktime + best_plan.linktime + best_plan.commtime print "Total time: {0} minutes".format(int(totalTime / 60. + 0.5)) print "Number of portals: {0}".format(best_PP.num_portals) print "Number of links: {0}".format(best_PP.num_links) print "Number of fields: {0}".format(best_PP.num_fields) portal_ap = (125 * 8 + 500 + 250) * best_PP.num_portals link_ap = 313 * best_PP.num_links field_ap = 1250 * best_PP.num_fields print "AP from portals capture: {0}".format(portal_ap) print "AP from link creation: {0}".format(link_ap) print "AP from field creation: {0}".format(field_ap) print "Total AP: {0}".format(portal_ap + link_ap + field_ap) tdiff = time.time() - start_time hrs = int(tdiff / 3600.) mins = int((tdiff - 3600. * hrs) / 60.) secs = tdiff - 3600. * hrs - 60. * mins print "Runtime: {0:02}h {1:02}m {2:05.2f}s".format(hrs, mins, secs) plt.close('all')
def main(): args = docopt.docopt(__doc__) timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S") COLOR = GREEN if args['-g'] else BLUE nagents = int(args['-n']) if nagents <= 0: print 'Number of agents should be positive' exit() # We will take many samples in an attempt to reduce number of keys to farm # This is the number of samples to take since the last improvement EXTRA_SAMPLES = int(args['-s']) if EXTRA_SAMPLES not in range(1, 101): print 'Number of extra samples must be between 1 and 100' exit() input_file = args['<input_file>'] name, ext = os.path.splitext(os.path.basename(input_file)) try: os.makedirs(name) except OSError as exception: if exception.errno != errno.EEXIST: raise output_directory = name + os.sep output_file = name + '_' + timestamp + '.pkl' if ext != '.pkl': a = nx.DiGraph() np = geometry.np locs = [] # each line should be name,intel_link,keys with open(input_file) as fin: text, encoding = guess_bytes(fin.read()) rows = unicodecsv.reader(text.encode('utf-8').strip().split('\n'), encoding='utf-8') for i, row in enumerate(rows): a.add_node(i) a.node[i]['name'] = row[0] url = ','.join(row[1:4]).strip() if not url.startswith('http'): print 'Unable to parse input file. Did you forget to put quotes around a name containing a comma?' exit() coords = urlparse.parse_qs(urlparse.urlparse(url).query)['pll'][0] # this could have been done the quick and dirty way, but I chose this way. It just felt right coord_parts = coords.split(',') lat = int(float(coord_parts[0]) * 1.e6) lon = int(float(coord_parts[1]) * 1.e6) locs.append(np.array([lat, lon], dtype=int)) # why does this have to be a numpy array? if '.' in row[-1]: a.node[i]['keys'] = 0 else: a.node[i]['keys'] = int(row[-1]) n = a.order() # number of nodes if n > 65: print 'Limit of 65 portals may be optimized at once' exit() locs = np.array(locs, dtype=float) # This part assumes we're working with E6 latitude-longitude data locs = geometry.e6LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs,xyz) for i in xrange(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz [i] a.node[i]['xy' ] = xy [i] # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf allTK = [] allMK = [] allWeights = [] sinceImprove = 0 while sinceImprove < EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print 'Randomization failure\n\tThe program may work if you try again. It is more likely to work if you remove some portals.' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK allTK.append(TK) allMK.append(MK) allWeights.append(weightedlack) if weightedlack < bestlack: sinceImprove = 0 print 'IMPROVEMENT:\ttotal: {}\tmax: {}\tweighted: {}\t{} tries since improvement'.format(TK, MK, weightedlack, sinceImprove) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print 'this time:\ttotal: {}\tmax: {}\tweighted: {}\t{} tries since improvement'.format(TK, MK, weightedlack, sinceImprove) if weightedlack <= 0: print 'KEY PERFECTION' bestlack = weightedlack bestTK = TK bestMK = MK break # if num agent keys is zero, this code isn't true... # if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): # print 'All keys used. Improvement impossible' # break if bestgraph == None: print 'EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!' print '' exit() print 'Choosing plan requiring {} additional keys, max of {} from single portal'.format(bestTK, bestMK) plt.clf() plt.scatter(allTK,allMK,c=allWeights,marker='o') plt.xlim(min(allTK)-1,max(allTK)+1) plt.ylim(min(allMK)-1,max(allMK)+1) plt.xlabel('Total keys required') plt.ylabel('Max keys required for a single portal') cbar = plt.colorbar() cbar.set_label('Optimization Weighting (lower=better)') plt.savefig(output_directory+'optimization.png') a = bestgraph # remember: a = nx.DiGraph() # Attach to each edge a list of fields that it completes for t in a.triangulation: t.markEdgesWithFields() agentOrder.improveEdgeOrder(a) with open(output_directory+output_file,'w') as fout: pickle.dump(a, fout) else: with open(input_file,'r') as fin: a = pickle.load(fin) # agentOrder.improveEdgeOrder(a) # with open(output_directory+output_file,'w') as fout: # pickle.dump(a,fout) PP = PlanPrinterMap.PlanPrinter(a, output_directory, nagents, COLOR) PP.keyPrep() PP.agentKeys() PP.planMap() PP.agentLinks() # These make step-by-step instructional images PP.animate() PP.split3instruct() print "Number of portals: {0}".format(PP.num_portals) print "Number of links: {0}".format(PP.num_links) print "Number of fields: {0}".format(PP.num_fields) portal_ap = (125*8 + 500 + 250)*PP.num_portals link_ap = 313 * PP.num_links field_ap = 1250 * PP.num_fields print "AP from portals capture: {0}".format(portal_ap) print "AP from link creation: {0}".format(link_ap) print "AP from field creation: {0}".format(field_ap) print "Total AP: {0}".format(portal_ap+link_ap+field_ap)
def main(): args = docopt(__doc__) np = geometry.np #GREEN = 'g' #BLUE = 'b' GREEN = '#3BF256' # Actual faction text colors in the app BLUE = '#2ABBFF' #GREEN = (0.0 , 1.0 , 0.0 , 0.3) #BLUE = (0.0 , 0.0 , 1.0 , 0.3) COLOR = GREEN if args['-b']: COLOR = BLUE output_directory = '' if args['<output_directory>'] != None: output_directory = args['<output_directory>'] if output_directory[-1] != '/': output_directory += '/' output_file = 'lastPlan.pkl' if args['<output_file>'] != None: output_file = args['<output_file>'] if not output_file[-3:] == 'pkl': print 'WARNING: output file should end in "pkl" or you cannot use it as input later' nagents = int(args['-n']) if nagents <= 0: print 'Numer of agents should be positive' exit() input_file = args['<input_file>'] if input_file[-3:] != 'pkl': a = nx.DiGraph() locs = [] # ------------- URL ------------- # name ; lat , lng ; keys urlpat = re.compile('^([^;]*);.*ll=([-0-9\.]+),([-0-9\.]+)\s*;?\s*(\d+)?') # name ; lat ; lng ; keys cvspat = re.compile('^([^;]*);\s*([-0-9\.]+)\s*;\s*([-0-9\.]+)\s*;?\s*(\d+)?') i = 0 # each line should be id,name,lat,long,keys with open(input_file,'r') as fin: for line in fin: m = urlpat.match(line) if m == None: m = cvspat.match(line) if m == None: continue g = m.groups() # print g a.add_node(i) a.node[i]['name'] = g[0] locs.append( np.array([float(g[1]),float(g[2])] )) if g[3] == None: a.node[i]['keys'] = 0 else: a.node[i]['keys'] = int(g[3]) i += 1 n = a.order() # number of nodes locs = np.array(locs,dtype=float) # print locs # This part assumes we're working with decimal latitude-longitude data locs = geometry.LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs,xyz) for i in xrange(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz [i] a.node[i]['xy' ] = xy [i] maxfield.maxFields(a) ''' # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf sinceImprove = 0 while sinceImprove<EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print 'Randomization failure\nThe program may work if you try again. It is more likely to work if you remove some protals.' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK if weightedlack < bestlack: sinceImprove = 0 print 'IMPROVEMENT:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print 'this time:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) if weightedlack == 0: print 'KEY PERFECTION' bestlack = weightedlack bestTK = TK bestMK = MK break # if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): # print 'All keys used. Improvement impossible' # break # print '%s tries since improvement'%sinceImprove if bestgraph == None: print 'EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!' print '' exit() print 'Choosing plan requiring %s additional keys, max of %s from single portal'%(bestTK,bestMK) a = bestgraph ''' # Attach to each edge a list of fields that it completes for t in a.triangulation: t.markEdgesWithFields() agentOrder.improveEdgeOrder(a) with open(output_directory+output_file,'w') as fout: pickle.dump(a,fout) else: with open(input_file,'r') as fin: a = pickle.load(fin) # agentOrder.improveEdgeOrder(a) # with open(output_directory+output_file,'w') as fout: # pickle.dump(a,fout) PP = PlanPrinter.PlanPrinter(a,output_directory,nagents,COLOR) PP.keyPrep() PP.agentKeys() PP.planMap() PP.agentLinks()
# EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf sinceImprove = 0 while sinceImprove<EXTRA_SAMPLES: b = a.copy() if not maxfield.maxFields(b): print 'Failed maxfield (if this happens many times, this loop could be infinite. I''ll fix this sometime)' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK if weightedlack < bestlack: sinceImprove = 0
def main(): args = docopt(__doc__) # We will take many samples in an attempt to reduce number of keys to farm # This is the number of samples to take since the last improvement EXTRA_SAMPLES = 50 np = geometry.np #GREEN = 'g' #BLUE = 'b' GREEN = '#3BF256' # Actual faction text colors in the app BLUE = '#2ABBFF' #GREEN = (0.0 , 1.0 , 0.0 , 0.3) #BLUE = (0.0 , 0.0 , 1.0 , 0.3) COLOR = GREEN if args['-b']: COLOR = BLUE output_directory = '' if args['<output_directory>'] != None: output_directory = args['<output_directory>'] if output_directory[-1] != '/': output_directory += '/' output_file = 'lastPlan.pkl' if args['<output_file>'] != None: output_file = args['<output_file>'] if not output_file[-3:] == 'pkl': print 'WARNING: output file should end in "pkl" or you cannot use it as input later' nagents = int(args['-n']) if nagents < 0: print 'Number of agents should be positive' exit() EXTRA_SAMPLES = int(args['-s']) if EXTRA_SAMPLES < 0: print 'Number of extra samples should be positive' exit() elif EXTRA_SAMPLES > 100: print 'Extra samples may not be more than 100' exit() input_file = args['<input_file>'] if input_file[-3:] != 'pkl': a = nx.DiGraph() locs = [] i = 0 # each line should be name,intel_link,keys with open(input_file,'r') as fin: for line in fin: parts = line.split(';') if len(parts) < 2: break a.add_node(i) a.node[i]['name'] = parts[0].strip() coords = (parts[1].split('pll='))[1] coord_parts = coords.split(',') lat = int(float(coord_parts[0]) * 1.e6) lon = int(float(coord_parts[1]) * 1.e6) locs.append( np.array([lat,lon],dtype=int) ) if len(parts) < 3: a.node[i]['keys'] = 0 else: a.node[i]['keys'] = int(parts[3]) i += 1 if i > 65: print 'Limit of 65 portals may be optimized at once' exit() n = a.order() # number of nodes locs = np.array(locs,dtype=float) # This part assumes we're working with E6 latitude-longitude data locs = geometry.e6LLtoRads(locs) xyz = geometry.radstoxyz(locs) xy = geometry.gnomonicProj(locs,xyz) for i in xrange(n): a.node[i]['geo'] = locs[i] a.node[i]['xyz'] = xyz [i] a.node[i]['xy' ] = xy [i] # EXTRA_SAMPLES attempts to get graph with few missing keys # Try to minimuze TK + 2*MK where # TK is the total number of missing keys # MK is the maximum number of missing keys for any single portal bestgraph = None bestlack = np.inf bestTK = np.inf bestMK = np.inf allTK = [] allMK = [] allWeights = [] sinceImprove = 0 while sinceImprove<EXTRA_SAMPLES: b = a.copy() sinceImprove += 1 if not maxfield.maxFields(b): print 'Randomization failure\nThe program may work if you try again. It is more likely to work if you remove some protals.' continue TK = 0 MK = 0 for j in xrange(n): keylack = max(b.in_degree(j)-b.node[j]['keys'],0) TK += keylack if keylack > MK: MK = keylack weightedlack = TK+2*MK allTK.append(TK) allMK.append(MK) allWeights.append(weightedlack) if weightedlack < bestlack: sinceImprove = 0 print 'IMPROVEMENT:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) bestgraph = b bestlack = weightedlack bestTK = TK bestMK = MK else: print 'this time:\n\ttotal: %s\n\tmax: %s\n\tweighted: %s'%\ (TK,MK,weightedlack) if weightedlack <= 0: print 'KEY PERFECTION' bestlack = weightedlack bestTK = TK bestMK = MK break # if num agent keys is zero, this code isn't true... # if all([ b.node[i]['keys'] <= b.out_degree(i) for i in xrange(n) ]): # print 'All keys used. Improvement impossible' # break print '%s tries since improvement'%sinceImprove if bestgraph == None: print 'EXITING RANDOMIZATION LOOP WITHOUT SOLUTION!' print '' exit() print 'Choosing plan requiring %s additional keys, max of %s from single portal'%(bestTK,bestMK) plt.clf() plt.scatter(allTK,allMK,c=allWeights,marker='o') plt.xlim(min(allTK)-1,max(allTK)+1) plt.ylim(min(allMK)-1,max(allMK)+1) plt.xlabel('Total keys required') plt.ylabel('Max keys required for a single portal') cbar = plt.colorbar() cbar.set_label('Optimization Weighting (lower=better)') plt.savefig(output_directory+'optimization.png') a = bestgraph # Attach to each edge a list of fields that it completes for t in a.triangulation: t.markEdgesWithFields() agentOrder.improveEdgeOrder(a) with open(output_directory+output_file,'w') as fout: pickle.dump(a,fout) else: with open(input_file,'r') as fin: a = pickle.load(fin) # agentOrder.improveEdgeOrder(a) # with open(output_directory+output_file,'w') as fout: # pickle.dump(a,fout) PP = PlanPrinterMap.PlanPrinter(a,output_directory,nagents,COLOR) PP.keyPrep() PP.agentKeys() PP.planMap() PP.agentLinks() # These make step-by-step instructional images PP.animate() PP.split3instruct() print "Number of portals: {0}".format(PP.num_portals) print "Number of links: {0}".format(PP.num_links) print "Number of fields: {0}".format(PP.num_fields) portal_ap = (125*8 + 500 + 250)*PP.num_portals link_ap = 313 * PP.num_links field_ap = 1250 * PP.num_fields print "AP from portals capture: {0}".format(portal_ap) print "AP from link creation: {0}".format(link_ap) print "AP from field creation: {0}".format(field_ap) print "Total AP: {0}".format(portal_ap+link_ap+field_ap)