def getAgentOrder(a,nagents,orderedEdges): ''' returns visits visits[i] = j means agent j should make edge i ALSO creates time attributes in a: Time that must be spent just walking a.walktime Time it takes to communicate completion of a sequence of links a.commtime Time spent navigating linking menu a.linktime ''' geo = np.array([ a.node[i]['geo'] for i in xrange(a.order())]) d = geometry.sphereDist(geo,geo) # print d order = [e[0] for e in orderedEdges] # Reduce sequences of links made from same portal to single entry condensed , mult = condenseOrder(order) link2agent , times = orderedTSP.getVisits(d,condensed,nagents) # print # Expand links made from same portal to original count link2agent = expandOrder(link2agent,mult) # If agents communicate sequential completions all at once, we avoid waiting for multiple messages # To find out how many communications will be sent, we count the number of same-agent link sequences condensed , mult = condenseOrder(link2agent) numCOMMs = len(condensed) # Time that must be spent just walking a.walktime = times[-1]/WALKSPEED # Waiting for link completion messages to be sent a.commtime = numCOMMs*COMMTIME # Time spent navigating linking menu a.linktime = a.size()*LINKTIME movements = [None]*nagents for i in xrange(len(link2agent)): try: movements[link2agent[i]].append(i) except: movements[link2agent[i]] = [i] return movements
def getAgentOrder(a, nagents, orderedEdges): ''' returns visits visits[i] = j means agent j should make edge i ALSO creates time attributes in a: Time that must be spent just walking a.walktime Time it takes to communicate completion of a sequence of links a.commtime Time spent navigating linking menu a.linktime ''' geo = np.array([a.node[i]['geo'] for i in xrange(a.order())]) d = geometry.sphereDist(geo, geo) # print d order = [e[0] for e in orderedEdges] # Reduce sequences of links made from same portal to single entry condensed, mult = condenseOrder(order) link2agent, times = orderedTSP.getVisits(d, condensed, nagents) # print # Expand links made from same portal to original count link2agent = expandOrder(link2agent, mult) # If agents communicate sequential completions all at once, we avoid waiting for multiple messages # To find out how many communications will be sent, we count the number of same-agent link sequences condensed, mult = condenseOrder(link2agent) numCOMMs = len(condensed) # Time that must be spent just walking a.walktime = times[-1] / WALKSPEED # Waiting for link completion messages to be sent a.commtime = numCOMMs * COMMTIME # Time spent navigating linking menu a.linktime = a.size() * LINKTIME movements = [None] * nagents for i in xrange(len(link2agent)): try: movements[link2agent[i]].append(i) except: movements[link2agent[i]] = [i] return movements
def getAgentOrder(a,nagents,orderedEdges): ''' returns visits visits[i] = j means agent j should make edge i ''' geo = np.array([ a.node[i]['geo'] for i in xrange(a.order())]) d = geometry.sphereDist(geo,geo) # print d order = [e[0] for e in orderedEdges] link2agent , times = orderedTSP.getVisits(d,order,nagents) print 'Plan can be completed in time it takes one agent to walk',times[-1],'meters' movements = [None]*nagents # I realize that switching between these formats all the time is stupid # Consistency hasn't been my highest priority for i in xrange(len(link2agent)): try: movements[link2agent[i]].append(i) except: movements[link2agent[i]] = [i] return movements
def getGreedyAgentOrder_DONT_USE_THIS_FUNCTION(a,nagents,orderedEdges): ''' a is a digraph node have 'pos' property with location nagents is the number of agents orderedEdges maps i to the ith edge to be made this greedily minimizes wait time (equating distance with time) the player who has the most time to spare is assigned the link ''' m = len(orderedEdges) # movements[i][j] will be the index (in orderedEdges) of the jth edge that agent i should make movements = dict([ (i,[]) for i in range(nagents) ]) # The ammount of time that has elapsed curtime = 0. # Last time at which the agents made links lastActTime = np.zeros(nagents) # agent locations agentpos = np.empty([nagents,2]) # Find initial deployments: starts[i] is the agent who starts at node i starts = {} assigning = 0 e=0 for e in xrange(m): p = orderedEdges[e][0] if not p in starts: # Nobody is at this link's head yet movements[assigning].append(e) starts[p] = assigning agentpos[assigning] = a.node[p]['geo'] assigning += 1 if assigning >= nagents: break else: # the agent who is already at this link's head should make it movements[starts[p]].append(e) # No agents have actually moved yet # continue from startup loop for e in xrange(e+1,m): p,q = orderedEdges[e] ppos = a.node[p]['geo'] dists = geometry.sphereDist(agentpos,ppos) radii = curtime-lastActTime # how far could they have moved waits = dists-radii # how long will the team wait if this agent moves waits[waits<0] = 0 # no time travel mover = np.argmin(waits) movements[mover].append(e) agentpos[mover] = ppos curtime += waits[mover] + linkTime lastActTime[mover] = curtime return movements
def getGreedyAgentOrder_DONT_USE_THIS_FUNCTION(a, nagents, orderedEdges): ''' a is a digraph node have 'pos' property with location nagents is the number of agents orderedEdges maps i to the ith edge to be made this greedily minimizes wait time (equating distance with time) the player who has the most time to spare is assigned the link ''' m = len(orderedEdges) # movements[i][j] will be the index (in orderedEdges) of the jth edge that agent i should make movements = dict([(i, []) for i in range(nagents)]) # The ammount of time that has elapsed curtime = 0. # Last time at which the agents made links lastActTime = np.zeros(nagents) # agent locations agentpos = np.empty([nagents, 2]) # Find initial deployments: starts[i] is the agent who starts at node i starts = {} assigning = 0 e = 0 for e in xrange(m): p = orderedEdges[e][0] if not p in starts: # Nobody is at this link's head yet movements[assigning].append(e) starts[p] = assigning agentpos[assigning] = a.node[p]['geo'] assigning += 1 if assigning >= nagents: break else: # the agent who is already at this link's head should make it movements[starts[p]].append(e) # No agents have actually moved yet # continue from startup loop for e in xrange(e + 1, m): p, q = orderedEdges[e] ppos = a.node[p]['geo'] dists = geometry.sphereDist(agentpos, ppos) radii = curtime - lastActTime # how far could they have moved waits = dists - radii # how long will the team wait if this agent moves waits[waits < 0] = 0 # no time travel mover = np.argmin(waits) movements[mover].append(e) agentpos[mover] = ppos curtime += waits[mover] + linkTime lastActTime[mover] = curtime return movements
def improveEdgeOrderMore(a): ''' A greedy algorithm to reduce the path length. Moves edges earlier or later, if they can be moved (dependencies are done in the proper order) and the move reduces the total length of the path. The algorithm tries to move 1 to 5 edges at the same time as a block to improve upon certain types of local optima. ''' m = a.size() # If link i is e then orderedEdges[i]=e orderedEdges = [-1] * m geo = np.array([a.node[i]['geo'] for i in xrange(a.order())]) d = geometry.sphereDist(geo, geo) def pathLength(d, edges): startps = [edges[i][0] for i in xrange(len(edges))] return np.sum(d[startps[:-1], startps[1:]]) def dependsOn(subjects, objects): ''' Returns True, if an edge inside 'objects' should be made before one (or more) of the edges inside 'subjects' ''' for p, q in subjects: depends = a.edge[p][q]['depends'] for u, v in objects: if depends.count(( u, v, )) > 0 or depends.count(u) > 0: return True return False def possiblePlaces(j, block): ''' A generator returning the possible places of the given block of edges within the complete edge sequence. The current position (j) is not returned. ''' pos = j # smaller index means made earlier while pos > 0 and not dependsOn(block, [orderedEdges[pos - 1]]): pos -= 1 yield pos bsize = len(block) pos = j + bsize n = len(orderedEdges) + 1 # bigger index means made later while pos < n - 1 and not dependsOn([orderedEdges[pos]], block): pos += 1 yield pos for p, q in a.edges_iter(): orderedEdges[a.edge[p][q]['order']] = (p, q) origLength = pathLength(d, orderedEdges) bestLength = origLength cont = True while cont: cont = False for j in xrange(m): best = j bestPath = orderedEdges currentLength = bestLength # max block size is 5 (6-1); chosen arbitrarily for block in xrange(1, 6): moving = orderedEdges[j:j + block] # if the first and last link in the block are from the same portal # and the link before or after the block is also from that portal, # moving the block will not improve the path length, and thus there # is no point in trying if moving[0][0] == moving[-1][0] and ( (j > 0 and moving[0][0] == orderedEdges[j - 1][0]) or (j + block < m and moving[0][0] == orderedEdges[j + block][0])): continue removedEdgesLengthBase = 0 addedEdgesLengthBase = 0 if j > 0: removedEdgesLengthBase += d[orderedEdges[j - 1][0], orderedEdges[j][0]] if j + block < m: removedEdgesLengthBase += d[orderedEdges[j + block - 1][0], orderedEdges[j + block][0]] if j > 0 and j + block < m: addedEdgesLengthBase += d[orderedEdges[j - 1][0], orderedEdges[j + block][0]] for possible in possiblePlaces(j, moving): addedEdgesLength = addedEdgesLengthBase removedEdgesLength = removedEdgesLengthBase if possible > 0: addedEdgesLength += d[orderedEdges[possible - 1][0], moving[0][0]] if possible < m: removedEdgesLength += d[orderedEdges[possible - 1][0], orderedEdges[possible][0]] if possible < m: addedEdgesLength += d[moving[-1][0], orderedEdges[possible][0]] length = currentLength - removedEdgesLength + addedEdgesLength if bestLength - length <= 1e-10: continue #print("Improved by %f meters in index %d (from %d, block %d)" % (bestLength-length, possible, best, block)) if possible < j: # Move the links to be at an earlier index bestPath = orderedEdges[ :possible] +\ moving +\ orderedEdges[possible :j] +\ orderedEdges[j+block: ] else: # Move to a later position bestPath = orderedEdges[ :j] +\ orderedEdges[j+block: possible] +\ moving +\ orderedEdges[possible :] #assert abs(length - pathLength(d,bestPath)) < 1e-10 best = possible bestLength = length if best != j: #print("New order (%d -> %d): %s" % (j, best, bestPath)) orderedEdges = bestPath cont = True length = pathLength(d, orderedEdges) print #print("Length reduction: original = %d, improved = %d, change = %d meters" % (origLength, length, length-origLength)) for i in xrange(m): p, q = orderedEdges[i] a.edge[p][q]['order'] = i
def agentLinks(self): # Total distance traveled by each agent agentdists = np.zeros(self.nagents) # Total experience for each agent agentexps = np.zeros(self.nagents,dtype=int) for i in range(self.nagents): movie = self.movements[i] # first portal in first link curpos = self.a.node[self.orderedEdges[movie[0]][0]]['geo'] for e in movie[1:]: p,q = self.orderedEdges[e] newpos = self.a.node[p]['geo'] dist = geometry.sphereDist(curpos,newpos) agentdists[i] += dist curpos = newpos agentexps[i] += 313 + 1250*len(self.a.edge[p][q]['fields']) # Different formatting for the agent's own links plainStr = '{0:4d}{1:1s} {2: 5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' hilitStr = '{0:4d}{1:1s} {2:_>5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' csv_file = open(self.outputDir+'links_for_agents.csv','w') for agent in range(self.nagents): with open(self.outputDir+'links_for_agent_%s_of_%s.txt'\ %(agent+1,self.nagents),'w') as fout: fout.write('Complete link schedule issued to agent %s of %s\n'\ %(agent+1,self.nagents)) totalTime = self.a.walktime+self.a.linktime+self.a.commtime fout.write('\nTotal time estimate: %s minutes\n\n'%int(totalTime/60+.5)) fout.write('Agent distance: %s m\n'%int(agentdists[agent])) fout.write('Agent experience: %s AP\n'%(agentexps[agent])) fout.write('\nLinks marked with * can be made EARLY\n') fout.write('\nLink Agent Map# Link Origin\n') fout.write(' Link Destination\n') fout.write('-----------------------------------\n') # 1234112345612345 name csv_file.write('Link, Agent, MapNumOrigin, OriginName, MapNumDestination, DestinationName\n') for i in xrange(self.m): p,q = self.orderedEdges[i] linkagent = self.link2agent[i] # Put a star by links that can be completed early since they complete no fields numfields = len(self.a.edge[p][q]['fields']) if numfields == 0: star = '*' # print '%s %s completes nothing'%(p,q) else: star = '' # print '%s %s completes'%(p,q) # for t in self.a.edge[p][q]['fields']: # print ' ',t if linkagent != agent: fout.write(plainStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) else: fout.write(hilitStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) csv_file.write("{0}{1}, {2}, {3}, {4}, {5}, {6}\n".\ format(i,star,linkagent+1, self.nslabel[p],self.names[p], self.nslabel[q],self.names[q])) csv_file.close()
def agentLinks(self): # Total distance traveled by each agent agentdists = np.zeros(self.nagents) # Total number of links, fields for each agent agentlinkcount = [0] * self.nagents agentfieldcount = [0] * self.nagents totalAP = 0 totalDist = 0 for i in range(self.nagents): movie = self.movements[i] # first portal in first link curpos = self.a.node[self.orderedEdges[movie[0]][0]]['geo'] for e in movie[1:]: p, q = self.orderedEdges[e] newpos = self.a.node[p]['geo'] dist = geometry.sphereDist(curpos, newpos) # print 'Agent %s walks %s to %s'%(i,dist,self.nslabel[p]) agentdists[i] += dist curpos = newpos agentlinkcount[i] += 1 agentfieldcount[i] += len(self.a.edge[p][q]['fields']) self.num_fields += len(self.a.edge[p][q]['fields']) totalAP += 313 totalAP += 1250 * len(self.a.edge[p][q]['fields']) totalDist += dist # Different formatting for the agent's own links plainStr = '{0:4d}{1:1s} {2: 5d}{3:5d} {4:s} -> {5:d} {6:s}\n' hilitStr = '{0:4d}{1:1s} {2:_>5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' totalTime = self.a.walktime + self.a.linktime + self.a.commtime csv_file = open(self.outputDir + 'links_for_agents.csv', 'w') csv_file.write( 'Link, Agent, MapNumOrigin, OriginName, MapNumDestination, DestinationName\n' ) for agent in range(self.nagents): with open(self.outputDir+'links_for_agent_%s_of_%s.txt'\ %(agent+1,self.nagents),'w') as fout: fout.write('Complete link schedule issued to agent %s of %s %s\n\n'\ %(agent+1,self.nagents,time.strftime('%Y-%m-%d %H:%M:%S %Z'))) fout.write('\nLinks marked with * can be made EARLY\n') fout.write('----------- PLAN DATA ------------\n') fout.write('Minutes: %s minutes\n' % int(totalTime / 60 + .5)) fout.write('Total Distance: %s meter\n' % int(totalDist)) fout.write('Total AP: %s\n' % totalAP) fout.write('AP per Agent per minute: %0.2f AP/Agent/min\n' % float(totalAP / self.nagents / (totalTime / 60 + .5))) fout.write('AP per Agent per meter: %0.2f AP/Agent/m\n' % float(totalAP / self.nagents / totalDist)) agentAP = 313 * agentlinkcount[agent] + 1250 * agentfieldcount[ agent] fout.write('----------- AGENT DATA -----------\n') fout.write('Distance traveled: %s m (%s %%)\n' % (int(agentdists[agent]), int(100 * agentdists[agent] / totalDist))) fout.write('Links made: %s\n' % (agentlinkcount[agent])) fout.write('Fields completed: %s\n' % (agentfieldcount[agent])) fout.write('Total experience: %s AP (%s %%)\n' % (agentAP, int(100 * agentAP / totalAP))) fout.write('----------------------------------\n') fout.write('Link Agent Map# Link Origin\n') fout.write(' Link Destination\n') fout.write('----------------------------------\n') # 1234112345612345 name last_link_from_other_agent = 0 for i in xrange(self.m): p, q = self.orderedEdges[i] linkagent = self.link2agent[i] # Put a star by links that can be completed early since they complete no fields numfields = len(self.a.edge[p][q]['fields']) if numfields == 0: star = '*' # print '%s %s completes nothing'%(p,q) else: star = '' # print '%s %s completes'%(p,q) # for t in self.a.edge[p][q]['fields']: # print ' ',t if linkagent != agent: fout.write(plainStr.format(\ i+1,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) last_link_from_other_agent = 1 else: if last_link_from_other_agent: fout.write('\n') last_link_from_other_agent = 0 fout.write(hilitStr.format(\ i+1,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) csv_file.write("{0}{1}, {2}, {3}, {4}, {5}, {6}\n".\ format(i,star,linkagent+1, self.nslabel[p],self.names[p], self.nslabel[q],self.names[q])) csv_file.close()
def agentLinks(self): # Total distance traveled by each agent agentdists = np.zeros(self.nagents) # Total experience for each agent agentexps = np.zeros(self.nagents, dtype=int) agentfields = np.zeros(self.nagents, dtype=int) for i in range(self.nagents): movie = self.movements[i] # first portal in first link curpos = self.a.node[self.orderedEdges[movie[0]][0]]['geo'] for e in movie[1:]: p, q = self.orderedEdges[e] newpos = self.a.node[p]['geo'] dist = geometry.sphereDist(curpos, newpos) agentdists[i] += dist curpos = newpos agentexps[i] += 313 + 1250 * len(self.a.edge[p][q]['fields']) agentfields[i] += len(self.a.edge[p][q]['fields']) # Different formatting for the agent's own links plainStr = '{0:4d}{1:1s} {2: 5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' hilitStr = '{0:4d}{1:1s} {2:_>5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' for agent in range(self.nagents): with open(self.outputDir+'links_for_agent_%s_of_%s.txt'\ %(agent+1,self.nagents),'w') as fout: fout.write('Complete link schedule issued to agent %s of %s\n'\ %(agent+1,self.nagents)) totalTime = self.a.walktime + self.a.linktime + self.a.commtime fout.write('\nTotal time estimate: %s minutes\n\n' % int(totalTime / 60 + .5)) fout.write('Agent distance: %s m\n' % int(agentdists[agent])) fout.write('Agent experience: %s AP\n' % (agentexps[agent])) print 'Agent fields: %s\n' % (agentfields[agent]) print 'Agent experience: %s AP\n' % (agentexps[agent]) fout.write('\nLinks marked with * can be made EARLY\n') fout.write('\nLink Agent Map# Link Origin\n') fout.write(' Link Destination\n') fout.write('-----------------------------------\n') # 1234112345612345 name seqLinks = [] earlyLinks = [] for i in xrange(self.m): p, q = self.orderedEdges[i] linkagent = self.link2agent[i] # Put a star by links that can be completed early since they complete no fields numfields = len(self.a.edge[p][q]['fields']) if numfields == 0: star = '*' # print '%s %s completes nothing'%(p,q) else: star = '' # print '%s %s completes'%(p,q) # for t in self.a.edge[p][q]['fields']: # print ' ',t # print star, i, self.names[p], "-->", self.names[q] if (star == '*'): earlyLinks.append([i, p, q]) else: seqLinks.append([i, self.names[p], self.names[q]]) if linkagent != agent: fout.write(plainStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) else: fout.write(hilitStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) earlyPointsToOpt = [] for i, point in enumerate(earlyLinks): p, q = point[1], point[2] x, y = self.xy[p][0], self.xy[p][1] earlyPointsToOpt.append([i, float(x), float(y)]) # print earlyPointsToOpt print 'Agent distance: %s m\n' % int(agentdists[agent]) costs, earlyPointsOptimized = tsp.simAnneal( earlyPointsToOpt) # NJA XXX for point in earlyPointsOptimized: i, p, q = earlyLinks[point[0]] print '*', i, self.names[p], "-->", self.names[q] for link in seqLinks: print ' ', link[0], link[1], "-->", link[2]
def agentLinks(self): # Total distance traveled by each agent agentdists = np.zeros(self.nagents) # Total number of links, fields for each agent agentlinkcount = [0]*self.nagents agentfieldcount = [0]*self.nagents totalAP = 0 totalDist = 0 for i in range(self.nagents): movie = self.movements[i] # first portal in first link curpos = self.a.node[self.orderedEdges[movie[0]][0]]['geo'] for e in movie[1:]: p,q = self.orderedEdges[e] newpos = self.a.node[p]['geo'] dist = geometry.sphereDist(curpos,newpos) # print 'Agent %s walks %s to %s'%(i,dist,self.nslabel[p]) agentdists[i] += dist curpos = newpos agentlinkcount[i] += 1 agentfieldcount[i] += len(self.a.edge[p][q]['fields']) totalAP += 313 totalAP += 1250 * len(self.a.edge[p][q]['fields']) totalDist += dist # Different formatting for the agent's own links # plainStr = '{0:4d}{1:1s} {2: 5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' plainStr = '{0:4d}{1:1s} {2: 5d}{3:5d} {4:s} -> {5:d} {6:s}\n' hilitStr = '{0:4d}{1:1s} {2:_>5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' totalTime = self.a.walktime+self.a.linktime+self.a.commtime for agent in range(self.nagents): with open(self.outputDir+'links_for_agent_%s_of_%s.txt'\ %(agent+1,self.nagents),'w') as fout: fout.write('Complete link schedule issued to agent %s of %s %s\n\n'\ %(agent+1,self.nagents,time.strftime('%Y-%m-%d %H:%M:%S %Z'))) fout.write('\nLinks marked with * can be made EARLY\n') fout.write('----------- PLAN DATA ------------\n') fout.write('Minutes: %s minutes\n'%int(totalTime/60+.5)) fout.write('Total Distance: %s meter\n'%int(totalDist)) fout.write('Total AP: %s\n'%totalAP) fout.write('AP per Agent per minute: %0.2f AP/Agent/min\n'%float(totalAP/self.nagents/(totalTime/60+.5))) fout.write('AP per Agent per meter: %0.2f AP/Agent/m\n'%float(totalAP/self.nagents/totalDist)) agentAP = 313*agentlinkcount[agent] + 1250*agentfieldcount[agent] fout.write('----------- AGENT DATA -----------\n') fout.write('Distance traveled: %s m (%s %%)\n'%(int(agentdists[agent]),int(100*agentdists[agent]/totalDist))) fout.write('Links made: %s\n'%(agentlinkcount[agent])) fout.write('Fields completed: %s\n'%(agentfieldcount[agent])) fout.write('Total experience: %s AP (%s %%)\n'%(agentAP,int(100*agentAP/totalAP))) fout.write('----------------------------------\n') fout.write('Link Agent Map# Link Origin\n') fout.write(' Link Destination\n') fout.write('----------------------------------\n') # 1234112345612345 name last_link_from_other_agent = 0 for i in xrange(self.m): p,q = self.orderedEdges[i] linkagent = self.link2agent[i] # Put a star by links that can be completed early since they complete no fields numfields = len(self.a.edge[p][q]['fields']) if numfields == 0: star = '*' # print '%s %s completes nothing'%(p,q) else: star = '' # print '%s %s completes'%(p,q) # for t in self.a.edge[p][q]['fields']: # print ' ',t if linkagent != agent: fout.write(plainStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) last_link_from_other_agent = 1 else: if last_link_from_other_agent: fout.write('\n') last_link_from_other_agent = 0 fout.write(hilitStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ ))
def agentLinks(self): # Total distance traveled by each agent agentdists = np.zeros(self.nagents) # Total experience for each agent agentexps = np.zeros(self.nagents, dtype=int) for i in range(self.nagents): movie = self.movements[i] # first portal in first link curpos = self.a.node[self.orderedEdges[movie[0]][0]]['geo'] for e in movie[1:]: p, q = self.orderedEdges[e] newpos = self.a.node[p]['geo'] dist = geometry.sphereDist(curpos, newpos) agentdists[i] += dist curpos = newpos agentexps[i] += 313 + 1250 * len(self.a.edge[p][q]['fields']) # Different formatting for the agent's own links plainStr = '{0:4d}{1:1s} {2: 5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' hilitStr = '{0:4d}{1:1s} {2:_>5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' csv_file = open(self.outputDir + 'links_for_agents.csv', 'w') for agent in range(self.nagents): with open(self.outputDir+'links_for_agent_%s_of_%s.txt'\ %(agent+1,self.nagents),'w') as fout: fout.write('Complete link schedule issued to agent %s of %s\n'\ %(agent+1,self.nagents)) totalTime = self.a.walktime + self.a.linktime + self.a.commtime fout.write('\nTotal time estimate: %s minutes\n\n' % int(totalTime / 60 + .5)) fout.write('Agent distance: %s m\n' % int(agentdists[agent])) fout.write('Agent experience: %s AP\n' % (agentexps[agent])) fout.write('\nLinks marked with * can be made EARLY\n') fout.write('\nLink Agent Map# Link Origin\n') fout.write(' Link Destination\n') fout.write('-----------------------------------\n') # 1234112345612345 name csv_file.write( 'Link, Agent, MapNumOrigin, OriginName, MapNumDestination, DestinationName\n' ) for i in xrange(self.m): p, q = self.orderedEdges[i] linkagent = self.link2agent[i] # Put a star by links that can be completed early since they complete no fields numfields = len(self.a.edge[p][q]['fields']) if numfields == 0: star = '*' # print '%s %s completes nothing'%(p,q) else: star = '' # print '%s %s completes'%(p,q) # for t in self.a.edge[p][q]['fields']: # print ' ',t if linkagent != agent: fout.write(plainStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) else: fout.write(hilitStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) csv_file.write("{0}{1}, {2}, {3}, {4}, {5}, {6}\n".\ format(i,star,linkagent+1, self.nslabel[p],self.names[p], self.nslabel[q],self.names[q])) csv_file.close()
def agentLinks(self): # Total distance traveled by each agent agentdists = np.zeros(self.nagents) # Total experience for each agent agentexps = np.zeros(self.nagents,dtype=int) for i in range(self.nagents): movie = self.movements[i] # first portal in first link curpos = self.a.node[self.orderedEdges[movie[0]][0]]['geo'] for e in movie[1:]: p,q = self.orderedEdges[e] newpos = self.a.node[p]['geo'] dist = geometry.sphereDist(curpos,newpos) agentdists[i] += dist curpos = newpos agentexps[i] += 313 + 1250*len(self.a.edge[p][q]['fields']) # Different formatting for the agent's own links plainStr = '{:4d}{:1s} {: 5d}{:5d} {:s}\n {:4d} {:s}\n\n' hilitStr = '{:4d}{:1s} {:_>5d}{:5d} {:s}\n {:4d} {:s}\n\n' for agent in range(self.nagents): with open(self.outputDir+'links_for_agent_%s_of_%s.txt'\ %(agent+1,self.nagents),'w') as fout: fout.write('Complete link schedule issued to agent %s of %s\n'\ %(agent+1,self.nagents)) fout.write('Total distance : %s m\n'%int(agentdists[agent])) fout.write('Total experience: %s AP\n'%(agentexps[agent])) fout.write('Links marked with * can be made EARLY\n') fout.write('\nLink Agent Map# Link Origin\n') fout.write(' Link Destination\n') # 1234112345612345 name for i in xrange(self.m): p,q = self.orderedEdges[i] linkagent = self.link2agent[i] # Put a star by links that can be completed early since they complete no fields numfields = len(self.a.edge[p][q]['fields']) if numfields == 0: star = '*' # print '%s %s completes nothing'%(p,q) else: star = '' # print '%s %s completes'%(p,q) # for t in self.a.edge[p][q]['fields']: # print ' ',t if linkagent != agent: fout.write(plainStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) else: fout.write(hilitStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ ))
def agentLinks(self): # Total distance traveled by each agent agentdists = np.zeros(self.nagents) # Total experience for each agent agentexps = np.zeros(self.nagents,dtype=int) agentfields = np.zeros(self.nagents,dtype=int) for i in range(self.nagents): movie = self.movements[i] # first portal in first link curpos = self.a.node[self.orderedEdges[movie[0]][0]]['geo'] for e in movie[1:]: p,q = self.orderedEdges[e] newpos = self.a.node[p]['geo'] dist = geometry.sphereDist(curpos,newpos) agentdists[i] += dist curpos = newpos agentexps[i] += 313 + 1250*len(self.a.edge[p][q]['fields']) agentfields[i] += len(self.a.edge[p][q]['fields']) # Different formatting for the agent's own links plainStr = '{0:4d}{1:1s} {2: 5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' hilitStr = '{0:4d}{1:1s} {2:_>5d}{3:5d} {4:s}\n {5:4d} {6:s}\n\n' for agent in range(self.nagents): with open(self.outputDir+'links_for_agent_%s_of_%s.txt'\ %(agent+1,self.nagents),'w') as fout: fout.write('Complete link schedule issued to agent %s of %s\n'\ %(agent+1,self.nagents)) totalTime = self.a.walktime+self.a.linktime+self.a.commtime fout.write('\nTotal time estimate: %s minutes\n\n'%int(totalTime/60+.5)) fout.write('Agent distance: %s m\n'%int(agentdists[agent])) fout.write('Agent experience: %s AP\n'%(agentexps[agent])) print 'Agent fields: %s\n'%(agentfields[agent]) print 'Agent experience: %s AP\n'%(agentexps[agent]) fout.write('\nLinks marked with * can be made EARLY\n') fout.write('\nLink Agent Map# Link Origin\n') fout.write(' Link Destination\n') fout.write('-----------------------------------\n') # 1234112345612345 name seqLinks = [] earlyLinks = [] for i in xrange(self.m): p,q = self.orderedEdges[i] linkagent = self.link2agent[i] # Put a star by links that can be completed early since they complete no fields numfields = len(self.a.edge[p][q]['fields']) if numfields == 0: star = '*' # print '%s %s completes nothing'%(p,q) else: star = '' # print '%s %s completes'%(p,q) # for t in self.a.edge[p][q]['fields']: # print ' ',t # print star, i, self.names[p], "-->", self.names[q] if(star == '*'): earlyLinks.append( [i, p, q] ) else: seqLinks.append( [i, self.names[p], self.names[q]] ) if linkagent != agent: fout.write(plainStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) else: fout.write(hilitStr.format(\ i,\ star,\ linkagent+1,\ self.nslabel[p],\ self.names[p],\ self.nslabel[q],\ self.names[q]\ )) earlyPointsToOpt = [] for i,point in enumerate(earlyLinks): p,q = point[1], point[2] x,y = self.xy[p][0], self.xy[p][1] earlyPointsToOpt.append( [i, float(x), float(y)] ) # print earlyPointsToOpt print 'Agent distance: %s m\n'%int(agentdists[agent]) costs, earlyPointsOptimized = tsp.simAnneal(earlyPointsToOpt) # NJA XXX for point in earlyPointsOptimized: i,p,q = earlyLinks[point[0]] print '*', i, self.names[p], "-->", self.names[q] for link in seqLinks: print ' ', link[0], link[1], "-->", link[2]
def improveEdgeOrderMore(a): ''' A greedy algorithm to reduce the path length. Moves edges earlier or later, if they can be moved (dependencies are done in the proper order) and the move reduces the total length of the path. The algorithm tries to move 1 to 5 edges at the same time as a block to improve upon certain types of local optima. ''' m = a.size() # If link i is e then orderedEdges[i]=e orderedEdges = [-1]*m geo = np.array([ a.node[i]['geo'] for i in xrange(a.order())]) d = geometry.sphereDist(geo,geo) def pathLength(d, edges): startps = [edges[i][0] for i in xrange(len(edges))] return np.sum(d[startps[:-1], startps[1:]]) def dependsOn(subjects, objects): ''' Returns True, if an edge inside 'objects' should be made before one (or more) of the edges inside 'subjects' ''' for p,q in subjects: depends = a.edge[p][q]['depends'] for u,v in objects: if depends.count((u,v,)) + depends.count(u) > 0: return True return False def possiblePlaces(j, block): ''' A generator returning the possible places of the given block of edges within the complete edge sequence. The current position (j) is not returned. ''' pos = j # smaller index means made earlier while pos > 0 and not dependsOn(block, [orderedEdges[pos-1]]): pos -= 1 yield pos pos = j bsize = len(block) n = len(orderedEdges) - bsize + 1 # bigger index means made later while pos < n-1 and not dependsOn([orderedEdges[pos+bsize]], block): pos += 1 yield pos for p,q in a.edges_iter(): orderedEdges[a.edge[p][q]['order']] = (p,q) origLength = pathLength(d, orderedEdges) bestLength = origLength cont = True while cont: cont = False for j in xrange(m): best = j bestPath = orderedEdges # max block size is 5 (6-1); chosen arbitrarily for block in xrange(1, 6): moving = orderedEdges[j:j+block] # if the first and last link in the block are from the same portal # and the link before or after the block is also from that portal, # moving the block will not improve the path length, and thus there # is no point in trying if moving[0][0] == moving[-1][0] and ( (j > 0 and moving[0][0] == orderedEdges[j-1][0]) or (j + block < m and moving[0][0] == orderedEdges[j+block][0])): filter = [] # skips the loop below else: filter = True # do the loop for possible in filter and possiblePlaces(j, moving): if possible < j: # Move the links to be at an earlier index path = orderedEdges[ :possible] +\ moving +\ orderedEdges[possible :j] +\ orderedEdges[j+block: ] else: # Move to a later position path = orderedEdges[ :j] +\ orderedEdges[j+block: possible+block] +\ moving +\ orderedEdges[possible+block :] length = pathLength(d,path) if bestLength - length > 1e-10: #print("Improved by %f meters in index %d (from %d, block %d)" % (bestLength-length, possible, best, block)) best = possible bestLength = length bestPath = path if best != j: #print("New order (%d -> %d): %s" % (j, best, bestPath)) orderedEdges = bestPath cont = True length = pathLength(d, orderedEdges) print #print("Length reduction: original = %d, improved = %d, change = %d meters" % (origLength, length, length-origLength)) for i in xrange(m): p,q = orderedEdges[i] a.edge[p][q]['order'] = i