
import pandas as pd
import numpy as np
import pulp as plp
import pickle


warehouse_supply = pickle.load( open(r":C:\Users\User\Desktop\Extending Power BI\kod\Extending-Power-BI-with-Python-and-R-main\Chapter10\Python\warehouse_supply.pkl", "rb") )
country_demands = pickle.load( open(r"C:\Users\User\Desktop\Extending Power BI\kod\Extending-Power-BI-with-Python-and-R-main\Chapter10\Python\country_demands.pkl", "rb") )
cost_matrix = pickle.load( open(r"C:\Users\User\Desktop\Extending Power BI\kod\Extending-Power-BI-with-Python-and-R-main\Chapter10\Python\cost_matrix.pkl", "rb") )

n_warehouses = warehouse_supply.shape[0]
n_countries = country_demands.shape[0]

# Tworzenie obiektu problemu LP
model = plp.LpProblem("supply-demand-minimize-costs-problem", plp.LpMinimize)

# Nazwy zmiennych decyzyjnych
var_indexes = [str(i)+str(j) for i in range(1, n_warehouses+1) for j in range(1, n_countries+1)]

# Definiowanie zmiennych decyzyjnych
decision_vars = plp.LpVariable.matrix(
    name="x",            # nazwa zmiennej
    indexs=var_indexes,  # indeksy zmiennych
    cat="Integer",       # Zmienne decyzyjne mogą przyjmować tylko wartości całkowite (default='Continuous')
    lowBound=0 )         # wartości nie mogą być ujemne

# Zmień kształt macierzy, aby mieć takie same rozmiary macierzy kosztów
shipping_mtx = np.array(decision_vars).reshape(n_warehouses,n_countries)

# Funkcja celu zapisana w całości
objective_func = plp.lpSum(cost_matrix * shipping_mtx)

# Dodawanie funkcji celu do obiektu modelu
model += objective_func

# Wyświetlenie i dodanie ograniczeń zaopatrzenia magazynowego do obiektu modelu
for i in range(n_warehouses):
    model += plp.lpSum(shipping_mtx[i][j] for j in range(n_countries)) <= warehouse_supply[i], "Ograniczenia zaopatrzenia magazynów" + str(i)
    
# Wyświetlenie i dodanie do obiektu modelu ograniczeń zapotrzebowania krajów
for j in range(n_countries):
    model += plp.lpSum(shipping_mtx[i][j] for i in range(n_warehouses)) >= country_demands[j] , "Ograniczenia zapotrzebowania krajów" + str(j)


model.solve()

status = plp.LpStatus[model.status]

# Znaleziono wartości zmiennych decyzyjnych
decision_var_results = np.empty(shape=(n_warehouses * n_countries))
z = 0
for v in model.variables():
    try:
        decision_var_results[z] = v.value()
        z += 1
    except:
        print("Błąd: nie można znaleźć wartości")


countries = ['Włochy','Francja','Niemcy','Japonia','Chiny','USA']
row_idxs = ['Magazyn ITA','Magazyn DEU','Magazyn JPN','Magazyn USA']

result_df = pd.DataFrame({'warehouse_name': np.repeat(warehouses, n_countries),
                          'country_name': np.tile(countries, n_warehouses),
                          'shipped_qty': decision_var_results,
                          'cost': np.multiply( cost_matrix.reshape(n_warehouses * n_countries), decision_var_results )},
                         columns=['warehouse_name','country_name','shipped_qty','cost'])
