Example #1
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 = 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()
Example #2
0
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))
Example #3
0
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')
Example #4
0
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)
Example #5
0
            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
Example #6
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)