I have been given a problem to solve that I am fairly certain its insoluble.
For a system I am working in I need to take piece of branching logic (graph) and translate it to a linear path(flatten it), without node repeats. Given a tree I know that I can do this.
The rules are that the path must be traversed in order, but can 'skip' any panel if some condition is met.
Given the tree:
A > B > C
&&
A > D > E
Our tree can be flattened to:
A > B > C > D > E
So in this case B and C share the same conditional, and D, and E have the inverse of that condition. Thus if B is met so is C, but D and E will be skipped. Conversely, if B is not met, B and C are skipped, but D and E aren't.
So far, so simple. I am fairly convinced this is true for any tree. The problem I have is that the objects I have been given to flatten are graphs, and contain simple cycles, and closed walks.
After that huge preamble my questions are:
Am I right in stating that it is impossible to guarantee that such a graph can be flattened?
I know that closed walks cannot follow my rules (by virtue of returning to a node), but are there any other rules that describe a 'flatten-able' graph versus a 'non-flatten-able' one?
Cheers
If it is a directed graph, then the graph can be flattened if there are no directed cycles.
There is a handy library available JGraphT which will provide the necessary methods to determine if there is a cycle presnet as well a TopologicalOrderIterator which will perform the flattening as well.
Using the graph library and the example above this code will show an exmaple of how to do it.
DirectedGraph<String, DefaultEdge> graph = new DefaultDirectedGraph<String, DefaultEdge>(DefaultEdge.class);
graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addVertex("D");
graph.addVertex("E");
// A > B
graph.addEdge("A", "B");
// B > C
graph.addEdge("B", "C");
// A > D
graph.addEdge("A", "D");
// D > E
graph.addEdge("D", "E");
// Uncomment the following line to create a cyclic graph.
//graph.addEdge("E", "D");
CycleDetector<String, DefaultEdge> cycleDector = new CycleDetector<String, DefaultEdge>(graph);
if (cycleDector.detectCycles()) {
System.err.println("Cyclic graph");
} else {
StringBuilder sb = new StringBuilder();
// Create topological order iterator
for (TopologicalOrderIterator<String, DefaultEdge> iter = new TopologicalOrderIterator<String, DefaultEdge>(
graph); iter.hasNext();) {
String vertex = iter.next();
if (sb.length() > 0) {
sb.append(" > ");
}
sb.append(vertex);
}
System.out.println(sb.toString());
}
Sample output with the cycle disabled.
A > B > D > C > E
Related
im trying to implement the prim algorithm in julia.
My function gets the adjacency matrix with the weights but isnt working correctly. I dont know what i have to change. There is some problem with the append!() function i guess.
Is there maybe another/better way to implement the algorithm by just passing the adjacency matrix?
Thank you.
function prims(AD)
n = size(AD)
n1 = n[1]
# choose initial vertex from graph
vertex = 1
# initialize empty edges array and empty MST
MST = []
edges = []
visited = []
minEdge = [nothing, nothing, float(Inf)]
# run prims algorithm until we create an MST
# that contains every vertex from the graph
while length(MST) != n1 - 1
# mark this vertex as visited
append!(visited, vertex)
# add each edge to list of potential edges
for r in 1:n1
if AD[vertex][r] != 0
append!(edges, [vertex, r, AD[vertex][r]])
end
end
# find edge with the smallest weight to a vertex
# that has not yet been visited
for e in 1:length(edges)
if edges[e][3] < minEdge[3] && edges[e][2] not in visited
minEdge = edges[e]
end
end
# remove min weight edge from list of edges
deleteat!(edges, minEdge)
# push min edge to MST
append!(MST, minEdge)
# start at new vertex and reset min edge
vertex = minEdge[2]
minEdge = [nothing, nothing, float(Inf)]
end
return MST
end
For example. When im trying the algorithm with this adjacency Matrix
C = [0 2 3 0 0 0; 2 0 5 3 4 0; 3 5 0 0 4 0; 0 3 0 0 2 3; 0 4 4 2 0 5; 0 0 0 3 5 0]
i get
ERROR: BoundsError
Stacktrace:
[1] getindex(::Int64, ::Int64) at .\number.jl:78
[2] prims(::Array{Int64,2}) at .\untitled-8b8d609f2ac8a0848a18622e46d9d721:70
[3] top-level scope at none:0
I guess i have to "reshape" my Matrix C in a form like this
D = [ [0,2,3,0,0,0], [2,0,5,3,4,0], [3,5,0,0,4,0], [0,3,0,0,2,3], [0,4,4,2,0,5], [0,0,0,3,5,0
]]
But also with this i get the same Error.
First note that LightGraphs.jl has this algorithm implemented. You can find the code here.
I have also made some notes on your algorithm to make it working and indicate the potential improvements without changing its general structure:
using DataStructures # library defining PriorityQueue type
function prims(AD::Matrix{T}) where {T<:Real} # make sure we get what we expect
# make sure the matrix is symmetric
#assert transpose(AD) == AD
n1 = size(AD, 1)
vertex = 1
# it is better to keep edge information as Tuple rather than a vector
# also note that I add type annotation for the collection to improve speed
# and make sure that the stored edge weight has a correct type
MST = Tuple{Int, Int, T}[]
# using PriorityQueue makes the lookup of the shortest edge fast
edges = PriorityQueue{Tuple{Int, Int, T}, T}()
# we will eventually visit almost all vertices so we can use indicator vector
visited = falses(n1)
while length(MST) != n1 - 1
visited[vertex] = true
for r in 1:n1
# you access a matrix by passing indices separated by a comma
dist = AD[vertex, r]
# no need to add edges to vertices that were already visited
if dist != 0 && !visited[r]
edges[(vertex, r, dist)] = dist
end
end
# we will iterate till we find an unvisited destination vertex
while true
# handle the case if the graph was not connected
isempty(edges) && return nothing
minEdge = dequeue!(edges)
if !visited[minEdge[2]]
# use push! instead of append!
push!(MST, minEdge)
vertex = minEdge[2]
break
end
end
end
return MST
end
I've been implementing higher order functions recursively with .foldRight() like any, all, and takeWhile as practice, but dropWhile has been elusive. _Collections.kt has the imperative way but I couldn't convert it to a recursive structure.
For reference, this is takeWhile
fun takeWhile(list:List<Int>, func:(Int) -> Boolean):List<Int> = list.foldRight(emptyList(),
{ next:Int, acc:List<Int> -> if (func(next)) acc.plus(next) else emptyList() })
First, let's outline the idea of the solution.
With foldRight, you can only process the items one by one from right to left, maintaining an accumulator.
The problem is, for an item at position i, the dropWhile logic makes a decision whether to include the item into the result or not based on whether there is an item at position j <= i that does not satisfy the predicate (include if yes). This means you cannot simply maintain the result items: for some items you already processed, you don't know if they should actually be included.
Example:
(we're processing the items right-to-left, so the prefix is unknown to us)
... (some unknown items) ... ... ... ... a b c d <--- (right-to-left)
predicate satisfied: T T F T
As we discover more items on the left, there are two possibilities:
We found the beginning of the sequence, and there were no items that gave F on the predicate:
(the sequence start) y z a b c d <--- (right-to-left)
predicate satisfied: T T T T F T
-------
drop
In this case, the prefix y z a b should be dropped.
We found an item that does not satisfy the predicate:
... (some unknown items) ... w z a b c d <--- (right-to-left)
predicate satisfied: F T T T F T
-------
include
Only at this point we know for sure that we need to include the items w z a b, we could not do that earlier because there could be the beginning of the sequence instead of item w, and then we should have dropped z a b.
But note that in both cases we are certain that the items c d are to be included into the result: that's because they have c with F predicate in front of them.
Given this, it becomes clear that, when processing the items right-to-left, you can maintain a separate list of items that are not certain to be included into the result and are either to be dropped or to be included when a false predicate result is encountered, together with the item that gave such false result.
My implementation:
I used a pair of two lists for the accumulator, where the first list is for the items that are certain to be included, and the second one for those which are not.
fun <T> List<T>.myDropWhile(predicate: (T) -> Boolean) =
foldRight(Pair(emptyList<T>(), emptyList<T>())) { item, (certain, uncertain) ->
if (predicate(item))
Pair(certain, uncertain + item) else
Pair(certain + uncertain + item, emptyList())
}.first.reversed()
Example:
val ints = listOf(0, 0, 0, 1, 0, 2, 3, 0, 0, 4)
println(ints.myDropWhile { it == 0 }) // [1, 0, 2, 3, 0, 0, 4]
See: runnable demo of this code with more tests.
Note: copying a read-only list by doing uncertain + item or certain + uncertain + item in each iteration gives O(n^2) worst-case time complexity, which is impractical. Using mutable data structures gives O(n) time.
I'm trying to create a route, given a start node and end node, that will travel to every single node in the graph, and minimize the cost of doing so.
The graph is undirected, and every node is connected to each other directly. The weight of every edge is positive. I think because every node connects to eachother, that there are many "loops" in my graph, but I don't want to generate a route with a loop in it.
So, for a graph with N nodes, I have (N*N-1) directed edges. A graph with nodes A,B,C,D would have edges:
A to B / B to A
A to C / C to A
A to D / D to A
B to C / C to B
C to D / D to C
B to D / D to B
When I implement the Floyd Warshall algorithm from Wikipedia, I only ever get an array of 2 nodes. There's a function in the article that gives you the shortest path from node U to node V, and that's the function that only returns [U,V] (array containing U and V)
I MUST be misunderstanding what it is exactly that Floyd Warshall is meant to solve. I'll attach my code to show how I've implemented it in javascript.
function colorsToEdgeMatrix(colors){
var dist = [];
for(var i = 0; i < colors.length;i++){
dist[i] = [];
var c1 = colors[i];
for(var j = 0; j < colors.length;j++){
if(i == j){continue;}
var c2 = colors[j];
dist[i][j] = colorDistance(c1,c2);
}
}
return dist;
}
function colorsToNextMatrix(colors){
var next = [];
for(var i = 0; i < colors.length;i++){
next[i] = [];
for(var j = 0; j < colors.length;j++){
if(i == j){continue;}
next[i][j] = j;
}
}
return next;
}
//lab colors
function FloydWarshallWithPathReconstruction (colors){
var next = [];
var dist = colorsToEdgeMatrix(colors);
var next = colorsToNextMatrix(colors);
var N = colors.length;
for(var k = 0; k < N; k++){ // standard Floyd-Warshall implementation
for(var i = 0; i < N; i++){
for(var j = 0; j < N; j++){
if(dist[i][k] + dist[k][j] < dist[i][j]){
dist[i][j] = dist[i][k] + dist[k][j]
next[i][j] = next[i][k]
}
}
}
}
return next;
}
function Path(next,u, v) {
var path = [];
if(next[u][v] == null){
return []
}
path = [u]
while(u != v){
u = next[u][v]
path.push(u)
}
return path;
}
var lab = randomLABArray(100); //make an array of LAB color space colors. a LAB element has an array structure [L,a,b]
lab = sortLuminosityLAB(lab); //sorts the LAB colors from light to dark
var next = FloydWarshallWithPathReconstruction(lab); //gets all paths using floyd warshall
var path = Path(next, 0, lab.length-1); //gets the path calculated from lightest to darkest
console.log( path );
Does this algorithm not necessarily return a path that goes through every node? I guess what it does is just spits out the best path for every start and end node, and doesn't guarantee any path goes through every node...
I used the Nearest Neighbor algorithm with decent result, and Brute Force is impossible after 10 elements. I was hoping the Floyd Warshall would give even better results
Huh...so this might actually be a Hamiltonian Path problem and isn't as simple as I thought...
This can be reduced to the Traveling Salesman problem as follows. Pick a large number M which is greater than the sum of all weights in the graph. Add this number to the weights on all edges in the graph except the edge connecting the start node and the end node. That edge should have its cost set to zero. Solve the resulting Traveling Salesman Problem. It is easy to see that the optimal solution of the TSP will include the edge connecting the start and end node. Throw that edge away from the optimal solution and adjust the weights back to their original value -- and you have found the optimal solution to your problem.
Conversely, the regular TSP can be reduced to your problem in an even easier way. Pick a node at random and duplicate it. Let one of these newly duplicated nodes be the start node and the other be the end node. Solve your optimal path problem for this instance. Then -- remerge these two nodes into the original node, which will splice the ends together to form a circuit, which is easily seen to be optimal. This confirms your intuition that the problem is at least as hard as the Hamiltonian circuit problem.
Hello,
I would like to know about an algorithm to produce a graph decomposition into branches with rank in the following way:
Rank | path (or tree branch)
0 1-2
1 2-3-4-5-6
1 2-7
2 7-8
2 7-9
The node 1 would be the Root node and the nodes 6, 8 and 9 would be the end nodes.
the rank of a branch should be given by the number of bifurcation nodes up to the root node. Let's assume that the graph has no loops (But I'd like to have no such constraint)
I am electrical engineer, and perhaps this is a very standard problem, but so far I have only found the BFS algorithm to get the paths, and all the cut sets stuff. I also don't know if this applies.
I hope that my question is clear enough.
PS: should this question be in stack overflow?
From your example, I'm making some assumptions:
You want to bifurcate whenever a node's degree is > 2
Your input graph is acyclic
With an augmented BFS this is possible from the root r. The following will generate comp_groups, which will be a list of components (each of which is a list of its member vertices). The rank of each component will be under the same index in the list rank.
comp[1..n] = -1 // init all vertices to belong to no components
comp[r] = 0 // r is part of component 0
comp_groups = [[r]] // a list of lists, with the start of component 0
rank[0] = 0 // component 0 (contains root) has rank 0
next_comp_id = 1
queue = {r} // queues for BFS
next_queue = {}
while !queue.empty()
for v in queue
for u in neighbors(v)
if comp[u] == -1 // test if u is unvisited
if degree(v) > 2
comp[u] = next_comp_id // start a new component
next_comp_id += 1
rank[comp[u]] = rank[comp[v]] + 1 // new comp's rank is +1
comp_groups[comp[u]] += [v] // add v to the new component
else
comp[u] = comp[v] // use same component
comp_group[comp[u]] += [u] // add u to the component
next_queue += {u} // add u to next frontier
queue = next_queue // move on to next frontier
next_queue = {}
the data i am having is like, i am trying this from week am not able to find any solution.
I need to do this using either pivot using c# or using lists. Kindly provide the answers. immediate.
Key Value
A e
B f
C i
D j
A k
B l
C m
D n
i need something like this
A B C D
-------
e f i j
k l m n
where the first line is a column header.
Any better link of any stackoverflow question also appreciable.
By following code am able to get distinct columns, now problem is with assigning values in rows.
please provide any better way of doing this.
foreach (DataRow row in dtBackupData.Rows)
{
keyname = row["KeyName"].ToString();
if (!keyNameList.Contains(keyname))
{
keyNameList.Add(keyname);
dtDynamic.Columns.Add(keyname, typeof(string));
}
}