Problème de flux à coût minimum

9

Un réseau de flux est un graphe orienté G = (V, E)avec un sommet source s ϵ Vet un sommet puits t ϵ V, et où chaque arête (u, v) ϵ Edu graphe (nœuds de connexion u ϵ Vet v ϵ V) est associée à 2 quantités:

  1. c(u, v) >= 0, la capacité du bord
  2. a(u, v) >= 0, le coût de l'envoi d'une unité par le bord

Nous définissons une fonction 0 <= f(u, v) <= c(u, v)comme le nombre d'unités passant par un bord donné (u, v). Ainsi, le coût pour un bord donné (u, v)est a(u, v) * f(u, v). Le problème de flux à coût minimum est défini comme la minimisation du coût total sur toutes les arêtes pour une quantité de flux ddonnée, donnée par la quantité suivante:

Coût

Les contraintes suivantes s'appliquent au problème:

  1. Besoins en capacité : le débit à travers un bord donné ne doit pas dépasser la capacité de ce bord ( f(u, v) <= c(u, v)).
  2. Symétrie asymétrique : le flux à travers un bord donné doit être antisymétrique lorsque la direction est inversée ( f(u, v) = -f(v, u)).
  3. Conservation du flux : le flux net dans un nœud non-source non-puits doit être 0 (pour chaque u ∉ {s, t}, sommant sur tous w, sum f(u, w) = 0).
  4. Débit requis : le flux net de la source et le flux net dans l'évier doit être égale à la fois le débit requis par le réseau ( en sommant sur tous u, sum f(s, u) = sum f(u, t) = d).

Étant donné un réseau de flux Get un flux requis d, générer le coût minimum pour envoyer des dunités via le réseau. Vous pouvez supposer qu'une solution existe. det toutes les capacités et tous les coûts seront des nombres entiers non négatifs. Pour un réseau avec des Nsommets étiquetés avec [0, N-1], le sommet source sera 0et le sommet récepteur sera N-1.

Il s'agit de , donc la réponse la plus courte (en octets) l'emporte. N'oubliez pas qu'il s'agit d'un concours au sein des langues ainsi qu'entre les langues, alors n'ayez pas peur de publier une solution dans une langue verbeuse.

Les fonctions intégrées sont autorisées, mais vous êtes encouragés à inclure des solutions sans fonctions intégrées, soit comme solution supplémentaire dans la même réponse, soit comme réponse indépendante.

L'entrée peut être de toute manière raisonnable qui inclut les capacités et les coûts de chaque bord et la demande.

Cas de test

Les cas de test sont fournis dans le format suivant:

c=<2D matrix of capacities> a=<2D matrix of costs> d=<demand> -> <solution>

c=[[0, 3, 2, 3, 2], [3, 0, 5, 3, 3], [2, 5, 0, 4, 5], [3, 3, 4, 0, 4], [2, 3, 5, 4, 0]] a=[[0, 1, 1, 2, 1], [1, 0, 1, 2, 3], [1, 1, 0, 2, 2], [2, 2, 2, 0, 3], [1, 3, 2, 3, 0]] d=7 -> 20
c=[[0, 1, 1, 5, 4], [1, 0, 2, 4, 2], [1, 2, 0, 1, 1], [5, 4, 1, 0, 3], [4, 2, 1, 3, 0]] a=[[0, 1, 1, 2, 2], [1, 0, 2, 4, 1], [1, 2, 0, 1, 1], [2, 4, 1, 0, 3], [2, 1, 1, 3, 0]] d=7 -> 17
c=[[0, 1, 4, 5, 4, 2, 3], [1, 0, 5, 4, 3, 3, 5], [4, 5, 0, 1, 5, 5, 5], [5, 4, 1, 0, 3, 2, 5], [4, 3, 5, 3, 0, 4, 4], [2, 3, 5, 2, 4, 0, 2], [3, 5, 5, 5, 4, 2, 0]] a=[[0, 1, 4, 2, 4, 1, 1], [1, 0, 3, 2, 2, 1, 1], [4, 3, 0, 1, 4, 5, 2], [2, 2, 1, 0, 2, 2, 3], [4, 2, 4, 2, 0, 4, 1], [1, 1, 5, 2, 4, 0, 2], [1, 1, 2, 3, 1, 2, 0]] d=10 -> 31
c=[[0, 16, 14, 10, 14, 11, 10, 4, 3, 16], [16, 0, 18, 19, 1, 6, 10, 19, 5, 4], [14, 18, 0, 2, 15, 9, 3, 14, 20, 13], [10, 19, 2, 0, 2, 10, 12, 17, 19, 22], [14, 1, 15, 2, 0, 11, 23, 25, 10, 19], [11, 6, 9, 10, 11, 0, 14, 16, 25, 4], [10, 10, 3, 12, 23, 14, 0, 11, 7, 8], [4, 19, 14, 17, 25, 16, 11, 0, 14, 5], [3, 5, 20, 19, 10, 25, 7, 14, 0, 22], [16, 4, 13, 22, 19, 4, 8, 5, 22, 0]] a=[[0, 12, 4, 2, 9, 1, 1, 3, 1, 6], [12, 0, 12, 16, 1, 2, 9, 13, 2, 3], [4, 12, 0, 2, 2, 2, 2, 10, 1, 1], [2, 16, 2, 0, 2, 1, 8, 4, 4, 2], [9, 1, 2, 2, 0, 5, 6, 23, 5, 8], [1, 2, 2, 1, 5, 0, 13, 12, 12, 1], [1, 9, 2, 8, 6, 13, 0, 9, 4, 4], [3, 13, 10, 4, 23, 12, 9, 0, 13, 1], [1, 2, 1, 4, 5, 12, 4, 13, 0, 13], [6, 3, 1, 2, 8, 1, 4, 1, 13, 0]] d=50 -> 213

Ces cas de test ont été calculés avec la bibliothèque NetworkX Python .

Mego
la source
Sandbox
Mego
1
Le golf pendant longtemps a ensuite réalisé que je jouais au mauvais algorithme parce que je ne peux pas lire
Quintec

Réponses:

3

[R + lpSolve ], 201 186 149 144 144 octets

function(c,a,d,`^`=rep,N=ncol(c),G=diag(N),P=t(1^N),M=P%x%G+G%x%-P)lpSolve::lp(,a,rbind(M,diag(N*N)),c('=','<')^c(N,N*N),c(d,0^(N-2),-d,c))$objv

Essayez-le en ligne!

Le code construit le problème linéaire suivant et le résout à l'aide du lpSolvepackage:

mjenXV yVUNEX,yFX,ysubject to:XVFv,X-FX,v=0vV:v{s,t}XVFs,X-FX,s=XVFt,X-FX,t=-FX,bCX,bXV,yV

  • V
  • s
  • t
  • UNEX,yx -> y
  • FX,yx -> y
  • ts
  • CX,yx -> y
digEmAll
la source
Belle programmation linéaire :) Malheureusement, la plupart des langues n'ont pas de lpSolve... :(
Quintec
C'est malheureusement vrai ... BTW ce n'est pas disponible sur base-R, c'est un paquet ... J'ai dû demander à installer sur TIO;)
digEmAll
Pour une raison quelconque, je n'ai pas encore trouvé un moyen rapide de modifier MinCostMaxFlow pour devenir MinCostFlow ... mon cerveau est frit lol, j'aurais aimé qu'il y ait une fonction pour cela dans des langues autres que mathématique
Quintec
@Quintec: faites-vous référence à une implémentation spécifique (par exemple dans une certaine langue) de MinCostMaxFlow?
digEmAll
Non, mon algorithme codé à la main
Quintec
1

Langue Wolfram, 42 octets

FindMinimumCostFlow[#,1,VertexCount@#,#2]&

Intégré trivial. Solution non intégrée à venir bientôt.

lirtosiast
la source
Arrive-t-il dans 6-8 semaines? : P
Quintec
1

Python 3 + NetworkX , 137 octets

from networkx import*
def f(g,d,z='demand'):N=len(g)**.5//1;G=DiGraph(g);G.node[0][z]=-d;G.node[N-1][z]=d;return min_cost_flow_cost(G)

Pas de lien TryItOnline car TIO n'a pas la bibliothèque NetworkX installée

Prend l'entrée du graphique comme une liste de bords avec des attributs de capacité et de poids, comme ceci:

[(0, 0, {'capacity': 0, 'weight': 0}), (0, 1, {'capacity': 3, 'weight': 1}), (0, 2, {'capacity': 2, 'weight': 1}), (0, 3, {'capacity': 3, 'weight': 2}), (0, 4, {'capacity': 2, 'weight': 1}), (1, 0, {'capacity': 3, 'weight': 1}), (1, 1, {'capacity': 0, 'weight': 0}), (1, 2, {'capacity': 5, 'weight': 1}), (1, 3, {'capacity': 3, 'weight': 2}), (1, 4, {'capacity': 3, 'weight': 3}), (2, 0, {'capacity': 2, 'weight': 1}), (2, 1, {'capacity': 5, 'weight': 1}), (2, 2, {'capacity': 0, 'weight': 0}), (2, 3, {'capacity': 4, 'weight': 2}), (2, 4, {'capacity': 5, 'weight': 2}), (3, 0, {'capacity': 3, 'weight': 2}), (3, 1, {'capacity': 3, 'weight': 2}), (3, 2, {'capacity': 4, 'weight': 2}), (3, 3, {'capacity': 0, 'weight': 0}), (3, 4, {'capacity': 4, 'weight': 3}), (4, 0, {'capacity': 2, 'weight': 1}), (4, 1, {'capacity': 3, 'weight': 3}), (4, 2, {'capacity': 5, 'weight': 2}), (4, 3, {'capacity': 4, 'weight': 3}), (4, 4, {'capacity': 0, 'weight': 0})]

Il s'agit d'une version golfée du code que j'ai utilisé pour vérifier les cas de test.

Mego
la source