from gurobipy import *
import pandas as pd
from matplotlib import pyplot as plt

plt.style.use('ggplot')

#IMPORT DATAFRAME CONFRONTO IN SAMPLE
#SOLVER STANDARD vs SOLVER FIX & RELAX
df=pd.read_csv('dataframes/DatiConfrontoFR6.csv')

#VETTORE DEI BRANCHING FACTORS
branching_factors=[[5,3,2],[6,5,2],[5,3,2,2],[9,5,2,1],[5,3,3,2,1]]

#CONFRONTO TRA I SOLVER, FATTO SINGOLARMENTE PER OGNI
#FATTORE (GRAFICI SU COSTI, TEMPI E GAP)

for i in range(5):
    
    branching_factor=branching_factors[i]
    str="".join(["[",",".join([f"{ele}" for ele in branching_factor]),"]"])

    print('Branching factors: {}'.format(branching_factor))

    #DATAFRAME CON SOLO ALBERI DI SCENARI CON IL FATTORE  
    #DI RAMIFICAZIONE DELL'ITERAZIONE IN CORSO DEL CICLO FOR
    df_temp=df[df['Branching_factors']==str]

    #DATAFRAME CON LE SOLE OSSERVAZIONI IN CUI L'ARRESTO E'
    #DOVUTO AL TIME LIMIT
    df_temp2=df_temp.query('Stopping_Crit_BC==1')
    #STAMPA A SCHERMO DI ALCUNE STATISTICHE DELLE PERFORMANCE DELL'ALBERO
    print('{} out of 120 BC simulations interrupted due to time limit'.format(df_temp2.shape[0]))
    print('Mean MIPGap at time limit: {}'.format(df_temp2['MIPGap_BC'].mean()))
    print('Mean relative difference of ObjVs: {}'.format(df_temp['Rel_Diff'].mean()))
    print('Max relative difference of ObjVs: {}'.format(df_temp['Rel_Diff'].max()))

    fig1,ax1=plt.subplots(nrows=2,ncols=1,sharex=True)
    fig2,ax2=plt.subplots(nrows=2,ncols=1,sharex=True)
    x=[]
    y1=[]
    y2=[]
    y3=[]
    y4=[]
    y5=[]
    y6=[]
    y7=[]
    y8=[]
    y9=[]
    y10=[]

    #I TRE CICLI FOR SERVONO PER SCANDIRE TUTTE LE POSSIBILI CONFIGURAZIONI
    #DEI TRE FATTORI PRESI IN ANALISI (COSTI DI MAGAZZINO BASSI/ALTI, PENALITA'
    #DOMANDA NON SODDISFATTA BASSA/ALTA, TB0=2/3/4)
    for h_fact in [0,1]:
        for g_fact in [0,1]:
            for TBO in [2,3,4]:
                #DATAFRAME RIDOTTO ALLE SIMULAZIONI SULLA CONFIGURAZIONE 
                #(h_fact,g_fact,TBO) CORRENTE
                df_temp3=df_temp.query('h_fact=={} and g_fact=={} and TBO=={}'.format(h_fact,g_fact,TBO))
                                 
                x.append('({},{},{})'.format(h_fact,g_fact,TBO))
                #COSTO MEDIO SOLVER STANDARD DELLA CONFIGURAZIONE
                y1.append(df_temp3["Cost_BC"].mean())
                #COSTO MEDIO SOLVER FIIX & RELAX DELLA CONFIGURAZIONE
                y2.append(df_temp3["Cost_FR"].mean())
                #DIFFERENZA RELATIVA MEDIA TRA GLI OBIETTIVI DELLA CONFIGURAZIONE
                y3.append(df_temp3["Rel_Diff"].mean())
                #GAP MEDIO (QUANDO E' MAGGIORE DELLO 0.01) SULLA CONFIGURAZIONE
                if(df_temp3["Stopping_Crit_BC"].mean()>0):
                    y4.append(df_temp3["MIPGap_BC"].mean())
                else:
                    y4.append(0.01)
                #GAP MEDIO DEL FATTORE DI RAMIFICAZIONE (QUANDO E' MAGGIORE DELLO 0.01)
                y5.append(df_temp2['MIPGap_BC'].mean())
                #TEMPO MEDIO SOLVER STANDARD SULLA CONFIGURAZIONE
                y6.append(df_temp3["Time_BC"].mean())
                #TEMPO MEDIO SOLVER FIX & RELAX SULLA CONFIGURAZIONE
                y7.append(df_temp3["Time_FR"].mean())
                #TEMPO MEDIO SOLVER STANDARD DEL FATTORE DI RAMIFICAZIONE
                y8.append(df_temp['Time_BC'].mean())
                #TEMPO MEDIO SOLVER FIX & RELAX DEL FATTORE DI RAMIFICAZIONE
                y9.append(df_temp['Time_FR'].mean())
                #DIFFERENZA RELATIVA MEDIA TRA GLI OBIETTIVI DEL FATTORE DI RAMIFICAZIONE
                y10.append(df_temp['Rel_Diff'].mean())
    fig1.suptitle('Fattore di ramificazione: {}'.format(branching_factor))

    #PLOT VALORI OBIETTIVO DEI DUE SOLVER
    ax1[0].plot(x,y1,marker='.',label='Solver standard')
    ax1[0].plot(x,y2,marker='.',label='Solver F&R')
    ax1[0].set_ylabel('Valore funzione obiettivo')
    ax1[0].legend()
    #PLOT DIFFERENZA RELATIVA MEDIA DEGLI OBIETTIVI
    ax1[1].plot(x,y3,marker='.')
    ax1[1].plot(x,y10,label='Differenza relativa media')
    ax1[1].set_ylabel('Differenza relativa funzioni obiettivo')
    ax1[1].set_xlabel('(h_fact,g_fact,TBO)')
    ax1[1].legend()
    #PLOT GAP MEDIO
    ax2[0].plot(x,y4,marker='.',label='MIPGap')
    ax2[0].plot(x,y5,label='MIPGap medio sopra all\'1%')
    ax2[0].legend()
    ax2[0].set_ylabel('MIPGap')
    #PLOT DEI TEMPI DEI DUE SOLVER
    ax2[1].plot(x,y6,marker='.',label='Tempo solver std')
    ax2[1].plot(x,y7,marker='.',label='Tempo solver F&R')
    ax2[1].plot(x,y8,label='Tempo medio solver std')
    ax2[1].plot(x,y9,label='Tempo medio solver F&R')
    ax2[1].set_xlabel('(h_fact,g_fact,TBO)')
    ax2[1].set_ylabel('Tempo')
    ax2[1].legend()

    #STAMPA DEI DUE TEMPI MEDI DEI DUE SOLVER
    print(y8[0],y9[0])

    plt.show()

