from gurobipy import *
import numpy as np
import random
from functions import *
from solvers import CLSP_Det
from solvers import CLSP_Det2
from instances import Instance_Det
import shelve
import pandas as pd

#VARIABILI FISSE PER ORA
num_items=5
num_repl=5
horizon=50

#ESTRAZIONE VETTORE MEDIE E MATRICE VARIANZA COVARIANZA
random.seed(100)

mean=[]
    
for i in range(num_items):
    mean.append(random.randint(10,100))

var_coeff=[]
var=[]
sd=[]

for i in range(num_items):
    var_coeff.append(random.uniform(0.1,0.5))
    sd.append(mean[i]*var_coeff[i])
    var.append(pow(sd[i],2))
    
cov=create_cov(var)

#DOMANDE OUT OF SAMPLE(SALVATE IN UN FILE)

d=shelve.open('dataframes/matrice.dat')

D=d['FixedDemands']

d.close()


#CREAZIONE DATASET VUOTO
df=pd.DataFrame(columns=["Seed parameters","Solver type","alpha","T","Path number","Time period","Y0","Y1","Y2","Y3","Y4","S0","S1","S2","S3","S4","I0","I1","I2","I3","I4","Z0","Z1","Z2","Z3","Z4","D0","D1","D2","D3","D4","Cost","CumCost","Time","CumTime","Time Limit","MIP Gap","h_cost","g_cost","f_cost"])


#POPOLAZIONE DATASET, CICLO FOR SUI DIVERSI SEED

for seedP in [100,200,300,400,500,600,700,800,900,1000]:

    #ESTRAZIONE PARAMETRI COL SEED DELL'ITERAZIONE

    random.seed(seedP)
    
    
    #MAGAZZINO INIZIALE
    initial_inventory=[]
    for i in range(num_items):
        initial_inventory.append(random.randint(0,2*mean[i]))

    #COSTI DI MAGAZZINO

    h=[]
    for i in range(num_items):
        h.append(random.randint(1,10))

    #PENALITA' PER DOMANDA NON SODDISFATTA

    g=[]
    for i in range(num_items):
        g.append(random.randint(50,100))
    
    #COSTI DI SETUP

    f=[]
    for i in range(num_items):
        f.append(mean[i]*0.5*4*h[i])
    
    #PROCESSING TIMES

    proc_time=[]
    for i in range(num_items):
        proc_time.append(random.uniform(1,5))
    
    #DISPONIBILITA' MASSIMA DELLA RISORSA

    cap_factor=2
    R=np.inner(proc_time,mean)*cap_factor

    #TEMPI DI SETUP

    setup_factor=0.5
    setup_times=[]

    for i in range(num_items):
        setup_times.append(R*setup_factor/num_items)

    #FOR SULLA LUNGHEZZA DELL'ORIZZONTE TEMPORALE
    for T in [10,20,30,40,50]:
        
        #FOR SUL LIVELLO DI SICUREZZA DELLE SCORTE
        for alpha in [0.55,0.6,0.65,0.7,0.75,0.8,0.85,0.9,0.95]:

            setting={
                'h':h,
                'f':f,
                'proc_time':proc_time,
                'R':R,
                'setup_times':setup_times,
                'num_items':num_items,
                'time_periods':T,
                'mean':mean,
                'sd':sd,
                'alpha':alpha
                }

            #CREAZIONE ISTANZA DEL PROBLEMA
            instance1=Instance_Det(setting)

            #DEFINIZIONE DEL SOLVER DETERMINISTICO
            solver=CLSP_Det(**setting)
            #OPPURE SOLVER DETERMINISTICO CON VARIANTE
            #solver=CLSP_Det2(**setting)

            #FOR SUI 5 PERCORSI DI DOMANDA OUT OF SAMPLE
            for path in range(5):
                    
                cum_cost=0
                cum_time=0
                    
                I=[]
                for l in range(num_items):
                    I.append(initial_inventory[l])
                
                Z=np.zeros((num_items))

                #FOR SUI 50 ISTANTI DI TEMPO DI OGNI PERCORSO
                for t in range(horizon):
                    
                    #RISOLUZIONE DEL PROBLEMA COL SOLVER
                    [objV,Y,S,comp_time,gap]=solver.solve(instance1,I)

                    #AGGIORNAMENTO DEL MAGAZZINO
                    for k in range(num_items):
                        if I[k]+Y[k]-D[path,t,k]>0:
                            I[k]=I[k]+Y[k]-D[path,t,k]
                            Z[k]=0
                        else:
                            Z[k]=-(I[k]+Y[k]-D[path,t,k])
                            I[k]=0
                    
                    #COSTI DI MAGAZZINO
                    h_cost=np.inner(I,h)
                    #COSTI DI VENDITE PERSE
                    g_cost=np.inner(Z,g)
                    #COSTI DI SETUP
                    f_cost=np.inner(S,f)
                    #COSTO TOTALE DELL'ISTANTE TEMPORALE
                    cost=h_cost+g_cost+f_cost
                    #COSTO CUMULATIVO DEL PERCORSO
                    cum_cost+=cost
                    #TEMPO CUMULATIVO DEL PERCORSO
                    cum_time+=comp_time

                    #SALVATAGGIO DELLA NUOVA OSSERVAZIONE NEL DATAFRAME
                    new_obs={
                        "Seed parameters":[seedP],
                        "Solver type":[0],
                        "alpha":[alpha],
                        "T":[T],
                        "Path number":[path],
                        "Time period":[t],
                        "Y0":[Y[0]],
                        "Y1":[Y[1]],
                        "Y2":[Y[2]],
                        "Y3":[Y[3]],
                        "Y4":[Y[4]],
                        "S0":[S[0]],
                        "S1":[S[1]],
                        "S2":[S[2]],
                        "S3":[S[3]],
                        "S4":[S[4]],
                        "I0":[I[0]],
                        "I1":[I[1]],
                        "I2":[I[2]],
                        "I3":[I[3]],
                        "I4":[I[4]],
                        "Z0":[Z[0]],
                        "Z1":[Z[1]],
                        "Z2":[Z[2]],
                        "Z3":[Z[3]],
                        "Z4":[Z[4]],
                        "D0":[D[path,t,0]],
                        "D1":[D[path,t,1]],
                        "D2":[D[path,t,2]],
                        "D3":[D[path,t,3]],
                        "D4":[D[path,t,4]],
                        "Cost":[cost],
                        "CumCost":[cum_cost],
                        "Time":[comp_time],
                        "CumTime":[cum_time],
                        "Time Limit":[np.nan],
                        "MIP Gap":[0.0001],
                        "h_cost":[h_cost],
                        "g_cost":[g_cost],
                        "f_cost":[f_cost]
                        }
                    new=pd.DataFrame(new_obs)
                    df=pd.concat([df,new],ignore_index=True)
                    
                
                    df.to_csv('DatiSimulazioniRHDet20.csv',index=False)

