All Downloads are FREE. Search and download functionalities are using the official Maven repository.

breeze.optimize.flow.LPMaxFlow.scala Maven / Gradle / Ivy

package breeze.optimize.flow

import breeze.optimize.linear.LinearProgram
import collection.mutable.ArrayBuffer

/**
 * 
 * @author dlwh
 */

class LPMaxFlow[N](val g: FlowGraph[N]) {
  import g._
  lazy val maxFlow:(Map[Edge,Double],Double) = {
    val queue = collection.mutable.Queue[N]()
    queue += g.source
    val visited = collection.mutable.Set[N]()

    val lp = new LinearProgram
    import lp._


    val constraints = new ArrayBuffer[Constraint]()
    val incoming = new collection.mutable.HashMap[N,ArrayBuffer[Expression]]() {
      override def default(k: N) = {
        val a = new ArrayBuffer[Expression]()
        update(k,a)
        a
      }
    }
    val outgoing = new collection.mutable.HashMap[N,ArrayBuffer[Expression]]() {
      override def default(k: N) = {
        val a = new ArrayBuffer[Expression]()
        update(k,a)
        a
      }
    }

    val edgeMap = collection.mutable.Map[Edge,Variable]()

    while(queue.nonEmpty) {
      val n = queue.dequeue()
      if(!visited(n)) {
        visited += n
        if(n != sink)
          for(e <- edgesFrom(n)) {
            val f_e = Real(e.head + "->" + e.tail)
            edgeMap += (e -> f_e)
            constraints += (f_e <= e.capacity)
            constraints += (f_e * -1.0 <= 0.0 )
            incoming(e.tail) += f_e * e.gain
            outgoing(e.head) += f_e
            if(!visited(e.tail))
              queue += e.tail
          }
      }
    }

    for(n <- visited; inc <- incoming.get(n); out <- outgoing.get(n)) {
      constraints += (inc.reduceLeft(_ + _) <= out.reduceLeft(_ + _))
      constraints += ( out.reduceLeft(_ + _) <= inc.reduceLeft(_ + _) )
    }

    val total = incoming(sink).reduceLeft( _ + _)
    val solution = maximize { total subjectTo(constraints:_*) }

    (Map.empty ++ edgeMap.mapValues(solution.valueOf(_)),solution.value)
  }

  def minCostFlow(minimumFlow: Double = -1) = {
    val mf = if(minimumFlow < 0) maxFlow._2 else minimumFlow


    val queue = collection.mutable.Queue[N]()
    queue += g.source
    val visited = collection.mutable.Set[N]()

    val lp = new LinearProgram
    import lp._

    val costs = new ArrayBuffer[Expression]()

    val constraints = new ArrayBuffer[Constraint]()
    val incoming = new collection.mutable.HashMap[N,ArrayBuffer[Expression]]() {
      override def default(k: N) = {
        val a = new ArrayBuffer[Expression]()
        update(k,a)
        a
      }
    }
    val outgoing = new collection.mutable.HashMap[N,ArrayBuffer[Expression]]() {
      override def default(k: N) = {
        val a = new ArrayBuffer[Expression]()
        update(k,a)
        a
      }
    }

    val edgeMap = collection.mutable.Map[Edge,Variable]()

    while(queue.nonEmpty) {
      val n = queue.dequeue()
      if(!visited(n)) {
        visited += n
        if(n != sink)
          for(e <- edgesFrom(n)) {
            val f_e = Real(e.head + "->" + e.tail)
            edgeMap += (e -> f_e)
            constraints += (f_e <= e.capacity)
            constraints += (f_e * -1.0 <= 0.0 )
            costs += (f_e * e.cost)

            incoming(e.tail) += f_e * e.gain
            outgoing(e.head) += f_e
            if(!visited(e.tail))
              queue += e.tail
          }
      }
    }

    for(n <- visited; inc <- incoming.get(n); out <- outgoing.get(n)) {
      constraints += (inc.reduceLeft(_ + _) <= out.reduceLeft(_ + _))
      constraints += ( out.reduceLeft(_ + _) <= inc.reduceLeft(_ + _) )
    }

    val flowTotal = incoming(sink).reduceLeft(_ + _)
    constraints += (flowTotal * -1.0 <= mf * -1.0)

    val total = costs.reduceLeft( _ + _)
    val solution = maximize { total * -1.0 subjectTo(constraints:_*) }

    (Map.empty ++ edgeMap.mapValues(solution.valueOf(_)),-solution.value)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy