In [9]:
import os
import csv
import platform
import pandas as pd
import networkx as nx
from graph_partitioning import GraphPartitioning, utils

algorithms = ["FENNEL", "SCOTCH", "PATOH"]

cols = ["WASTE", "CUT RATIO", "EDGES CUT", "TOTAL COMM VOLUME", "MODULARITY", "LONELINESS", "NETWORK PERMANENCE", "NORM. MUTUAL INFO"]
pwd = %pwd

run_metrics = True
dumpAssignments = True

# TODO: copy PaToH & SCOTCH settings to FENNEL script

config = {

    "DATA_FILENAME": os.path.join(pwd, "data", "predition_model_tests", "network", "network_1.txt"),
    "OUTPUT_DIRECTORY": os.path.join(pwd, "output"),

    # Set which algorithm is run for the PREDICTION MODEL.
    # Either: 'FENNEL' or 'SCOTCH'
    "PREDICTION_MODEL_ALGORITHM": "",

    # Alternativly, read input file for prediction model.
    # Set to empty to generate prediction model using algorithm value above.
    "PREDICTION_MODEL": "",

    
    "PARTITIONER_ALGORITHM": "",

    # File containing simulated arrivals. This is used in simulating nodes
    # arriving at the shelter. Nodes represented by line number; value of
    # 1 represents a node as arrived; value of 0 represents the node as not
    # arrived or needing a shelter.
    "SIMULATED_ARRIVAL_FILE": os.path.join(pwd,
                                           "data",
                                           "predition_model_tests",
                                           "dataset_1_shift_rotate",
                                           "simulated_arrival_list",
                                           "percentage_of_prediction_correct_90",
                                           "arrival_90_1.txt"
                                          ),
    
    # File containing the prediction of a node arriving. This is different to the
    # simulated arrivals, the values in this file are known before the disaster.
    "PREDICTION_LIST_FILE": os.path.join(pwd,
                                         "data",
                                         "predition_model_tests",
                                         "dataset_1_shift_rotate",
                                         "prediction_list",
                                         "prediction_1_norm.txt"
                                        ),

    # File containing the geographic location of each node, in "x,y" format.
    "POPULATION_LOCATION_FILE": os.path.join(pwd,
                                             "data",
                                             "predition_model_tests",
                                             "coordinates",
                                             "coordinates_1.txt"
                                            ),

    # Number of shelters
    "num_partitions": 6,

    # The number of iterations when making prediction model
    "num_iterations": 1,

    # Percentage of prediction model to use before discarding
    # When set to 0, prediction model is discarded, useful for one-shot
    "prediction_model_cut_off": 0.10,

    # Alpha value used in one-shot (when restream_batches set to 1)
    "one_shot_alpha": 0.5,

    # Number of arrivals to batch before recalculating alpha and restreaming.
    # When set to 1, one-shot is used with alpha value from above
    "restream_batches": 10,

    # When the batch size is reached: if set to True, each node is assigned
    # individually as first in first out. If set to False, the entire batch
    # is processed and empty before working on the next batch.
    "sliding_window": False,

    # Create virtual nodes based on prediction model
    "use_virtual_nodes": False,

    # Virtual nodes: edge weight
    "virtual_edge_weight": 1.0,

    # Loneliness score parameter. Used when scoring a partition by how many
    # lonely nodes exist.
    "loneliness_score_param": 1.2,

    ####
    # GRAPH MODIFICATION FUNCTIONS

    # Also enables the edge calculation function.
    "graph_modification_functions": False,

    # If set, the node weight is set to 100 if the node arrives at the shelter,
    # otherwise the node is removed from the graph.
    "alter_arrived_node_weight_to_100": True,

    # Uses generalized additive models from R to generate prediction of nodes not
    # arrived. This sets the node weight on unarrived nodes the the prediction
    # given by a GAM.
    # Needs POPULATION_LOCATION_FILE to be set.
    "alter_node_weight_to_gam_prediction": False,

    # The value of 'k' used in the GAM will be the number of nodes arrived until
    # it reaches this max value.
    "gam_k_value": 100,

    # Alter the edge weight for nodes that haven't arrived. This is a way to
    # de-emphasise the prediction model for the unknown nodes.
    "prediction_model_emphasis": 1.0,
    
    
    # Path to the scotch shared library
    "SCOTCH_LIB_PATH": os.path.join(pwd, "libs/scotch/macOS/libscotch.dylib")
    if 'Darwin' in platform.system()
    else "/usr/local/lib/libscotch.so",
    
    # Path to the PaToH shared library
    "PATOH_LIB_PATH": os.path.join(pwd, "libs/patoh/lib/macOS/libpatoh.dylib")
    if 'Darwin' in platform.system()
    else os.path.join(pwd, "libs/patoh/lib/linux/libpatoh.so"),
    
    "PATOH_ITERATIONS": 5,

    # Alters how much information to print. Keep it at 1 for this notebook.
    # 0 - will print nothing, useful for batch operations.
    # 1 - prints basic information on assignments and operations.
    # 2 - prints more information as it batches arrivals.
    "verbose": 1
}

#gp = GraphPartitioning(config)

# Optional: shuffle the order of nodes arriving
# Arrival order should not be shuffled if using GAM to alter node weights
#random.shuffle(gp.arrival_order)

%pylab inline


Populating the interactive namespace from numpy and matplotlib

In [10]:
import time

output_graphs = {}

for algorithm in algorithms:
    config['PREDICTION_MODEL_ALGORITHM'] = algorithm
    config['PARTITIONER_ALGORITHM'] = algorithm
    config['verbose'] = 0
    
    output_graphs[algorithm] = {}
    
    print('RUNNUNG ALGORITHM: ', algorithm)
    start_time = time.time()
    # create partitioner
    gp = GraphPartitioning(config)
    
    # load network
    print('Load Network')
    gp.load_network()
    
    print('Initialise Partitioner')
    gp.init_partitioner()
    
    print('Compute prediction model')
    m = gp.prediction_model()
    
    if dumpAssignments:
        output_graphs[algorithm]['prediction'] = gp.metrics_run_file_prefix_prediction + '-prediction-assignments.txt'
        utils.write_assignment_file(gp.metrics_run_folder, gp.metrics_run_file_prefix_prediction + '-prediction-assignments.txt', gp.assignments)

    print('Assign cut-off arrivals')
    m = gp.assign_cut_off()
    
    if dumpAssignments:
        output_graphs[algorithm]['cutoff'] = gp.metrics_run_file_prefix_prediction + '-cutoff-assignments.txt'
        utils.write_assignment_file(gp.metrics_run_folder, gp.metrics_run_file_prefix_prediction + '-cutoff-assignments.txt', gp.assignments)
    
    print('Batch arrival computation')
    m = gp.batch_arrival()
    
    if dumpAssignments:
        output_graphs[algorithm]['batch'] = gp.metrics_run_file_prefix_prediction + '-batch-assignments.txt'
        utils.write_assignment_file(gp.metrics_run_folder, gp.metrics_run_file_prefix_partitioner + '-batch-assignments.txt', gp.assignments)
    
    end_time = time.time()
    output_graphs[algorithm]['elapsed'] = str(end_time-start_time)
    print('Finished in ' + str(end_time-start_time) + 's\n')


RUNNUNG ALGORITHM:  FENNEL
Load Network
Initialise Partitioner
Compute prediction model
Assign cut-off arrivals
Batch arrival computation
Finished in 2.593596935272217s

RUNNUNG ALGORITHM:  SCOTCH
Load Network
Initialise Partitioner
Compute prediction model
Assign cut-off arrivals
Batch arrival computation
Finished in 8.320680141448975s

RUNNUNG ALGORITHM:  PATOH
Load Network
Initialise Partitioner
Compute prediction model
Assign cut-off arrivals
Batch arrival computation
Finished in 3.145155906677246s


In [11]:
# store current run
import datetime
outfile = os.path.join(gp.metrics_run_folder, 'run_' + datetime.datetime.now().strftime('%y_%m_%d').replace("/", "") + '.txt')
with open(outfile, 'w+') as outF:
    for alg in algorithms:
        outF.write(output_graphs[alg]['prediction'] + '\n')
        outF.write(output_graphs[alg]['cutoff'] + '\n')
        outF.write(output_graphs[alg]['batch'] + '\n')
        outF.write(output_graphs[alg]['elapsed'] + '\n')

In [12]:
def loadAssignments(path):
    assignments = []
    with open(path, 'r') as f:
        for line in f:
            line = line.strip()
            parts = line.split(" ")
            assignments.append(int(parts[1]))
    return assignments

In [13]:
# analyse prediction model
fennel_pred_assignments = loadAssignments(output_graphs['FENNEL']['prediction'])
scotch_pred_assignments = loadAssignments(output_graphs['SCOTCH']['prediction'])
patoh_pred_assignments = loadAssignments(output_graphs['PATOH']['prediction'])

fennel_batch_assignments = loadAssignments(output_graphs['FENNEL']['batch'])
scotch_batch_assignments = loadAssignments(output_graphs['SCOTCH']['batch'])
patoh_batch_assignments = loadAssignments(output_graphs['PATOH']['batch'])

In [14]:
#print(fennel_pred_assignments)
#print(scotch_pred_assignments)
#print(patoh_pred_assignments)
from sklearn.metrics.cluster import normalized_mutual_info_score as nmis

fennel_nmi_prediction = [nmis(fennel_pred_assignments, fennel_pred_assignments)]
fennel_nmi_prediction.append(nmis(fennel_pred_assignments, scotch_pred_assignments))
fennel_nmi_prediction.append(nmis(fennel_pred_assignments, patoh_pred_assignments))

scotch_nmi_prediction = [nmis(scotch_pred_assignments, fennel_pred_assignments)]
scotch_nmi_prediction.append(nmis(scotch_pred_assignments, scotch_pred_assignments))
scotch_nmi_prediction.append(nmis(scotch_pred_assignments, patoh_pred_assignments))

patoh_nmi_prediction = [nmis(patoh_pred_assignments, fennel_pred_assignments)]
patoh_nmi_prediction.append(nmis(patoh_pred_assignments, scotch_pred_assignments))
patoh_nmi_prediction.append(nmis(patoh_pred_assignments, patoh_pred_assignments))

nmi_prediction = np.array([fennel_nmi_prediction, scotch_nmi_prediction, patoh_nmi_prediction])

print(nmi_prediction)

fennel_nmi_batch = [nmis(fennel_batch_assignments, fennel_batch_assignments)]
fennel_nmi_batch.append(nmis(fennel_batch_assignments, scotch_batch_assignments))
fennel_nmi_batch.append(nmis(fennel_batch_assignments, patoh_batch_assignments))

scotch_nmi_batch = [nmis(scotch_batch_assignments, fennel_batch_assignments)]
scotch_nmi_batch.append(nmis(scotch_batch_assignments, scotch_batch_assignments))
scotch_nmi_batch.append(nmis(scotch_batch_assignments, patoh_batch_assignments))

patoh_nmi_batch = [nmis(patoh_batch_assignments, fennel_batch_assignments)]
patoh_nmi_batch.append(nmis(patoh_batch_assignments, scotch_batch_assignments))
patoh_nmi_batch.append(nmis(patoh_batch_assignments, patoh_batch_assignments))

nmi_batch = np.array([fennel_nmi_batch, scotch_nmi_batch, patoh_nmi_batch])

print(nmi_batch)

fennel_nmi_self = [nmis(fennel_pred_assignments, fennel_batch_assignments)]
scotch_nmi_self = [nmis(scotch_pred_assignments, scotch_batch_assignments)]
patoh_nmi_self = [nmis(patoh_pred_assignments, patoh_batch_assignments)]


[[ 1.          0.14556242  0.15678145]
 [ 0.14556242  1.          0.33864059]
 [ 0.15678145  0.33864059  1.        ]]
[[ 1.          0.65020998  0.64184705]
 [ 0.65020998  1.          0.72158337]
 [ 0.64184705  0.72158337  1.        ]]

In [15]:
print(patoh_pred_assignments)
print(patoh_batch_assignments)


[1, 2, 3, 2, 4, 0, 2, 5, 0, 2, 5, 0, 4, 0, 1, 1, 4, 0, 0, 5, 0, 1, 1, 0, 3, 3, 5, 1, 5, 4, 3, 4, 2, 4, 1, 5, 2, 1, 4, 2, 0, 4, 3, 5, 2, 5, 5, 0, 0, 1, 3, 1, 4, 4, 1, 3, 3, 2, 4, 3, 1, 0, 2, 3, 5, 3, 5, 2, 2, 2, 0, 5, 4, 1, 5, 0, 2, 4, 3, 1, 5, 2, 1, 4, 5, 3, 0, 2, 3, 2, 1, 5, 5, 3, 1, 2, 1, 0, 4, 2, 3, 1, 5, 1, 1, 4, 4, 0, 5, 4, 2, 3, 3, 0, 1, 4, 1, 3, 2, 1, 2, 4, 3, 4, 4, 1, 3, 1, 4, 5, 5, 3, 2, 3, 0, 4, 0, 1, 2, 3, 0, 2, 0, 3, 4, 2, 1, 3, 3, 5, 1, 3, 0, 3, 1, 2, 0, 4, 3, 5, 0, 2, 3, 3, 4, 3, 4, 5, 5, 1, 0, 5, 5, 2, 3, 5, 4, 0, 3, 1, 0, 2, 5, 5, 0, 1, 1, 4, 3, 5, 1, 4, 2, 3, 1, 3, 1, 4, 0, 3, 0, 3, 0, 3, 4, 1, 0, 2, 4, 2, 3, 3, 3, 4, 2, 5, 0, 2, 4, 1, 3, 3, 2, 0, 5, 4, 0, 0, 3, 1, 1, 5, 3, 1, 3, 3, 2, 2, 2, 4, 1, 3, 0, 0, 3, 4, 4, 1, 5, 4, 1, 0, 2, 1, 1, 2, 4, 1, 1, 2, 1, 4, 3, 1, 1, 5, 1, 2, 4, 0, 2, 2, 2, 4, 4, 3, 4, 0, 3, 4, 5, 2, 0, 4, 5, 1, 2, 5, 5, 0, 2, 5, 0, 3, 3, 0, 3, 1, 5, 5, 3, 2, 0, 4, 5, 1, 4, 5, 1, 4, 1, 3, 3, 5, 5, 1, 0, 5, 3, 3, 5, 3, 3, 3, 4, 4, 2, 2, 0, 4, 2, 5, 3, 4, 5, 3, 1, 2, 5, 0, 4, 3, 1, 4, 3, 4, 3, 2, 0, 2, 3, 1, 1, 0, 4, 3, 5, 4, 1, 1, 3, 4, 0, 1, 0, 4, 2, 1, 4, 3, 3, 0, 5, 3, 4, 1, 5, 5, 1, 2, 0, 5, 1, 2, 2, 5, 3, 0, 4, 4, 3, 1, 0, 2, 4, 1, 3, 4, 4, 1, 1, 2, 4, 4, 3, 0, 4, 5, 0, 2, 1, 1, 4, 1, 1, 0, 3, 0, 2, 0, 2, 4, 0, 1, 5, 4, 5, 2, 3, 1, 2, 5, 1, 1, 5, 3, 1, 0, 5, 3, 4, 4, 1, 1, 1, 1, 3, 2, 5, 0, 4, 2, 4, 2, 2, 3, 0, 0, 2, 5, 2, 0, 2, 3, 4, 2, 3, 1, 0, 1, 1, 5, 4, 4, 5, 2, 0, 5, 3, 2, 4, 4, 5, 2, 0, 3, 1, 5, 3, 2, 2, 0, 4, 3, 0, 5, 0, 4, 4, 3, 3, 1, 1, 1, 3, 0, 2, 5, 4, 0, 2, 3, 4, 0, 5, 0, 4, 3, 3, 0, 1, 2, 1, 0, 2, 1, 0, 5, 3, 2, 3, 0, 2, 1, 4, 0, 4, 0, 2, 4, 5, 5, 5, 5, 2, 2, 2, 4, 1, 3, 1, 0, 4, 3, 5, 3, 3, 0, 1, 3, 2, 2, 4, 0, 3, 5, 1, 3, 1, 0, 3, 2, 5, 4, 0, 1, 4, 0, 3, 4, 3, 5, 0, 1, 0, 1, 1, 0, 2, 2, 1, 2, 5, 2, 0, 2, 2, 1, 0, 3, 2, 5, 3, 3, 5, 5, 4, 5, 0, 2, 0, 3, 5, 4, 5, 2, 5, 1, 2, 4, 3, 1, 4, 5, 5, 3, 0, 2, 2, 4, 5, 0, 5, 2, 2, 4, 1, 2, 5, 5, 4, 4, 5, 2, 0, 4, 1, 0, 5, 3, 3, 2, 1, 4, 2, 1, 1, 5, 5, 5, 2, 5, 5, 1, 3, 4, 2, 4, 3, 0, 2, 5, 3, 2, 4, 0, 1, 3, 4, 5, 4, 0, 0, 3, 5, 5, 4, 2, 0, 2, 2, 5, 0, 0, 1, 3, 5, 5, 0, 0, 5, 5, 5, 4, 2, 4, 2, 2, 4, 5, 5, 2, 1, 1, 0, 5, 0, 5, 0, 4, 0, 4, 5, 2, 1, 0, 5, 0, 4, 3, 2, 1, 2, 4, 0, 2, 5, 0, 0, 0, 1, 0, 4, 4, 1, 3, 3, 2, 5, 1, 0, 1, 4, 1, 0, 0, 0, 3, 0, 5, 4, 3, 5, 3, 2, 5, 4, 3, 5, 5, 1, 2, 5, 4, 3, 5, 0, 4, 1, 5, 4, 1, 2, 1, 0, 5, 1, 5, 2, 0, 3, 4, 2, 5, 2, 0, 4, 3, 4, 0, 3, 1, 4, 2, 1, 1, 3, 2, 3, 5, 0, 1, 4, 0, 2, 5, 3, 2, 1, 1, 4, 4, 0, 3, 3, 0, 4, 0, 5, 0, 3, 5, 0, 4, 3, 2, 5, 4, 1, 2, 1, 2, 2, 1, 2, 4, 0, 4, 5, 2, 2, 3, 5, 5, 0, 5, 4, 0, 1, 3, 2, 4, 3, 5, 4, 5, 4, 1, 5, 1, 0, 0, 4, 0, 4, 0, 0, 0, 3, 1, 4, 1, 4, 1, 2, 2, 1, 3, 4, 4, 4, 5, 2, 5, 2, 4, 4, 5, 1, 1, 1, 3, 0, 1, 1, 3, 5, 3, 5, 0, 0, 3, 4, 3, 2, 1, 3, 3, 0, 4, 1, 5, 1, 4, 3, 5, 2, 1, 0, 0, 0, 4, 3, 0, 3, 2, 5, 5, 1, 3, 5, 4, 0, 0, 0, 0, 0, 0, 5, 3, 2, 4, 2, 3, 5, 5, 4, 5, 3, 2, 1, 5, 3, 0, 3, 0, 2, 3, 0, 2, 1, 2, 1, 4, 5, 5, 0, 5, 5, 5, 2, 1, 2, 2, 4, 3, 0, 0, 2, 2, 1, 3, 2, 1, 5, 1, 2, 3, 4, 2]
[-1, -1, -1, -1, 4, 0, -1, -1, -1, -1, -1, -1, 4, 0, -1, -1, -1, 0, 0, -1, -1, -1, -1, -1, 3, 3, -1, -1, -1, 4, -1, 4, -1, 4, -1, -1, -1, -1, 4, -1, 0, 4, 3, -1, -1, -1, -1, 0, -1, -1, 3, -1, -1, 4, -1, 3, 3, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, 0, 2, 4, -1, -1, -1, -1, -1, 4, -1, 3, 0, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, 0, 4, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, 4, -1, -1, 3, -1, -1, 4, -1, 3, -1, -1, -1, 4, 3, 4, -1, -1, -1, -1, 4, -1, -1, 3, -1, 3, -1, 4, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 0, 4, -1, -1, -1, -1, 3, -1, 4, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 4, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, 3, -1, -1, -1, 4, -1, -1, -1, 3, -1, -1, 4, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, -1, 0, -1, 4, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, 0, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 4, 3, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 4, 4, -1, 4, 0, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 3, 0, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, 4, -1, -1, -1, -1, -1, 3, -1, -1, -1, 0, -1, 3, -1, -1, -1, 3, -1, 4, 4, -1, -1, 0, 4, -1, -1, 3, 4, -1, -1, -1, -1, -1, -1, 4, 3, -1, -1, 3, 4, 3, -1, -1, -1, -1, -1, -1, 0, 4, 3, -1, 5, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 5, -1, -1, 2, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 5, -1, 1, -1, -1, -1, 2, -1, -1, 1, -1, 2, -1, -1, -1, 5, 1, -1, -1, 5, -1, -1, 5, -1, -1, 2, -1, -1, -1, 1, -1, -1, 2, 5, 5, 5, -1, -1, -1, -1, -1, -1, 2, -1, 5, -1, -1, -1, -1, 5, 1, -1, -1, -1, -1, -1, -1, 5, 5, -1, -1, -1, 1, -1, -1, -1, -1, 5, -1, -1, 2, -1, 3, -1, 2, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 5, -1, 1, -1, -1, -1, 5, -1, 5, -1, -1, -1, -1, -1, -1, -1, 5, 1, 2, -1, 3, 2, -1, 2, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, 5, 2, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, 1, 5, 3, 5, 1, -1, 2, -1, -1, -1, -1, -1, 1, 3, -1, -1, -1, -1, 2, 5, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 2, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 2, -1, -1, 3, -1, -1, -1, -1, 2, -1, 1, 5, -1, 1, 2, -1, -1, -1, -1, 5, 3, -1, 5, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5, -1, -1, -1, 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, -1, 2, -1, -1, 2, 1, -1, -1, 5, -1, -1, -1, 0, -1, -1, -1, 5, -1, 1, -1, -1, -1, 0, -1, -1, 3, -1, -1, 0, 1, -1, -1, -1, 5, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, 0, -1, 2, -1, -1, 2, -1, -1, -1, 0, -1, 1, 1, -1, -1, -1, -1, 2, 0, -1, -1, 1, 1, 0, -1, -1, 5, 5, -1, -1, 3, -1, -1, -1, 2, -1, -1, -1, 0, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 0, 5, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 5, -1, -1, -1, 3, -1, -1, -1, 5, 5, 0, 2, -1, 0, 5, -1, -1, -1, 1, -1, -1, 2, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, 2, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 2, -1, 0, -1, -1, 3, 5, 1, 2, -1, -1, -1, -1, 2, 1, -1, -1, -1, -1, 1, 0, -1, -1, 5, -1, -1, -1, 0, 0, 3, 1, 3, -1, -1, 3, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, 4, -1, -1, 3, -1, -1, -1, -1, -1, -1, 2, 0, 1, 1, 1, 0, 0, -1, -1, -1, 2, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, 3, 1, -1, 0, -1, 5, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, 4, -1]

In [ ]: