# -*- coding: utf-8 -*-
"""
Created on Tue Nov 04 2025

@author: RaquelMonteirodeNobr
"""


#importa todas as funções do PuLP
from pulp import *


import networkx as nx
import numpy as np
import random

#criação da instância

#conj das cidades
cidades = [0, "A", "B", "C", "D", "E"]

#matriz de custos
matriz_custos = [[0,28,31,20,25,34],
                 [28,0,21,29,26,20],
                 [31,21,0,38,20,32],
                 [20,29,38,0,30,27],
                 [25,26,20,30,0,25],
                 [34,20,32,27,25,0]]

procura = [0, 37, 35, 30, 25, 32]

Q = 100
K = 2

D = 0 #procura total
for i in procura:
    D = D + i

#correspondência entre os valores do vetor
#cidades e a matriz de custos
custos = makeDict([cidades, cidades],
                  matriz_custos)

d = makeDict ([cidades], procura)


n = len(cidades)

#estrutura que ignora entrada (i,i)
arcos = [(i,j) for i in cidades 
         for j in cidades if i!=j]

#fim de criação da instância

#início da criação do modelo

#variavel que guarda a formulação para o problema que queremos resolver
#recebe o nome do problems e o objetivo
formulacaoRCC = LpProblem("Formulacao RCC para VRP", LpMinimize)

#criar as variáveis
#LpVariable.dicts(nome variavel, conj. onde esta definida, limiteinferior, limite superior, tipo)
x = LpVariable.dicts("x", (cidades, cidades), 0, 1, LpInteger)


#adicionar as restrições
#----a primeira a adicionar é a FO
formulacaoRCC += (lpSum([x[i][j]*custos[i][j] for (i,j) in arcos]),
                  "FO",
                  )

#----adicionar as restrições
#sai K arcos do depósito
formulacaoRCC += (
        lpSum([x[cidades[0]][j] for j in cidades
               if (cidades[0],j) in arcos]) == K,
        f"sai_K_arcos_deposito",
        )

for i in cidades:
    if i != cidades[0]: #deposito na primeira pos. do vetor cidades
        formulacaoRCC += (
            lpSum([x[i][j] for j in cidades if (i,j) in arcos]) == 1,
            f"sai_{i}",
            )
    
        formulacaoRCC += (
            lpSum([x[j][i] for j in cidades if (j,i) in arcos]) == 1,
            f"entra_{i}",
            )


formulacaoRCC += (
     x[0]["A"] + x[0]["E"]
     + x["B"]["A"] + x["B"]["E"]
     + x["C"]["A"] + x["C"]["E"]
     + x["D"]["A"] + x["D"]["E"] >= 1,
     "RCC1",
     )       
        
formulacaoRCC += (
     x[0]["A"] + x[0]["B"] + x[0]["D"] + x[0]["E"]
     + x["C"]["A"] + x["C"]["B"] + x["C"]["D"] + x["C"]["E"] >= 2,
     "RCC2",
     )       
        
formulacaoRCC += (
     x[0]["A"] + x[0]["B"] + x[0]["C"] + x[0]["E"]
     + x["D"]["A"] + x["D"]["B"] + x["D"]["C"] + x["D"]["E"] >= 2,
     "RCC3",
     )   

#extrair o modelo para um modelo para um ficheiro
formulacaoRCC.writeLP("RCC.lp")

#resolve o modelo
formulacaoRCC.solve()

#estado da resolução
print("Estado:", LpStatus[formulacaoRCC.status])

#valor otimo
print("Custo total = ", value(formulacaoRCC.objective))

#escrever a solução
for v in formulacaoRCC.variables():
    if v.varValue > 0:
        print(v.name, "=", v.varValue)


# Create a graph representing the TSP tour
G = nx.DiGraph()
G.add_nodes_from(cidades)
 
graph_edges = [(i,j) for (i, j) in arcos if x[i][j].varValue == 1]
G.add_edges_from(graph_edges)
 
# Create a dictionary to store the edge values (weights) based on x[i][j].varValue
edge_values = {(i, j): x[i][j].varValue for (i, j) in arcos if x[i][j].varValue == 1}
 
 
# Draw the graph with nodes and edges
pos = nx.spring_layout(G)  # Positioning of nodes
nx.draw(G, pos, with_labels=True, node_color="red", node_size=2500)
 
# Draw the edge labels using the x[i][j].varValue values
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_values, font_color='black')
 
#output diferente


