Related
I have a Directed Graph G=(V,E) that each vertex v has two properties:
r indicating the worthiness
m indicating the highest v''s r (where v' is a reachable vertex from v).
I need to find ms for all vertices in O(|V|+|E|) time.
For example,
Initial G
A(r = 1, m = 1) → B(r = 3, m = 3) ← C(r = 2, m = 2)
↓
D(r = 4, m = 4)
has to be
A(r = 1, m = 4) → B(r = 3, m = 3) ← C(r = 2, m = 3)
↓
D(r = 4, m = 4)
I searched SO and found some Here, but one of the answers does not bound in time and another answer is very badly explained. Is there any simpler idea here?
In practice, I would use use the algorithm from Ehsan's answer, but it's not quite O(V+E). If you really need that complexity, then you can do this:
Divide the graph into strongly-connected components using, e.g., Tarjan's algorithm This is O(V+E).
Make a graph of the SCCs. Every node in an SCC is reachable from every other one, so the node for each SCC in the new graph gets the highest r value in the SCC. You can do this in O(V+E) too.
The graph of SCCs is acyclic, so you can do a topological sort. All the popular algorithms for that are O(V+E).
Process the SCC nodes in reverse topological order, calculating each m from neighbors. Because all the edges point from later to earlier nodes, the inputs for each node will be finished by the time you get to it. This is O(V+E) too.
Go through the original graph, setting every node's m to the value for its component in the SCC graph. O(V)
Use following O(E+V*log(V)) algorithm :
- Reverse all directions
- while |V| > 0 do
find max(v) from remaining nodes in V
from that node execute DFS and find all reachable nodes and update their m as max(V)
remove all updated nodes from V
the time-complexity of this algorithm is as your request O(V*log(V)+E)
How to solve the problem?
Reachable vertices in a directed graph
Which vertices can a given vertex visit?
Which vertices can visit the given vertex?
We are dealing with directed graphs. So, we need to find strongly connected components to answer the questions like above efficiently for this problem.
Once we know the strongly connected components, we can deal with the highest worthiness part.
In every strongly connected component, what is the highest worthiness value? Update accordingly.
Both steps are possible with O(V + E). With proper thought process, I believe it should be able to do both the steps in a single pass.
How to find strongly connected components?
Kosaraju's algorithm
Tarjan's algorithm
Path-based strong component algorithm
If you are looking for something simple, go for Kosaraju's algorithm. To me, it is the simplest of the above three.
If you are looking for efficiency, Kosaraju's algorithm takes two depth-first traversals but the other two algorithms accomplish the same within 1 depth-first traversal.
A Space-Efficient Algorithm for Finding Strongly Connected Components mentions that Tarjan’s algorithm required at most v(2 + 5w) bits of storage, where w is the machine’s word size. The improvement mentioned in the paper reduces the space requirements to v(1 + 3w) bits in the worst case.
Implementation:
Apparently, you are looking for some type of implementation.
For the mentioned 3 ways of finding strongly connected components, you can find java implementation here.
There are multiple Path-based strong component algorithms. To my knowledge, Gabow's algorithm is much simpler to understand than Tarjan's algorithm and the latest in path-based strong component algorithms. You can find java implementation for Gabow's algorithm here.
I am adding this answer, although there are correct answers with upvotes before me, only because you tagged java and python. So I will add java implementation now, and if needed the python implementation will follow.
The algorithm
This is a tweak on the classic topological sort:
foreach vertex:
foreach neighbour:
if didn't yet calculate m, calculate.
Take the maximum of yourself and neighbours. Mark yourself as visited, and if asked again for m, return the calculated.
It is implemented at calculateMostValuableVertex.
Time computation complexity
foreach vertex (O(|V|))
2. foreach edge(O(|E|) totally, as it will eventually go over each edge once.):
If not yet computed, compute m.
Please note that foreach vertex, it will be calculated either in stage 1, or 3. not twice, wince it is checked before the calculation.
Therefore the time complexity of this algorithm is O(|V| + |E|)
Assumptions
This solution relies heavily on the fact that HashMap in Java does operations such as add/update in O(1). That is true in average, but if that is not enough, the same idea can be fully implemented only with arrays, which will improve the solution into O(|V|+|E|) in the worst case.
Implementation
Let's first define the basic classes:
Vertex:
import java.util.ArrayList;
class Vertex {
String label;
public int r; // Worthiness
public int m; // Highest worthiness.
Vertex(String label, int r, int m) {
this.label = label;
this.r = r;
this.m = m;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result * r * m
+ ((label == null) ? 0 : label.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Vertex other = (Vertex) obj;
boolean labelEquals;
if (label == null) {
labelEquals = other.label == null;
} else {
labelEquals = label.equals(other.label);
}
return labelEquals && r == other.r && m == other.m;
}
#Override
public String toString() {
return "Vertex{" +
"label='" + label + '\'' +
", r=" + r +
", m=" + m +
'}';
}
}
It is important to define the methods equals and hashCode so later on their hash computations will work as expected.
Graph:
class Graph {
private final Map<Vertex, List<Vertex>> adjVertices = new HashMap<>();
private final Map<String, Vertex> nameToVertex = new HashMap<>();
private final List<Vertex> vertices = new ArrayList<>();
void addVertex(String label, int r, int m) {
Vertex vertex = new Vertex(label, r, m);
adjVertices.putIfAbsent(vertex, new ArrayList<>());
nameToVertex.putIfAbsent(label, vertex);
vertices.add(vertex);
}
void addEdge(String label1, String label2) {
adjVertices.get(nameToVertex.get(label1)).add(nameToVertex.get(label2));
}
public void calculateMostValuableVertex() {
Map<Vertex, Boolean> visitedVertices = new HashMap<>();
for (Vertex vertex : vertices) {
visitedVertices.put(vertex, false);
}
for (Vertex vertex : vertices) {
if (visitedVertices.get(vertex)) {
continue;
}
calculateMostValuableVertexInternal(vertex, visitedVertices);
}
}
public void calculateMostValuableVertexInternal(Vertex vertex, Map<Vertex, Boolean> visitedVertices) {
List<Vertex> neighbours = adjVertices.get(vertex);
visitedVertices.put(vertex, true);
int max = vertex.r;
for (Vertex neighbour: neighbours) {
if (visitedVertices.get(neighbour)) {
max = Math.max(max, neighbour.m);
} else {
calculateMostValuableVertexInternal(neighbour, visitedVertices);
max = Math.max(max, neighbour.m);
}
}
vertex.m = max;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
Iterator<Map.Entry<Vertex, List<Vertex>>> iter = adjVertices.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Vertex, List<Vertex>> entry = iter.next();
sb.append(entry.getKey());
sb.append('=').append('"');
sb.append(entry.getValue());
sb.append('"');
if (iter.hasNext()) {
sb.append(',').append('\n');
}
}
return "Graph{" +
"adjVertices=\n" + sb +
'}';
}
}
Finally, to run the above logic, you can do:
Graph g = new Graph();
g.addVertex("A", 1, 1);
g.addVertex("B", 3, 3);
g.addVertex("C", 2, 2);
g.addVertex("D", 4, 4);
g.addEdge("A", "B");
g.addEdge("C", "B");
g.addEdge("A", "D");
g.calculateMostValuableVertex();
System.out.println(g);
The output of the above is:
Graph{adjVertices=
Vertex{label='A', r=1, m=4}="[Vertex{label='B', r=3, m=3}, Vertex{label='D', r=4, m=4}]",
Vertex{label='D', r=4, m=4}="[]",
Vertex{label='B', r=3, m=3}="[]",
Vertex{label='C', r=2, m=3}="[Vertex{label='B', r=3, m=3}]"}
as expected. It supports graphs with cycles as well. For example the output of:
Graph g = new Graph();
g.addVertex("A", 1, 1);
g.addVertex("B", 3, 3);
g.addVertex("C", 2, 2);
g.addVertex("D", 4, 4);
g.addVertex("E", 5, 5);
g.addVertex("F", 6, 6);
g.addVertex("G", 7, 7);
g.addEdge("A", "B");
g.addEdge("C", "B");
g.addEdge("A", "D");
g.addEdge("A", "E");
g.addEdge("E", "F");
g.addEdge("F", "G");
g.addEdge("G", "A");
g.calculateMostValuableVertex();
System.out.println(g);
is:
Graph{adjVertices=
Vertex{label='A', r=1, m=7}="[Vertex{label='B', r=3, m=3}, Vertex{label='D', r=4, m=4}, Vertex{label='E', r=5, m=7}]",
Vertex{label='B', r=3, m=3}="[]",
Vertex{label='C', r=2, m=3}="[Vertex{label='B', r=3, m=3}]",
Vertex{label='D', r=4, m=4}="[]",
Vertex{label='E', r=5, m=7}="[Vertex{label='F', r=6, m=7}]",
Vertex{label='F', r=6, m=7}="[Vertex{label='G', r=7, m=7}]",
Vertex{label='G', r=7, m=7}="[Vertex{label='A', r=1, m=7}]"}
I implemented my answer from the linked question in Python. The lines that don't reference minreach closely follow Wikipedia's description of Tarjan's SCC algorithm.
import random
def random_graph(n):
return {
i: {random.randrange(n) for j in range(random.randrange(n))} for i in range(n)
}
class SCC:
def __init__(self, graph):
self.graph = graph
self.index = {}
self.lowlink = {}
self.stack = []
self.stackset = set()
self.minreach = {}
self.components = []
def dfs(self, v):
self.lowlink[v] = self.index[v] = len(self.index)
self.stack.append(v)
self.stackset.add(v)
self.minreach[v] = v
for w in self.graph[v]:
if w not in self.index:
self.dfs(w)
self.lowlink[v] = min(self.lowlink[v], self.lowlink[w])
elif w in self.stackset:
self.lowlink[v] = min(self.lowlink[v], self.index[w])
self.minreach[v] = min(self.minreach[v], self.minreach[w])
if self.lowlink[v] == self.index[v]:
component = set()
while True:
w = self.stack.pop()
self.stackset.remove(w)
self.minreach[w] = self.minreach[v]
component.add(w)
if w == v:
break
self.components.append(component)
def scc(self):
for v in self.graph:
if v not in self.index:
self.dfs(v)
return self.components, self.minreach
if __name__ == "__main__":
g = random_graph(6)
print(g)
components, minreach = SCC(g).scc()
print(components)
print(minreach)
Assume i have a word like this; mert . I want to to search for all 1 letter difference combinations for that word. aert, ert, meat,mmert, merst,merts etc. are all applicable. So my regular expression is like
[a-z]{0,2}ert OR m[a-z]{0,2}rt OR me[a-z]{0,2}t OR mer[a-z]{0,2}
So for n letter difference, i just replace 2 with n-1 and you can'T get all combinations.
My question is this; Is there any shorter way of writing this regexp?
Thanks
Please check this solution, I have test this code below. It seems to work.
/**
* Then function will return list of the words matched with nth_difference
*
* #param pattern search pattern
* #param data input data
* #param nth_difference difference
* #return
*/
static List<String> getNthDifferenceWords(String pattern, String[] data, int nth_difference) {
Map<Character, Integer> frequencyTable = new HashMap<>();
List<String> matchedWords = new ArrayList<>();
//Code complexity : O(n)
for (int i = 0; i < pattern.length(); ++i) {
frequencyTable.put(pattern.charAt(i), 1);
}
//Code complexity : O(m) where m is size of entire input;
for (String input : data) {
int matchCounter = 0;
for (int j=0; j<input.length(); ++j){
if(frequencyTable.containsKey(input.charAt(j))){
++matchCounter;
}
}
//System.out.println("matched=" + matchCounter);
if(input.length() <= pattern.length() && (matchCounter == pattern.length() - nth_difference)){
matchedWords.add(input);
}
if((input.length() - pattern.length() == 1) && (matchCounter >= input.length() - nth_difference)){
matchedWords.add(input);
}
}
return matchedWords;
}
public static void main(String[] args) {
int nth_difference = 1;
String pattern = "mert";
String[] data = new String[]{"aert", "ert", "meat", "mmert", "merst", "merts","meritos"};
System.out.println(getNthDifferenceWords(pattern,data,nth_difference));
nth_difference = 2;
pattern = "merit";
data = new String[]{"aert", "ert", "meat", "mmert", "merst", "merts","demerit","merito", "meritos"};
System.out.println(getNthDifferenceWords(pattern,data,nth_difference));
}
For a 1-letter difference, pre-build a table in the following way. Build a 2-column lexicon with the 'word' in the second column, and the following in the first column: One position at a time, remove one letter from the word.
Example: "meat" is the word; here are the rows for it in the table:
`col1` `col2`
------ ------
meat meat
eat meat
mat meat
met meat
mea meat
For "meet" (note the dup letter):
meet meet
eet meet
met meet -- only needed once
mee meet
Then test in a similar way. When searching for "mert", do
WHERE col1 IN ('mert', 'ert', 'mrt', 'met', 'ert')
Note that you will get both "meat" and "meet" from the above example. Note also what will happen with "met" and "meets".
And, it checks for simple transpositions. Searching for "meta":
WHERE col1 IN ('meta', 'eta', 'mta', 'mea', 'met')
will find "meat", "meet" (and other words like met, mean, ...) Arguably, "meta" -> "mean" is a 2-letter distance, but oh well.
Checking your test cases-- mert vs
aert -- via "ert"
ert -- via "ert"
meat -- via "met"
mmert -- via "mert"
merst -- via "mert"
merts -- via "mert"
Meanwhile, have PRIMARY KEY(col1, col2), INDEX(col2) on that table.
So I am aware that the bog standard Genetic Algorithm uses a string/array of binary digits as the population and then creates a series of Chromosomes out of this. After running, the chromosome with the highest fitness is presumed to be the most optimal solution. My question is, can I use array references as a replacement for the binary string/array.
For example, I am trying to create an algorithm which can automate aircraft queueing for a single runway. There are two inputs, aircraft wishing to take-off and aircraft wanting to land. Without going into too much detail, when an aircraft flys it produces distorted air behind it (Wake Turbulence) which can be extremely dangerous to succeeding aircraft. The weight/size of the aircraft is directly proportional to the size of the Wake Turbulence it produces. To stop it endangering other aircraft there is a required waiting period, which depends on the size of the leading aircraft, between each aircraft. An example of this is shown below:
Succeeding Aircraft Lead Aircraft Wake Turbulence Gap (NM)
------------------- ------------- --------------------------
H H 4
M H 5
S H 6
L H 7
H M 3
...
Where H = Heavy, M = Medium, S = Small, L = Light, NM = Nautical Miles;
This data will be kept in a separate array which can be called by the fitness function. What I am wondering is whether I can make an effective genetic algorithm that mainly utilises Crossover because I cannot see a way how I could use Mutation.
The population would look like:
input: N001,N002,N003,N004,N005,...,N###
Either separated by "," as a string or in a 1D array.
Each Gene (i.e. N001) would refer to a position in a 2D array where the Wake Turbulence Category (H,M,S,L) and its desired action (Take-Off or Landing) would be stored. (i.e dataArray[001][1] = Wake Turbulence Category)
To calculate the fitness I have come up with this:
input = "N001.N002.N003.N004.N005.N006. ... Nnnn";
String [] aircraft = input.split(".");
double totalWeight = 0;
for (i = 0; i <= aircraft.length; i++) {
priority = Array[i+1][1];
action1 = Array[i][2];
action2 = Array[i+1][2];
wakeTurb1 = Array[i][3];
wkaeTurb2 = Array[i+1][3];
if(priority == 1) {
totalWeight = totalWeight + 2^i;
}
if(action1 == 0 && action2 == 0) {
wakeTurbVal = tAftT[wakeTurb2][wakeTurb1]; }
else if(action1 == 0 && action2 == 1) {
wakeTurbVal = lAftT[wakeTurb2][wakeTurb1]; }
else if(action1 == 1 && action2 == 1) {
wakeTurbVal = lAftL[wakeTurb2][wakeTurb1]; }
else if(action1 = 1 && action2 == 0) {
wakeTurbVal = tAftL[wakeTurb2][wakeTurb1]; }
totalWeight = totalWeight + wakeTurbVal;
}
Where priority 1 is an emergency and needs to land quickly. tAftL (Take-Off after a Landing) = an array where accurate wake turbulence values are stored for specific scenarios (Scenarios: tAftT, tAftL, lAftL, laftT). The array Array is basically a database with values stored for each aircraft.
After running through the input, the resultant fitness for each chromosome would be 1/totalWeight.
How would I build a Genetic Algorithm on this population and fitness function?
Your assistance would be greatly appreciated. Thank you in advance.
Following a question here OP is interested in listing all unique 2x2 games. Games here are game theory games in which there with two players and two strategies each. Hence, there are four possible outcomes (see diagram). These outcomes comes with 'payoffs' for each players. Payoff 'pairs' are two payoffs for each player from some combinations of strategies. Payoffs are given in integers and cannot exceed 4.
For instance, consider the following example of a 2x2 game (with a payoff pair is written in the brackets, and P1 and P2 denote player 1 and 2 respectively):
P2
Right Left
Up (2,2) (3,4)
P1
Down (1,1) (4,3)
The payoffs here take the values [ (2,2),(3,4) | (1,1),(4,3) ].
Now, clearly many other games (i.e. unique payoff matrices) are possible. If payoffs for each players is given by 1,2,3,4 (which we can permute in 4!=24 ways) then 24*24 games are possible. OP was interested with listing all these games.
Here comes the subtle part: two unique payoff matrices may nevertheless represent games if one can be obtained from the other by
i) exchanging columns (i.e. relabel Player A's strategies)
ii) exchanging rows (i.e. relabel Player B's strategies)
iii) Exchange the players (i.e. exchanging the payoff pairs and
mirroring the matrix along the first diagonal)
OP posted the following code that correctly lists all 78 possible games in which the payoffs for each can be (1,2,3,4).
I am interested in changing the code so that the program lists all unique games where the possible payoffs are different: i.e. (1,2,3,3) for player 1 and (1,2,3,4) for player 2. Here, there would be 4!/2! ways of permuting (1,2,3,3) and therefore fewer games.
#!/usr/bin/groovy
// Payoff Tuple (a,b) found in game matrix position.
// The Tuple is immutable, if we need to change it, we create a new one.
// "equals()" checks for equality against another Tuple instance.
// "hashCode()" is needed for insertion/retrievel of a Tuple instance into/from
// a "Map" (in this case, the hashCode() actually a one-to-one mapping to the integers.)
class Tuple {
final int a,b
Tuple(int a,int b) {
assert 1 <= a && a <= 4
assert 1 <= b && b <= 4
this.a = a
this.b = b
}
#!/usr/bin/groovy
// Payoff Tuple (a,b) found in game matrix position.
// The Tuple is immutable, if we need to change it, we create a new one.
// "equals()" checks for equality against another Tuple instance.
// "hashCode()" is needed for insertion/retrievel of a Tuple instance into/from
// a "Map" (in this case, the hashCode() actually a one-to-one mapping to the integers.)
class Tuple {
final int a,b
Tuple(int a,int b) {
assert 1 <= a && a <= 4
assert 1 <= b && b <= 4
this.a = a
this.b = b
}
boolean equals(def o) {
if (!(o && o instanceof Tuple)) {
return false
}
return a == o.a && b == o.b
}
int hashCode() {
return (a-1) * 4 + (b-1)
}
String toString() {
return "($a,$b)"
}
Tuple flip() {
return new Tuple(b,a)
}
}
// "GameMatrix" is an immutable structure of 2 x 2 Tuples:
// top left, top right, bottom left, bottom right
// "equals()" checks for equality against another GameMatrix instance.
// "hashCode()" is needed for insertion/retrievel of a GameMatrix instance into/from
// a "Map" (in this case, the hashCode() actually a one-to-one mapping to the integers)
class GameMatrix {
final Tuple tl, tr, bl, br
GameMatrix(Tuple tl,tr,bl,br) {
assert tl && tr && bl && br
this.tl = tl; this.tr = tr
this.bl = bl; this.br = br
}
GameMatrix colExchange() {
return new GameMatrix(tr,tl,br,bl)
}
GameMatrix rowExchange() {
return new GameMatrix(bl,br,tl,tr)
}
GameMatrix playerExchange() {
return new GameMatrix(tl.flip(),bl.flip(),tr.flip(),br.flip())
}
GameMatrix mirror() {
// columnEchange followed by rowExchange
return new GameMatrix(br,bl,tr,tl)
}
String toString() {
return "[ ${tl},${tr} | ${bl},${br} ]"
}
boolean equals(def o) {
if (!(o && o instanceof GameMatrix)) {
return false
}
return tl == o.tl && tr == o.tr && bl == o.bl && br == o.br
}
int hashCode() {
return (( tl.hashCode() * 16 + tr.hashCode() ) * 16 + bl.hashCode() ) * 16 + br.hashCode()
}
}
// Check whether a GameMatrix can be mapped to a member of the "canonicals", the set of
// equivalence class representatives, using a reduced set of transformations. Technically,
// "canonicals" is a "Map" because we want to not only ask the membership question, but
// also obtain the canonical member, which is easily done using a Map.
// The method returns the array [ canonical member, string describing the operation chain ]
// if found, [ null, null ] otherwise.
static dupCheck(GameMatrix gm, Map canonicals) {
// Applying only one of rowExchange, colExchange, mirror will
// never generate a member of "canonicals" as all of these have player A payoff 4
// at topleft, and so does gm
def q = gm.playerExchange()
def chain = "player"
if (q.tl.a == 4) {
}
else if (q.tr.a == 4) {
q = q.colExchange(); chain = "column ∘ ${chain}"
}
else if (q.bl.a == 4) {
q = q.rowExchange(); chain = "row ∘ ${chain}"
}
else if (q.br.a == 4) {
q = q.mirror(); chain = "mirror ∘ ${chain}"
}
else {
assert false : "Can't happen"
}
assert q.tl.a == 4
return (canonicals[q]) ? [ canonicals[q], chain ] : [ null, null ]
}
// Main enumerates all the possible Game Matrixes and builds the
// set of equivalence class representatives, "canonicals".
// We only bother to generate Game Matrixes of the form
// [ (4,_) , (_,_) | (_,_) , (_,_) ]
// as any other Game Matrix can be trivially transformed into the
// above form using row, column and player exchange.
static main(String[] argv) {
def canonicals = [:]
def i = 1
[3,2,1].permutations { payoffs_playerA ->
[4,3,2,1].permutations { payoffs_playerB ->
def gm = new GameMatrix(
new Tuple(4, payoffs_playerB[0]),
new Tuple(payoffs_playerA[0], payoffs_playerB[1]),
new Tuple(payoffs_playerA[1], payoffs_playerB[2]),
new Tuple(payoffs_playerA[2], payoffs_playerB[3])
)
def ( c, chain ) = dupCheck(gm,canonicals)
if (c) {
System.out << "${gm} equivalent to ${c} via ${chain}\n"
}
else {
System.out << "${gm} accepted as canonical entry ${i}\n"
canonicals[gm] = gm
i++
}
}
}
}
I have attempted changing the "assert 1 <= a && a <= 4" to "assert 1 <= a && a <= 3" and then changing the 4's to a 3 further down in the code. This does not seem to work.
I am not sure however what the "int hashCode() {return (a-1) * 4 + (b-1)" or if "(q.tl.a == 4) {
}
else if (q.tr.a == 4) {" does and therefore not sure how to change this.
Apart from this, I suspect that the flips and exchanges can remain the way they are, since this should produce a procedure for identifying unique games no matter what the specific payoff set is (i.e. whether it's 1,2,3,4 or 1,2,3,3).
I have calculated the number of unique games for different payoff sets by hand which may be useful for reference.
I had a similar situation making an AI for Othello/Reversi, and wanting the state-space to be as small as possible to remove redundant processing.
The technique I used was to represent the game as a set of meta-states, or in your case, meta-outcomes, where each meta consists of all the permutations which are equivalent. Listing and identifying equivalent permutations involved coming up with a normalization scheme which determines which orientation or reflection is the key for the meta instance. Then all new permutations are transformed to normalize them before comparing to see if they represented a new instance.
In your case, if swapping rows and columns are both considered equivalent, you might consider the case where the orientation of sorted order puts the smallest value in the top-left corner and the next smallest adjacent value in the top-right corner. This normalizes all 4 flip positions (identity, h-flip, v-vlip, hv-flip) into a single representation.
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
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;
}