Created on Fri Feb 18 11:22:33 2022 @author: mesa

In [16]:
import numpy as np
from supplychainmodelhelper import graphoperations as go
import pandas as pd
from supplychainmodelhelper.drawer import Drawer
    # creating the graph
prod = ['eggs','milk']
act = ['Producer','Consumer']
loc = [
        'Portugal',
        'Spain',
        'France',
        'Italy',
        'Germany',
        'Montenegro',
        'others'
]
     
myNW = go.createGraph(
        listOfActors=act,
        listOfLocations=loc,
        listOfProducts=prod)
    
# Creating Distance matrix
myData = {
    loc[0]: [1, 625, 1737, 2509, 2781, 3351,4000],
    loc[1]: [625, 1, 1277, 1965, 2320, 2804,4000],
    loc[2]: [1737, 1277, 1, 1420, 1054, 2038,4000],
    loc[3]: [2509, 1965, 1420, 1, 1505, 740,4000],
    loc[4]: [2781, 2320, 1054, 1505, 1, 1636,4000],
    loc[5]: [3351, 2804, 2038, 740, 1636, 1,4000],
    loc[6]: [4000,4000,4000,4000,4000,4000,1]
}
    
myDF = pd.DataFrame(myData,index=loc)

# supply and demand    
sendingProd = [[12588339,44688368,48464470,33153139,24304433,2300,9204611],#eggs
                   [75752927,121886945,490834291,3933048,497278336,138,0]]#milk
   
receivingProd = [[19101284,91333314,48818138,957046,12195878,0,0],#eggs
                 [70146856,121623784,95268102,761020054,104160029,14602,37452258]]#milk


myTDs = []
    
allFlows = np.ndarray((7,7,2,5))

# creating list of node IDs of participants
for run,p in enumerate(prod):
    senderIDs = go.getListOfNodeIDs(
        myNW,
        actors=['Producer'],
        products=[p]
    )
    receiverIDs = go.getListOfNodeIDs(
        myNW,
        actors=['Consumer'],
        products=[p]
    )
    
    # creating edgeIDs for adding 'distance' to graph
    allcombIDs1, allcombIDs2 = go.getAllCombinations(
        senderIDs,
        receiverIDs,
        order='1st'
    )

    myEdges4Graph = go.getEdgeID(myNW, allcombIDs1, allcombIDs2)
        
    didItWork3 = go.addAttr2Edges(
        myNW,
        myEdges4Graph,
        myDF.values.flatten(),
        attr='distance'
    )
    
    go.addAttr2ExistingNodes(myNW,senderIDs,'output',sendingProd[run])
    go.addAttr2ExistingNodes(myNW,receiverIDs,'input',receivingProd[run])
    
    TD = go.calcPotTransportDistances(
            myNW,
            listOfSenderIDs=senderIDs,
            listOfReceiverIDs=receiverIDs
        )
    print(">>>TD ", p, ":", TD)
    # get the transport distances
    myTDs.append(
        TD
    )
    
    # Run the gravity model with given transport distance and return the
    # flow each myTDs[run] is a list of 5 transport distances
    # allFlows is input for the calibration algorithm
    for it, td in enumerate(myTDs[run]):
        allFlows[
            0:len(senderIDs),
            0:len(receiverIDs),
            run,
            it
        ] = go.hymanModel(
            myNW,
            listOfSenderIDs=senderIDs,
            listOfReceiverIDs=receiverIDs,
            transportDistance=td,
            tolerance=0.01
    )
/home/NeubertK/anaconda3/envs/p39/lib/python3.9/site-packages/ipfn/ipfn.py:146: RuntimeWarning: invalid value encountered in double_scalars
  if abs(m_ijk / ori_ijk - 1) > max_conv:
/home/NeubertK/anaconda3/envs/p39/lib/python3.9/site-packages/supplychainmodelhelper/graphoperations.py:1628: RuntimeWarning: invalid value encountered in double_scalars
  WeightDist = np.sum(flow * dist) / (np.sum(flow))
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
>>>TD  eggs : [518.0, 679.0, 841.0, 1002.0, 1164.0]
On the  1. iteration: tolerance is down to 284.5620
On the  2. iteration: tolerance is down to 228.5627
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  3. iteration: tolerance is down to 161.4165
On the  4. iteration: tolerance is down to 224.1155
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  5. iteration: tolerance is down to 161.4165
On the  6. iteration: tolerance is down to 224.1075
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  7. iteration: tolerance is down to 161.4165
On the  8. iteration: tolerance is down to 224.1063
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  9. iteration: tolerance is down to 161.4165
ipfn converged: convergence_rate not updating or below rate_tolerance
On the 10. iteration: tolerance is down to 161.4165
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration (10.): tolerance is down to 161.4165
On the  1. iteration: tolerance is down to 187.1614
On the  2. iteration: tolerance is down to 109.8858
On the  3. iteration: tolerance is down to 76.9338
On the  4. iteration: tolerance is down to 63.9681
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  5. iteration: tolerance is down to 322.4165
On the  6. iteration: tolerance is down to 63.1864
On the  7. iteration: tolerance is down to 63.1196
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  8. iteration: tolerance is down to 678.0000
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  9. iteration: tolerance is down to 677.9997
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration ( 7.): tolerance is down to 63.1196
On the  1. iteration: tolerance is down to 96.7715
On the  2. iteration: tolerance is down to 30.3042
On the  3. iteration: tolerance is down to 10.2949
On the  4. iteration: tolerance is down to 1.6670
On the  5. iteration: tolerance is down to 0.1098
On the  6. iteration: tolerance is down to 0.0013
On the last iteration ( 6.): tolerance is down to 0.0013
On the  1. iteration: tolerance is down to 4.2387
On the  2. iteration: tolerance is down to 0.0496
On the  3. iteration: tolerance is down to 0.0005
On the last iteration ( 3.): tolerance is down to 0.0005
On the  1. iteration: tolerance is down to 98.9327
On the  2. iteration: tolerance is down to 17.7928
On the  3. iteration: tolerance is down to 1.5979
On the  4. iteration: tolerance is down to 0.0178
On the  5. iteration: tolerance is down to 0.0000
On the last iteration ( 5.): tolerance is down to 0.0000
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
>>>TD  milk : [362.0, 597.0, 832.0, 1067.0, 1302.0]
On the  1. iteration: tolerance is down to 695.7447
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  2. iteration: tolerance is down to 235.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  3. iteration: tolerance is down to 235.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration ( 2.): tolerance is down to 235.1083
On the  1. iteration: tolerance is down to 492.5820
Maximum iterations reached
On the  2. iteration: tolerance is down to 459.8334
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  3. iteration: tolerance is down to 470.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  4. iteration: tolerance is down to 470.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration ( 2.): tolerance is down to 459.8334
On the  1. iteration: tolerance is down to 348.0484
On the  2. iteration: tolerance is down to 239.6603
/home/NeubertK/anaconda3/envs/p39/lib/python3.9/site-packages/supplychainmodelhelper/graphoperations.py:1920: RuntimeWarning: divide by zero encountered in double_scalars
  (
On the  3. iteration: tolerance is down to 225.1587
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  4. iteration: tolerance is down to 705.1083
Maximum iterations reached
On the  5. iteration: tolerance is down to 223.9220
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  6. iteration: tolerance is down to 705.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  7. iteration: tolerance is down to 223.8713
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  8. iteration: tolerance is down to 223.8443
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  9. iteration: tolerance is down to 831.0000
ipfn converged: convergence_rate not updating or below rate_tolerance
On the 10. iteration: tolerance is down to 831.0000
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration ( 8.): tolerance is down to 223.8443
On the  1. iteration: tolerance is down to 209.4188
On the  2. iteration: tolerance is down to 77.1483
On the  3. iteration: tolerance is down to 40.6498
On the  4. iteration: tolerance is down to 17.8773
On the  5. iteration: tolerance is down to 7.5900
On the  6. iteration: tolerance is down to 2.6236
On the  7. iteration: tolerance is down to 0.6371
On the  8. iteration: tolerance is down to 0.0760
On the  9. iteration: tolerance is down to 0.0026
On the last iteration ( 9.): tolerance is down to 0.0026
On the  1. iteration: tolerance is down to 47.6112
On the  2. iteration: tolerance is down to 2.6602
On the  3. iteration: tolerance is down to 0.1584
On the  4. iteration: tolerance is down to 0.0006
On the last iteration ( 4.): tolerance is down to 0.0006
In [17]:
#creating calibration measure that halfway might make sense
allFoodTransported = sum(sum(sendingProd,[]))
dummy = np.random.rand(48)*allFoodTransported/80+allFoodTransported/(len(sum(sendingProd,[]))+1)
myCalMat = np.append(
        dummy,
        allFoodTransported-np.sum(dummy)).reshape((len(senderIDs),
        len(receiverIDs))
)
    
print(go.calibration(allFlows,myCalMat))
exiting with relative difference to calibration matrix: 6.104584555716979
[4, 4]

Test visualization after model

In [18]:
myDF1 = pd.DataFrame(myCalMat, index=loc)

# entering distance information to the right nodes on the graph
senderIDs = go.getListOfNodeIDs(
    SCGraph=myNW,
    actors=['Producer'],
    products=['milk'])
receiverIDs = go.getListOfNodeIDs(
    myNW,
    actors=['Consumer'],
    products=['milk'])

# supply and demand for milk and enrich the graph with this data
sendingProd1 = np.sum(sendingProd, 0)# sum vectors and throughs only a list of integers
receivingProd1=  np.sum(receivingProd, 0)# sum vectors and throughs only a list  of integers
sendingProd1 = list(sendingProd1)#transform into a list form
receivingProd1= list(receivingProd1)#transform into a list form
#sendingProd = [1, 4, 9, 15, 2]
#receivingProd = [36, 47, 68, 79, 100]
go.addAttr2ExistingNodes(
    SCGraph=myNW,
    listOfNodeIDs=senderIDs,
    nameOfAttr='output',
    listOfAttr=sendingProd1)
go.addAttr2ExistingNodes(
    SCGraph=myNW,
    listOfNodeIDs=receiverIDs,
    nameOfAttr='input',
    listOfAttr=receivingProd1)


# get edge IDs for enriching graph with distance matrix
allcombIDs1, allcombIDs2 = go.getAllCombinations(
    senderIDs,
    receiverIDs,
    order='1st')
myEdges4Graph = go.getEdgeID(
    SCGraph=myNW,
    outgoingNodes=allcombIDs1,
    incomingNodes=allcombIDs2)

# actual adding edges to graph
go.addAttr2Edges(
    SCGraph=myNW,
    listOfEdgeIDs=myEdges4Graph,
    listOfContent=myDF1.values.flatten(),
    attr='weight')


###########################################################################
d = Drawer(myNW)
d.draw_it(product=['eggs','milk'], actor_type_names=['Producer', 'Consumer'])
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
Input In [18], in <cell line: 52>()
     50 ###########################################################################
     51 d = Drawer(myNW)
---> 52 d.draw_it(product=['eggs','milk'], actor_type_names=['Producer', 'Consumer'])

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/supplychainmodelhelper/drawer.py:124, in Drawer.draw_it(self, product, actor_type_names)
    118         raise Exception(
    119             "the parameter 'actor_type_names' "
    120             "should be a list"
    121         )
    123 # prepping for different aspects of the process of drawing
--> 124 node_positions, node_stages, node_stage_names = self.node_position(
    125     filtered_nodes=node_ids_to_draw
    126 )
    127 sm, edge_options = self.edge_color()
    128 node_list, node_size = self.node_size()

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/supplychainmodelhelper/drawer.py:282, in Drawer.node_position(self, node_attr, filtered_nodes)
    274     found_all_edges_to_be_drawn = all(
    275         [
    276             True if el in existing_edge_ids_in_layer
   (...)
    279         ]
    280     )
    281     if not found_all_edges_to_be_drawn:
--> 282         raise Exception(
    283             "ERROR! at least 1 of the edges between "
    284             "actors/products to be drawn do NOT contain "
    285             "the attribute 'weight'! please check edge "
    286             "ids of corresponding nodes!"
    287         )
    289 pos = dict()
    290 # handle each stage sorted by actors

Exception: ERROR! at least 1 of the edges between actors/products to be drawn do NOT contain the attribute 'weight'! please check edge ids of corresponding nodes!
In [ ]:
 
In [ ]: