-1

I am working on a formulation of transportation problem through Linear Programming. Primarily I searched it on the web and found a code which is written in Java. But, I have to write whole stuff in Python. And I am converting it into Python. I don't claim myself good at Java nay at Python. I tried to convert a bit. Everything is fine, but I don't know how to convert the snippet below, it deals with LinkedLists and Stream functions of Java.

static LinkedList<Shipment> matrixToList() {
    return stream(matrix)
            .flatMap(row -> stream(row))
            .filter(s -> s != null)
            .collect(toCollection(LinkedList::new));
}

If you are interested in looking into how I converted above linked Java code, here you can see the Shipment class below is my (incomplete) Python code:

import sys

class TransportationProblem:

    demand = list()
    supply = list()
    costs = list(list())
    matrix = list(list())

    def __init__(self):
        pass

    class Shipment:
        costPerUnit = 0.0
        quantity = 0.0
        r = 0
        c = 0

        def __init__(self, quantity, costPerUnit, r, c):
            self.quantity = quantity
            self.costPerUnit = costPerUnit
            self.r = r
            self.c = c

    def init(self, f_name= ""):
        try:
            with open(f_name) as f:
                val = [int(x) for x in f.readline().strip().split(' ')]
                numSources, numDestinations = val[0], val[1]
                src = list()
                dst = list()

                val = [int(x) for x in f.readline().strip().split(' ')]
                for i in range(0,numSources):
                    src.append(val[i])

                val = [int(x) for x in f.readline().strip().split(' ')]
                for i in range(0, numDestinations):
                    dst.append(val[i])

                totalSrc = sum(src)
                totalDst = sum(dst)

                if totalSrc > totalDst:
                    dst.append(totalSrc - totalDst)
                elif totalDst > totalSrc:
                    src.append(totalDst - totalSrc)

                self.supply = src
                self.demand = dst

                self.costs = [[0 for j in range(len(dst))] for i in range(len(src))]
                self.matrix = [[self.Shipment() for j in range(len(dst))] for i in range(len(src))]

                for i in range(0,len(src)):
                    val = [int(x) for x in f.readline().strip().split(' ')]
                    for j in range(0, len(dst)):
                        self.costs[i][j] = val[j]

                print self.costs
        except IOError:
            print "Error: can\'t find file or read data"

    def northWestCornerRule(self):
        northwest = 0
        for r in range(0, len(self.supply)):
            for c in range(northwest, len(self.demand)):
                quantity = min(self.supply[r], self.demand[c])
                if quantity > 0:
                    self.matrix[r][c] = self.Shipment(quantity=quantity, costPerUnit=self.costs[r][c], r=r, c=c)
                    self.supply[r] = self.supply[r] - quantity
                    self.demand[c] = self.demand[c] - quantity
                    if self.supply[r] == 0:
                        northwest = c
                        break

    def steppingStone(self):
        maxReduction = 0
        move = []
        leaving = self.Shipment()

        self.fixDegenerateCase()
        for r in range(0,len(self.supply)):
            for c in range(0,len(self.demand)):
                if self.matrix[r][c] != None:
                    pass

                trail = self.Shipment(quantity=0, costPerUnit=self.costs[r][c], r=r, c=c)
                path = self.geClosedPath(trail)

                reduction = 0
                lowestQuantity = sys.maxint
                leavingCandidate = None

                plus = True
                for s in path:
                    if plus == True:
                        reduction = reduction + s.costPerUnit
                    else:
                        reduction = reduction - s.costPerUnit
                        if s.quantity < lowestQuantity:
                            leavingCandidate = s
                            lowestQuantity = s.quantity
                    plus = not plus
                if reduction < maxReduction:
                    move = path
                    leaving = leavingCandidate
                    maxReduction = reduction

        if move != None:
            q = leaving.quantity
            plus = True
            for s in move:
                s.quantity = s.quantity + q if plus else s.quantity - q
                self.matrix[s.r][s.c] = None if s.quantity == 0 else s
                plus = not plus
            self.steppingStone()

    def fixDegenerateCase(self):
        pass

    def getClosedPath(self):
        pass

    def matrixToList(self):
        pass

1 Answers1

1

We can break this into steps. You start with a matrix variable, which is some iterable that contains iterables of type Shipment.

To stream an object means that you perform an action on each element of the stream.

A map on a stream means that you take each object, say of type A, and transform it to some type B. A flatMap is a special case used when a map would produce Stream<B>. flatMap lets you concatenate these streams into a single stream.

Say each A maps to a stream of 3 objects {A1, A2} -> {{B11, B12, B13}, {B21, B22, B23}}

flatMap will make this one stream {A1, A2} -> {B11, B12, B13, B21, B22, B23}

In this case a matrix produces a stream of row objects. Each row is mapped into a stream of Shipment and flatMap is used to concatenate them.

Finally filter is used to remove empty shipments (ie value is null) and the collect method is called to transform the stream of Shipment into a List.

Recreating this without streams might look like bellow:

static LinkedList<Shipment> matrixToList() {
    LinkedList<Shipment> result = new LinkedList<>();
    for (List<Shipment> row : matrix) {
        for (Shipment shipment : row) {
            if (shipment != null) {
                result.add(shipment );
            }
        }
    }
    return result;
}
flakes
  • 21,558
  • 8
  • 41
  • 88