route optimization with precedences between pairs of nodes - or-tools

For my routing application I have multiple pairs of nodes which must be visited. The order the nodes in each pair is not important, but both nodes in each pair must be visited after each other. Also, I have a max_travel_distance constraint per vehicle and it is not required to visit all nodes if no optimal solution exist. Meaning that if one node in a pair needs to be dropped, both nodes in the pair must be dropped.
For instance I have three pairs: [A,B], [C,D], [E,F], two valid solutions for two vehicles could be:
(if all node pair can be covered)
1) 0->A->B->C->D->0
2) 0->F->E->0
or
(if only [A,B] is within max_travel_distance)
1) 0->A->B->0
2) 0->0
From the pickup and deliveries example I see how I can make sure that both nodes in a pair always is included in the solution. The problem is that I dont see how I can enforce a constraint so that the two nodes from the same pair always is visited directly after each other, and that the order does not matter (A->B and B->A are both ok)
import math
from ortools.constraint_solver import pywrapcp
from ortools.constraint_solver import routing_enums_pb2
def calc_dmat(pairs, depot = [0,0]):
# Distance matrix
ncol = len(pairs)*2
nodes = [depot] + [p for pair in Pairs for p in pair]
dmat = [[math.dist(c,r) for c in nodes] for r in nodes]
return dmat
# Nodes and pairs
A = [1,1] # Coordinate
B = [1,5]
C = [3,1]
D = [3,8]
E = [6,3]
F = [6,19]
Pairs = [
[A,B],
[C,D],
[E,F]
]
data = {}
data["distance_matrix"] = calc_dmat(Pairs)
data["depot"] = 0
data["num_vehicles"]=2
data["pickups_deliveries"] = [
[1,2],
[3,4],
[5,6]
]
def print_solution(data, manager, routing, solution):
if solution is None:
print("No solution")
return
print(f'Objective: {solution.ObjectiveValue()}')
# Display dropped nodes.
dropped_nodes = 'Dropped nodes:'
for node in range(routing.Size()):
if routing.IsStart(node) or routing.IsEnd(node):
continue
if solution.Value(routing.NextVar(node)) == node:
dropped_nodes += ' {}'.format(manager.IndexToNode(node))
print(dropped_nodes)
max_route_distance = 0
max_route_time = 0
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
route_distance = 0
route_time = 0
while not routing.IsEnd(index):
plan_output += ' {} -> '.format(manager.IndexToNode(index))
previous_index = index
index = solution.Value(routing.NextVar(index))
route_distance += routing.GetArcCostForVehicle(
previous_index, index, vehicle_id)
plan_output += '{}\n'.format(manager.IndexToNode(index))
plan_output += 'Distance of the route: {}m\n'.format(route_distance)
print(plan_output)
max_route_distance = max(route_distance, max_route_distance)
max_route_time = max(route_time, max_route_time)
print('Maximum of the route distances: {}m'.format(max_route_distance))
print('Maximum of the route time: {}m'.format(max_route_time))
manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
data['num_vehicles'], data['depot'])
routing = pywrapcp.RoutingModel(manager)
def distance_callback(from_index, to_index):
from_node = manager.IndexToNode(from_index)
to_node = manager.IndexToNode(to_index)
return data["distance_matrix"][from_node][to_node]
transit_callback_index = routing.RegisterTransitCallback(distance_callback)
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
# Add Distance constraint.
dimension_name = 'Distance'
routing.AddDimension(
transit_callback_index,
0,
18,
True,
dimension_name)
distance_dimension = routing.GetDimensionOrDie(dimension_name)
# Define Transportation Requests.
for request in data['pickups_deliveries']:
pickup_index = manager.NodeToIndex(request[0])
delivery_index = manager.NodeToIndex(request[1])
routing.AddPickupAndDelivery(pickup_index, delivery_index)
routing.solver().Add(
routing.VehicleVar(pickup_index) == routing.VehicleVar(
delivery_index))
routing.solver().Add(
distance_dimension.CumulVar(pickup_index) <=
distance_dimension.CumulVar(delivery_index))
# Omit some nodes
for node in range(1,len(data["distance_matrix"])):
routing.AddDisjunction([manager.NodeToIndex(node)], 13)
# Setting first solution heuristic.
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION)
# Solve the problem.
solution = routing.SolveWithParameters(search_parameters)
# Print solution on console.
print_solution(data, manager, routing, solution)
Output:
*Objective: 25
Dropped nodes:
Route for vehicle 0:
0 -> 3 -> 1 -> 2 -> 4 -> 0
Distance of the route: 9m
Route for vehicle 1:
0 -> 5 -> 6 -> 0
Distance of the route: 16m
Maximum of the route distances: 16m
Maximum of the route time: 0m*
I don't see how I can add a constraint making sure both nodes from the same node is picked successively and independently of the order. A solution to this would be highly appreciated.

Set a dimension representing rank (transit is always 1)
Link the vehicle variables of the two nodes in a pair to be equal
Add each one in a disjunction of size 1 (maybe both in a unique disjunction of size 2)
Add a precedence on the cumul variables of the 2 elements of a pair

Here is another approach.
Create 2 fake nodes 'a->b' and 'b->a', do not create the nodes a and b.
Distance from any node c to 'a->b' is distance c to a. Distance from 'a->b' to any node d is distance from b to d.
Same thing for b->a.
Add 'a->b' and 'b->a' in a disjunction.
And solve.

Related

OR-tools VRP solver returning one job per vehicle

I am using Google OR-Tools in python to solve a capacitated VRP with pickup/delivery. In many cases the solver works well and returns reasonable solutions, but we have found that for some data sets the solver will always return one job per truck regardless of the time involved for the route.
I have the model set up as follows:
My initial vehicle count is equal to the number of jobs in the data-set, and we allow OR-Tools to automatically minimize the truck count.
Each job's pickup location has a demand of 1 and each job's dropoff location has a demand of -1, to enforce delivery immediately after pickup.
We set the maximum drive time per vehicle to 8 hours.
Then, each job has an associated quantity attached for pickup, and we separate this job into multiple deliveries based on a truck's capacity. For instance, if a job requires 60 tons delivered, we represent that as three jobs at 20 tons each (the maximum a vehicle is allowed to carry on an interstate in the U.S)
Now, we have a simple data set with a pickup location at: 698 Longtown Rd, Columbia, SC and a dropoff location at: 121 Chappell Creek Rd Hopkins, SC. This is a drive time of 32 minutes, or a total trip time of 64 minutes. This job has an associated quantity of 60 tons, which will require 3 truck loads.
The results we receive from or-tools shows one load per truck, and this result does not change regardless of how long we allow the solver to run. The optimal solution would allow one truck to complete all loads, as this is still drastically under the 8 hour drive time limit.
Here is my code:
import json
import math
import traceback
import urllib
import redis
import requests
import boto3
from signal import signal, SIGINT, SIGTERM
from ortools.constraint_solver import pywrapcp, routing_enums_pb2
url = 'https://test-api.truckit.com/api/2/signin'
api_data = {"password": "", "username": ""}
response = requests.post(url, json=api_data)
api_data = response.json()
def build_auth_header(token):
header = {'Authorization': f'Token {token}'}
return header
class SignalHandler:
def __init__(self):
self.received_signal = False
signal(SIGINT, self._signal_handler)
signal(SIGTERM, self._signal_handler)
def _signal_handler(self, signal, frame):
print(f"handling signal {signal}, exiting gracefully")
self.received_signal = True
sqs = boto3.resource("sqs")
queue = sqs.get_queue_by_name(QueueName="")
redisClient = redis.Redis(host='', port=6379,
password='')
def create_distance_matrix(data):
addresses = data["addresses"]
API_key = data["API_key"]
origin_addresses = []
dest_addresses = addresses
distance_matrix = []
responses = {}
responses['destination_addresses'] = []
responses['origin_addresses'] = []
responses['rows'] = []
# Send q requests, returning max_rows rows per request.
for i in range(0, len(addresses)):
origin_addresses.clear()
origin_addresses.append(addresses[i])
for j in range(0, len(addresses), 25):
dest_addresses_request = addresses[j:j + 25]
response = send_request(origin_addresses, dest_addresses_request, API_key)
responses['origin_addresses'] = response['origin_addresses']
for destination_address in response['destination_addresses']:
responses['destination_addresses'].append(destination_address)
for row in response['rows']:
if len(responses['rows']) == 0:
responses['rows'].append(row)
else:
for element in row['elements']:
responses['rows'][0]['elements'].append(element)
distance_matrix += build_distance_matrix(responses)
responses['origin_addresses'].clear()
responses['destination_addresses'].clear()
responses['rows'].clear()
return distance_matrix
def send_request(origin_addresses, dest_addresses, API_key):
""" Build and send request for the given origin and destination addresses."""
def build_address_str(addresses):
# Build a pipe-separated string of addresses
address_str = ''
for i in range(len(addresses) - 1):
address_str += addresses[i] + '|'
address_str += addresses[-1]
return address_str
request = 'https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial'
origin_address_str = build_address_str(origin_addresses)
dest_address_str = build_address_str(dest_addresses)
request = request + '&origins=' + origin_address_str + '&destinations=' + \
dest_address_str + '&key=' + API_key
jsonResult = urllib.request.urlopen(request).read()
response = json.loads(jsonResult)
return response
def build_distance_matrix(response):
distance_matrix = []
for row in response['rows']:
row_list = [row['elements'][j]['duration']['value'] for j in range(len(row['elements']))]
distance_matrix.append(row_list)
return distance_matrix
def process_message(message_body):
print(f"processing message: {message_body}")
data = json.loads(message_body)
data_matrix = {}
data_matrix['problem_id'] = data['problemId']
data_matrix["addresses"] = []
data_matrix["pickups_deliveries"] = []
data_matrix["demands"] = []
data_matrix["jobOrderIDs"] = []
depot_address = str(data["depot"]["latitude"]) + "," + str(data["depot"]["longitude"])
data_matrix["jobOrderIDs"].append(0)
data_matrix["addresses"].append(depot_address)
hash_key = data["hashKey"]
for location in data["locationList"]:
pick_lat = location["PickupLatitude"]
pick_long = location["PickupLongitude"]
drop_lat = location["DropoffLatitude"]
drop_long = location["DropoffLongitude"]
jobOrderId = location["jobOrderID"]
demand = math.ceil(float(int(location["totalQuantity"]) / 20))
for i in range(0, demand):
data_matrix["addresses"].append(str(pick_lat) + ',' + str(pick_long))
data_matrix["addresses"].append(str(drop_lat) + ',' + str(drop_long))
data_matrix["jobOrderIDs"].append(str(jobOrderId))
data_matrix["jobOrderIDs"].append(str(jobOrderId))
data_matrix["demands"].append(0)
for i in range(1, len(data_matrix["addresses"]) - 1, 2):
data_matrix["pickups_deliveries"].append([i, i + 1])
data_matrix["demands"].append(1)
data_matrix["demands"].append(-1)
data_matrix["num_vehicles"] = int(len(data_matrix["addresses"]) / 2)
data_matrix["vehicle_capacities"] = []
for i in range(0, data_matrix["num_vehicles"]):
data_matrix["vehicle_capacities"].append(1)
data_matrix["depot"] = 0
data_matrix["API_key"] = ''
data_matrix["distance_matrix"] = create_distance_matrix(data_matrix)
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(len(data_matrix['distance_matrix']),
data_matrix['num_vehicles'], data_matrix['depot'])
# Create Routing Model.
routing = pywrapcp.RoutingModel(manager)
# Define cost of each arc.
def distance_callback(from_index, to_index):
"""Returns the manhattan distance between the two nodes."""
# Convert from routing variable Index to distance matrix NodeIndex.
from_node = manager.IndexToNode(from_index)
to_node = manager.IndexToNode(to_index)
return data_matrix['distance_matrix'][from_node][to_node]*1000
transit_callback_index = routing.RegisterTransitCallback(distance_callback)
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
# Add Distance constraint.
dimension_name = 'Duration'
routing.AddDimension(
transit_callback_index,
0, # no slack
28800*1000, # vehicle maximum travel hours
True, # start cumul to zero
dimension_name)
distance_dimension = routing.GetDimensionOrDie(dimension_name)
distance_dimension.SetGlobalSpanCostCoefficient(100)
def demand_callback(from_index):
"""Returns the demand of the node."""
# Convert from routing variable Index to demands NodeIndex.
from_node = manager.IndexToNode(from_index)
return data_matrix['demands'][from_node]
demand_callback_index = routing.RegisterUnaryTransitCallback(
demand_callback)
routing.AddDimensionWithVehicleCapacity(
demand_callback_index,
0, # null capacity slack
data_matrix['vehicle_capacities'], # vehicle maximum capacities
True, # start cumul to zero
'Capacity')
# Define Transportation Requests.
for request in data_matrix['pickups_deliveries']:
pickup_index = manager.NodeToIndex(request[0])
delivery_index = manager.NodeToIndex(request[1])
routing.AddPickupAndDelivery(pickup_index, delivery_index)
routing.solver().Add(
routing.VehicleVar(pickup_index) == routing.VehicleVar(
delivery_index))
routing.solver().Add(
distance_dimension.CumulVar(pickup_index) <=
distance_dimension.CumulVar(delivery_index))
# Setting first solution heuristic.
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.local_search_metaheuristic = (
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
search_parameters.time_limit.seconds = 1200
search_parameters.log_search = True
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC)
search_parameters.use_full_propagation = True
# Solve the problem.
solution = routing.SolveWithParameters(search_parameters)
if solution:
solution_dict = {}
for vehicle_id in range(data_matrix['num_vehicles']):
index = routing.Start(vehicle_id)
plan_output = ''
route_distance = 0
route_load = 0
while not routing.IsEnd(index):
node_index = manager.IndexToNode(index)
plan_output += '{0},'.format(data_matrix['jobOrderIDs'][node_index])
previous_index = index
index = solution.Value(routing.NextVar(index))
plan_output += '{0},'.format(data_matrix['jobOrderIDs'][manager.IndexToNode(index)])
plan_output = plan_output[:-1]
plan_words = plan_output.split(",")
plan_output = ''
for i in range(len(plan_words)):
if (i % 2 == 0):
plan_output += plan_words[i] + ","
plan_output = plan_output[:-1]
plan_output += ",0"
if plan_output != 0 and plan_output != str(0) and plan_output != str('0,0'):
print(plan_output)
solution_dict[vehicle_id] = plan_output
# trucks_url = 'https://test-api.truckit.com/api/2/trucks'
trucks_url = 'https://test-api.truckit.com/api/2/job-orders/smart-dispatch/' + str(data_matrix['problem_id'])
head = build_auth_header(api_data["authToken"])
status = {}
ride_list = []
dummy_location_dict = {}
dummy_id_dict = {}
dummy_id_dict["id"] = 0
dummy_id_dict["name"] = ""
dummy_location_dict["location"] = dummy_id_dict
dummy_location_dict["timestamp"] = 0
ride_list.append(dummy_location_dict)
redisClient.hset(hash_key, "solution", json.dumps(solution_dict))
redisClient.hset(hash_key, "ride_list", json.dumps(ride_list))
json_data = {"status": "completed"}
api_response = requests.post(trucks_url, headers=head, json=json_data)
print_solution(data_matrix, manager, routing, solution)
def print_solution(data, manager, routing, solution):
"""Prints solution on console."""
print(f'Objective: {solution.ObjectiveValue()}')
total_distance = 0
total_load = 0
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
route_distance = 0
route_load = 0
while not routing.IsEnd(index):
node_index = manager.IndexToNode(index)
plan_output += ' {0} -> '.format(node_index)
previous_index = index
index = solution.Value(routing.NextVar(index))
try:
distance = data['distance_matrix'][previous_index][index]
route_distance += distance
except:
distance = distance
plan_output += ' {0}\n'.format(manager.IndexToNode(index))
plan_output += 'Time of the route: {} hours\n'.format(str(float(route_distance / (60 * 60))))
print(plan_output)
total_distance += route_distance
print('Total distance of all routes: {}m'.format(total_distance))
if __name__ == "__main__":
signal_handler = SignalHandler()
while not signal_handler.received_signal:
messages = queue.receive_messages(
MaxNumberOfMessages=1,
WaitTimeSeconds=1
)
for message in messages:
try:
process_message(message.body)
message.delete()
except Exception as e:
print(f"exception while processing message: {repr(e)}")
traceback.print_exc()
continue
message.delete()
IF anyone has any suggestions as to what the problem may be, your help is greatly appreciated.

Google OR-Tools: VRP with time windows - solution doesn't account for transit time

While trying to solve a VRP with time windows (based on the tutorial), the solver does not seem to take transit time into account. Instead, it seems to assume you can jump instantaneously between nodes. Why aren't the transit and loading/unloading times in time_dimension being applied?
Route for vehicle 6:
Node A: Time(36000,36000) ->
Node B: Time(36000,36000) ->
Node C: Time(36000,36000) ->
Node D: Time(36000,36000) ->
Node A: Time(36000,36000)
Cost of the route: $811.84
Timing of route: 10:0:0 - 10:0:0
Duration on-duty: 0hr, 0min, 0sec
I have verified that data['time_matrix'] is not all zeros. Below is the bulk of the code for context:
# Create and register a transit time callback.
def transit_time_callback(from_index, to_index):
"""Returns the travel time only between the two nodes."""
# Convert from routing variable Index to time matrix NodeIndex.
from_node = manager.IndexToNode(from_index)
to_node = manager.IndexToNode(to_index)
return data['time_matrix'][from_node][to_node]
# Create and register a time callback.
def time_callback(from_index, to_index):
"""Returns the travel and dock time between the two nodes."""
# Convert from routing variable Index to time matrix NodeIndex.
transit_time = transit_time_callback(from_index, to_index)
if to_node in data['pickups']:
dock_time = data['load_time'][to_node]
else:
dock_time = data['unload_time'][to_node]
return transit_time + dock_time
time_callback_index = routing.RegisterTransitCallback(time_callback)
# Add time windows constraint.
routing.AddDimension(
time_callback_index,
4 * MIN_PER_HR * SEC_PER_MIN, # allow waiting time
24 * MIN_PER_HR * SEC_PER_MIN, # maximum time per vehicle
False, # Don't force start cumul to zero.
'Time')
time_dimension = routing.GetDimensionOrDie('Time')
# Add time window constraints for each location.
for location_idx, time_window in enumerate(data['time_windows']):
index = manager.NodeToIndex(location_idx)
time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
# Limit max on-duty time for each vehicle
for vehicle_id in range(data['num_vehicles']):
routing.solver().Add(
time_dimension.CumulVar(routing.End(vehicle_id)) - time_dimension.CumulVar(routing.Start(vehicle_id)) <= MAX_TIME_ON_DUTY)
# Minimize on-duty duration.
for i in range(data['num_vehicles']):
routing.AddVariableMaximizedByFinalizer(
time_dimension.CumulVar(routing.Start(i)))
routing.AddVariableMinimizedByFinalizer(
time_dimension.CumulVar(routing.End(i)))
# Set cost
routing.SetArcCostEvaluatorOfAllVehicles(time_callback_index)
# Solve the problem
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
solution = routing.SolveWithParameters(search_parameters)

How can I generate 3d integer coordinates in order of distance from an origin

I want to generate a sequence of coordinates in order of distance from the origin. The sequence will obviously be infinite so just generating them all and sorting by distance will not work for me.
For those points that are the same distance I don't care about the order.
For example, here's some points, with their distance from the origin up to two steps away.
# d² = 0
(0,0,0)
# d² = 1
(0,0,-1)
(0,-1,0)
(-1,0,0)
(1,0,0)
(0,1,0)
(0,0,1)
# d² = 2
(0,-1,-1)
(-1,0,-1)
(1,0,-1)
(0,1,-1)
(-1,-1,0)
(1,-1,0)
(-1,1,0)
(1,1,0)
(0,-1,1)
(-1,0,1)
(1,0,1)
(0,1,1)
# d² = 3
(-1,-1,-1)
(1,-1,-1)
(-1,1,-1)
(1,1,-1)
(-1,-1,1)
(1,-1,1)
(-1,1,1)
(1,1,1)
# d² = 4
(0,0,-2)
(0,-2,0)
(-2,0,0)
(2,0,0)
(0,2,0)
(0,0,2)
# d² = 5
(0,-1,-2)
(-1,0,-2)
(1,0,-2)
(0,1,-2)
(0,-2,-1)
(-2,0,-1)
(2,0,-1)
(0,2,-1)
(-1,-2,0)
(1,-2,0)
(-2,-1,0)
(2,-1,0)
(-2,1,0)
(2,1,0)
(-1,2,0)
(1,2,0)
(0,-2,1)
(-2,0,1)
(2,0,1)
(0,2,1)
(0,-1,2)
(-1,0,2)
(1,0,2)
(0,1,2)
# d² = 6
(-1,-1,-2)
(1,-1,-2)
(-1,1,-2)
(1,1,-2)
(-1,-2,-1)
(1,-2,-1)
(-2,-1,-1)
(2,-1,-1)
(-2,1,-1)
(2,1,-1)
(-1,2,-1)
(1,2,-1)
(-1,-2,1)
(1,-2,1)
(-2,-1,1)
(2,-1,1)
(-2,1,1)
(2,1,1)
(-1,2,1)
(1,2,1)
(-1,-1,2)
(1,-1,2)
(-1,1,2)
(1,1,2)
# d² = 8
(0,-2,-2)
(-2,0,-2)
(2,0,-2)
(0,2,-2)
(-2,-2,0)
(2,-2,0)
(-2,2,0)
(2,2,0)
(0,-2,2)
(-2,0,2)
(2,0,2)
(0,2,2)
# d² = 9
(-1,-2,-2)
(1,-2,-2)
(-2,-1,-2)
(2,-1,-2)
(-2,1,-2)
(2,1,-2)
(-1,2,-2)
(1,2,-2)
(-2,-2,-1)
(2,-2,-1)
(-2,2,-1)
(2,2,-1)
(-2,-2,1)
(2,-2,1)
(-2,2,1)
(2,2,1)
(-1,-2,2)
(1,-2,2)
(-2,-1,2)
(2,-1,2)
(-2,1,2)
(2,1,2)
(-1,2,2)
(1,2,2)
# d² = 12
(-2,-2,-2)
(2,-2,-2)
(-2,2,-2)
(2,2,-2)
(-2,-2,2)
(2,-2,2)
(-2,2,2)
(2,2,2)
Starting from a solution aaa, then aab, then abc, you can retrieve all other "permutations" like aba, baa, -a-a-b, and so on. So you can keep a < b < c, positive numbers.
Geometrically : one eighth triangle on a globe. For a circle x²+y² one would iterate in a quarter over x and let y be retrieved from r² - x². Happens here to given an a.
Unfortunately the coding is too much to me for answering on a sunny Sunday.
(= hard enough).
Schematically in pseudo-code:
int distance = -1;
int a;
int b;
int c;
PermutationIterator perm = ...
Point next() {
if (perm.atEnd()) { // Initially true.
perm.nextDistance();
++distance;
a = distance;
b = a;
c = a;
// Will return Point(a, a, a);
}
return perm.nextPerm();
}

I have 10 nodes .. each node has known number of transceivers .. I want to know How can I obtain all possible connections between nodes ? using MATLAB

I have 10 nodes .. each node has known number of transceivers as indicated in this vector:
[8 3 3 3 3 3 2 1 1 1]
where: 8 is the number of transceivers at the 1st node, 3 is the number of transceivers at the 2nd node and so on ..
Each transceiver can only receive from one source at a time .. it is required that all transceivers must be in use simultaneously .. it is permitted for the same node to use more than one transceiver to transmit to another node that has enough transceivers to receive with .. it is not possible for a single transceiver to be considered to be transmitting to multiple transceivers ..
I want to know How can I obtain all possible connections between nodes and each obtained connection matrix identify the number of transceivers used between the connected nodes ?
I don't know how to do this in Matlab.
With Minizinc, I found the following solution (slightly massaged with Microsoft Word):
Note that I used node number 0..9 rather than 1..10 to compact the matrix text.
There is a huge number of possible solutions. This is just one of them.
The Minizinc script:
include "globals.mzn";
set of int: Transceivers = 1..28;
set of int: Nodes = 1..10;
array[Transceivers] of Nodes: node = [1,1,1,1,1,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,8,9,10];
array[Transceivers] of Nodes: seq = [1,2,3,4,5,6,7,8,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,1,1,1];
array[Transceivers] of var Transceivers: aTo;
array[Nodes, Nodes] of var Transceivers: connections;
% Each transceiver can only receive from one source at a time
constraint all_different([aTo[t] | t in Transceivers]);
% transceivers have to connect to other nodes rather than to their own node
constraint
forall(t in Transceivers)
(node[aTo[t]] != node[t]);
% no more than 1 connection between any pair of nodes
constraint
forall(i in Nodes, j in Nodes where j > i)
(sum([bool2int((node[t] == i) /\ (node[aTo[t]] == j)) | t in Transceivers]) < 2);
solve satisfy;
output [" "] ++ [ show(node[i]-1) ++ "." ++ show(seq[i]) ++ " | " | i in Transceivers] ++
[ if j == 1 then ("\n" ++ show(node[i]-1) ++ "." ++ show(seq[i]) ++ ": ") else "" endif ++
if fix(aTo[i]) == j then " x | " else " | " endif
| i in Transceivers, j in Transceivers ];

stress centrality in social network

i got the error of this code which is:
path[index][4] += 1
IndexError: list index out of range
why this happened?how can i remove this error ?
Code:
def stress_centrality(g):
stress = defaultdict(int)
for a in nx.nodes_iter(g):
for b in nx.nodes_iter(g):
if a==b:
continue
pred = nx.predecessor(G,b) # for unweighted graphs
#pred, distance = nx.dijkstra_predecessor_and_distance(g,b) # for weighted graphs
if a not in pred:
return []
path = [[a,0]]
path_length = 1
index = 0
while index >= 0:
n,i = path[index]
if n == b:
for vertex in list(map(lambda x:x[0], path[:index+1]))[1:-1]:
stress[vertex] += 1
if len(pred[n]) >i:
index += 1
if index == path_length:
path.append([pred[n][i],0])
path_length += 1
else:
path[index] = [pred[n][i],0]
else:
index -= 1
if index >= 0:
path[index][4] += 1
return stress
Without the data it's hard to give you anything more than an indicative answer.
This line
path[index][4] += 1
assumes there are 5 elements in path[index] but there are fewer than that. It seems to me that your code only assigns or appends to path lists of length 2. As in
path = [[a,0]]
path.append([pred[n][i],0])
path[index] = [pred[n][i],0]
So it's hard to see how accessing the 5th element of one of those lists could ever be correct.
This is a complete guess, but I think you might have meant
path[index][1] += 4