def run_ants(self, include_timing=False): ''' Run N ants and update the pheromone matrix ''' # Check if we are doing the initial run w/ no timing info. cheapness = None if include_timing: cheapness = self.routemap.cheapness else: cheapness = self.routemap.tangible_cheapness # Transition matrix is pheromone for each edge times inverse cost # between each edge transition_matrix = cheapness*self.pheromones # Route initializer # Start at origin route_init = [0] # All tbd points excepting the origin route_init.extend( [-1]*(self.num_dest-1) ) # Return to origin at end route_init.append(0) for ant in range(self.num_ants): # Setup mask mask = np.array([False]*self.num_dest, dtype=bool) # Start at origin current_location = 0 # Initialize route route = np.array(route_init, dtype=int) # Mark the origin as visited in the mask mask[0] = True # Index of route position route_index = 1 while route_index < self.num_dest: # Get costs for traveling from current location to others # note that only costs for edges to unvisted nodes are included. next_location = op.select_edge_weighted( np.ma.MaskedArray( transition_matrix[current_location, :], mask=mask)) # Update the route and mask route[route_index] = next_location mask[next_location] = True # Move to the new location current_location = next_location route_index += 1 # When done, update the pheromone matrix for this routes cost cost = self.routemap.total_tangible_cost_for_route(route) if include_timing: cost += self.routemap.total_satisfaction_costs route_tuple = tuple(route) if tuple(route) not in self.routes_and_results: self.routes_and_results[route_tuple] = (cost, route) # Update pheromone matrix for start, end in op.consecutive_pairs(route): self.pheromones[start, end] += 1.0/cost
def sim_arrival_times(self, route, start_time=0): output = [0]*len(route) current_time = start_time # Departure from origin output[0] = current_time for start, end in op.consecutive_pairs(route): # Sim delivery time @ starjt current_time += self.destinations[end].throw_delivery_time() # Travel from start to end current_time += self.time_for_edge(start, end) output[end] = current_time return output
def total_satisfaction_costs(self, route, iterations=None, cost_per_sad_customer=None): ''' Simulate the route and determine average satisfaction ''' total_satisfaction = 0. for iteration in range(iterations): # Pull a random start time from the base current_time = self.destinations[route[0]].time_pref.random() for start, end in op.consecutive_pairs(route): # Time to move from start to end current_time = self.time_for_edge(start, end) # Get our current customer customer = self.destinations[end] # Find if customer at end was satisfied total_satisfaction += \ customer.satisfaction_probability(current_time) # Throw a random delivery time for this customer current_time += customer.throw_delivery_time() # Normalize satisfaction normalization = iterations*1.0 return (1-(total_satisfaction / normalization))*cost_per_sad_customer