Problema de fluxo de custo mínimo

9

Uma rede de fluxo é um gráfico direcionado G = (V, E)com um vértice de origem s ϵ Ve um vértice de coletor t ϵ V, e onde cada aresta (u, v) ϵ Eno gráfico (nós de conexão u ϵ Ve v ϵ V) possui 2 quantidades associadas:

  1. c(u, v) >= 0, a capacidade da borda
  2. a(u, v) >= 0, o custo de enviar uma unidade pela borda

Definimos uma função 0 <= f(u, v) <= c(u, v)para ser o número de unidades que estão sendo passadas através de uma determinada aresta (u, v). Assim, o custo para uma determinada aresta (u, v)é a(u, v) * f(u, v). O problema do fluxo de custo mínimo é definido como a minimização do custo total em todas as arestas para uma determinada quantidade de fluxo d, fornecida pela seguinte quantidade:

custo

As seguintes restrições se aplicam ao problema:

  1. Requisitos de capacidade : o fluxo através de uma determinada aresta não pode exceder a capacidade dessa aresta ( f(u, v) <= c(u, v)).
  2. Simetria de inclinação : o fluxo através de uma determinada aresta deve ser anti-simétrico quando a direção é invertida ( f(u, v) = -f(v, u)).
  3. Fluxo de conservação : o fluxo líquido em qualquer nó não-fonte não pia deve ser 0 (para cada u ∉ {s, t}, somando sobre todos w, sum f(u, w) = 0).
  4. Fluxo necessário : a rede fluir para fora da fonte e o fluxo líquido na pia deve tanto igualar o fluxo necessário através da rede (somando sobre todos u, sum f(s, u) = sum f(u, t) = d).

Dada uma rede de fluxo Ge um fluxo necessário d, produza o custo mínimo para enviar dunidades pela rede. Você pode assumir que existe uma solução. de todas as capacidades e custos serão números inteiros não negativos. Para uma rede com Nvértices rotulados com [0, N-1], o vértice de origem será 0e o vértice de coletor será N-1.

Isso é , então a resposta mais curta (em bytes) vence. Lembre-se de que essa é uma competição entre idiomas e também entre idiomas. Portanto, não tenha medo de postar uma solução em um idioma detalhado.

Os internos são permitidos, mas você é encorajado a incluir soluções sem os internos, como uma solução adicional na mesma resposta ou como uma resposta independente.

A entrada pode ser de qualquer maneira razoável que inclua as capacidades e os custos de cada borda e a demanda.

Casos de teste

Os casos de teste são fornecidos no seguinte formato:

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

Esses casos de teste foram calculados com a biblioteca NetworkX Python .

Mego
fonte
Sandbox
Mego
11
Prática de golfe por um longo tempo, em seguida, percebi que eu estava jogando golfe o algoritmo errado porque eu não posso ler
Quintec

Respostas:

3

[R + lpSolve ], 201 186 149 144 bytes

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

Experimente online!

O código constrói o seguinte problema linear e resolve-o usando o lpSolvepacote:

mEunxV yVUMAx,yfx,ysvocêbject to:xVfv,x-fx,v=0 0vV:v{s,t}xVfs,x-fx,s=dxVft,x-fx,t=-dfx,bCx,bxV,yV

  • V
  • s
  • t
  • UMAx,yx -> y
  • fx,yx -> y
  • dts
  • Cx,yx -> y
digEmAll
fonte
Boa programação linear :) Infelizmente, a maioria das linguagens não possui um lpSolve... :(
Quintec 03/02/19
Isso é infelizmente verdade ... BTW ele não está disponível em base-R, é um pacote ... Eu tive que pedir para instalar em TIO;)
digEmAll
Por alguma razão eu ainda tenho que encontrar uma maneira curta de modificar MinCostMaxFlow para se tornar MinCostFlow ... meu cérebro está frito lol, eu gostaria que houvesse uma função para este em que não mathematica línguas
Quintec
@Quintec: você está se referindo a uma implementação específica (por exemplo, em um determinado idioma) do MinCostMaxFlow?
digEmAll
Não, meu algoritmo com código de mão
Quintec 03/02/19
1

Wolfram Language, 42 bytes

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

Trivial embutido. Solução não integrada em breve.

lirtosiast
fonte
Está chegando em 6-8 semanas? : P
Quintec 25/02/19
1

Python 3 + NetworkX , 137 bytes

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)

Nenhum link TryItOnline porque o TIO não possui a biblioteca NetworkX instalada

Toma a entrada do gráfico como uma lista de arestas com atributos de capacidade e peso, assim:

[(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})]

Esta é uma versão em golf do código que eu usei para verificar os casos de teste.

Mego
fonte