I have a data type Graph which looks like this:
data Graph w = Graph {vertices :: [(Char, w)],
edges :: [(Char, Char, w)]} deriving Show
This is representing a directed acyclic graph. Where vertices have a char identifier ('a' for the first vertice added, 'b' for the second and so on) and a weight. Edges are two vertice identifiers and a weight.
I'm thinking about making the vertices a bit more complex, maybe they should contain a list of all neighbours?
The topological ordering looks like this so far:
topological_ordering :: Graph w -> [Char]
topological_ordering (Graph v w) =
let startingNodes = getStartNodes (Graph v w)
emptyList = []
sorted = sortAlgorithm startingNodes emptyList (Graph v w)
in sorted
sortAlgorithm :: [Char] -> [Char] -> Graph w -> [Char]
sortAlgorithm startingNodes sorted (Graph v w) =
| [] _ _ = []
| (x:startingNodes) sorted (Graph v w) =
let sorted = sorted ++ [x]
neigbours = findNeighbours (Graph v w) x
getStartNodes :: Graph w -> [Char]
getStartNodes (Graph v w) =
let set1 = Set.fromList $ firstNodes w
set2 = Set.fromList $ secondNodes w
startNodes = Set.toList $ Set.difference set1 set2
in startNodes
firstNodes :: [(Char, Char, w)] -> [Char]
firstNodes [] = []
firstNodes (x:xs) = selectFirst x:firstNodes xs
secondNodes :: [(Char, Char, w)] -> [Char]
secondNodes [] = []
secondNodes (x:xs) = selectSecond x:secondNodes xs
From there I'm a little lost. I don't really know how to complete the sortAlgorithm, because I want it to be recursive (or use foldl/foldr?). Should implement the data type for Graph in another way or should I continue with this?
I just started haskell a few weeks ago and still feel a bit lost on functional programming.
Thanks
You might want to take a look at how elegantly it is done in Data.Graph. Here is an outline of the algorithm:
topSort :: Graph -> [Vertex]
topSort = reverse . postOrd
postOrd :: Graph -> [Vertex]
postOrd = postorderF . dff
postorder :: Tree a -> [a]
postorder (Node a ts) = postorderF ts ++ [a]
postorderF :: Forest a -> [a]
postorderF ts = concat (map postorder ts)
-- | A spanning forest of the graph, obtained from a depth-first search of
-- the graph starting from each vertex in an unspecified order.
dff :: Graph -> Forest Vertex
dff g = dfs g (vertices g)
-- | A spanning forest of the part of the graph reachable from the listed
-- vertices, obtained from a depth-first search of the graph starting at
-- each of the listed vertices in order.
dfs :: Graph -> [Vertex] -> Forest Vertex
That is, a topological sort of a graph is (the reverse of) a post-order traversal of a spanning forest of the graph.
Here is an example of how to use it:
import qualified Data.Graph as G
{-
5 --> 7
| |
v V
1 --> 4 --> 8
-}
(myGraph,vertexToNode,keyToVertex) = G.graphFromEdges [
("node4",4,[8]), -- the first component can be of any type
("node8",8,[]),
("node7",7,[4]),
("node5",5,[1,7]),
("node1",1,[4])
]
sorted = map vertexToNode $ G.topSort myGraph
-- [("node5",5,[1,7]),("node7",7,[4]),("node1",1,[4]),("node4",4,[8]),("node8",8,[])]
Do you have a solid algorithmic approach how to tackle topological sort? There are different possibilities; the two best-known are probably the following:
Do a DFS on the graph and sort the vertices according to their finish time in descending order. So: If you already have DFS, adapt it do output finish times and sort vertices in descending order.
The other approach requires you to store the number of incoming, not-yet-processed edges into each vertex (this possibly requires some preprocessing, usually one graph traversal - let's call the corresponding field for each vertex the "edge counter"). Starting nodes - of course - have edge counter = 0. As the next vertex, you can only pick those whose edge counter is set to 0. If you encounter an edge (a,b,w), you have to decrement the edge counter of b by 1.
Note that this second approach can be implemented in a way such you have a list candidates that is initially only filled with the starting nodes. As soon as you decrement the edge counter of b and see that it is now 0, you add b to the candidates. In the next step, you pick the head of candidates as the next vertex to process.
To store the edge count, you could use e.g. a HashMap.
Here some (non-haskell, but probably-close-to-haskell) inspiration for the second approach:
sortAlgorithm startingNodes sorted (Graph v w) edgeCounts =
| [] _ _ = sorted -- processed all nodes? => output result
| (x:remainingNodes) sorted (Graph v w) =
let newEdgeCounts = foldl
(\ec (a, b, w) -> Data.HashMap.insert ((Data.HashMap.findWithDefault 0 b ec) - 1) ec)
in sortAlgorithm remainingNodes (sorted ++ [x]) newEdgeCounts
Related
I would like to perform the Edmond matching algorithm or Blossom algorithm on a Graph (example Graph in picture), but how to I start with a empty matching set?
The Algorithm work this way:
Given: Graph G and matching M in G
Task: find matching M' with |M'| =
[M| + 1, or |M'| = IM| if M maximum
1 let F be the forest consisting of all M-exposed nodes; 2 while there
is outer node x and edge {x, y) with y \in V(F), add (x, y} and
matching edge covering y to F;
3 if there are adjacent outer nodes x, y in same tree, then shrink
cycle (M-blossom) in F \cup {x, y) and go to Step 2;
4 if there are adjacent outer nodes x, y in different trees, then
augment M along M-augmenting path P(x) \cup {x, y} \cup P(y);
5 in reverse order, undo each shrinking and re-establish near-perfect
matchings in blossoms.
You don’t begin the algorithm with an empty M. You have to provide one, generally by generating it with a greedy algorithm that parses all edges e of the graph G and adds each e to M if M + e form a matching.
I need to find a 'dynamic - programming' kind of solution for the following problem:
Input:
Perfect Binary-Tree, T = (V,E) - (each node has exactly 2 children except the leafs).
V = V(blue) ∪ V(black).
V(blue) ∩ V(black) = ∅.
(In other words, some vertices in the tree are blue)
Root of the tree 'r'.
integer k
A legal Solution:
A subset of vertices V' ⊆ V which is a vertex cover of T, and |V' ∩ V(blue)| = k. (In other words, the cover V' contains k blue vertices)
Solution Value:
The value of a legal solution V' is the number of vertices in the set = |V'|.
For convenience, we will define the value of an "un-legal" solution to be ∞.
What we need to find:
A solution with minimal Value.
(In other words, The best solution is a solution which is a cover, contains exactly k blue vertices and the number of vertices in the set is minimal.)
I need to define a typical sub-problem. (Like, if i know what is the value solution of a sub tree I can use it to find my value solution to the problem.)
and suggest a formula to solve it.
To me, looks like you are on the right track!
Still, I think you will have to use an additional parameter to tell us how far is any picked vertex from the current subtree's root.
For example, it can be just the indication whether we pick the current vertex, as below.
Let fun (v, b, p) be the optimal size for subtree with root v such that, in this subtree, we pick exactly b blue vertices, and p = 1 if we pick vertex v or p = 0 if we don't.
The answer is the minimum of fun (r, k, 0) and fun (r, k, 1): we want the answer for the full tree (v = r), with exactly k vertices covered in blue (b = k), and we can either pick or not pick the root.
Now, how do we calculate this?
For the leaves, fun (v, 0, 0) is 0 and fun (v, t, 1) is 1, where t tells us whether vertex v is blue (1 if yes, 0 if no).
All other combinations are invalid, and we can simulate it by saying the respective values are positive infinities: for example, for a leaf vertex v, the value fun (v, 3, 1) = +infinity.
In the implementation, the infinity can be just any value greater than any possible answer.
For all internal vertices, let v be the current vertex and u and w be its children.
We have two options: to pick or not to pick the vertex v.
Suppose we pick it.
Then the value we get for f (v, b, 1) is 1 (the picked vertex v) plus the minimum of fun (u, x, q) + fun (w, y, r) such that x + y is either b if the vertex v is black or b - 1 if it is blue, and q and r can be arbitrary: if we picked the vertex v, the edges v--u and v--w are already covered by our vertex cover.
Now let us not pick the vertex v.
Then the value we get for f (v, b, 0) is just the minimum of fun (u, x, 1) + fun (w, y, 1) such that x + y = b: if we did not pick the vertex v, the edges v--u and v--w have to be covered by u and w.
I have a question.
Given a directed graph (G = V, E) and the source vertex s from V group.
we want to check whether there is a simple path (no circles) from s to any vertex in G with at least 5 edges.
Offer as efficient an algorithm as possible that solves the problem for a graph G that can contain circles.
please I need your help
Thanks :-)
We need to find any 5-edge simple directed path starting at vertex s. This path will look like:
s -> a -> b -> c -> d -> e (all distinct)
Now let's go through the all possible values of c (any vertex besides s) and then for every c value we can go through all edges that do not contain s and c vertices and for the edge (x, y) do the following:
if edge (s, x) exists and edge (y, c) exists
put (x, y) in AB edges list
if edge (c, x) exists
put (x, y) in DE edges list
This can be done in O(|E|). Then we need to find a pair of edges (E1, E2) such that E1 is in AB, E2 is in DE and they don't share any vertex in common. The latter can be done in O(|E|).
We can take a graph G' = (V, DE) and find the degrees of the vertices. Then for every edge (a, b) from AB we need to check that
degree(a) + degree(b) = |DE| + x
where x = 1 if (a, b) is in DE, otherwise x = 0. If this equality does not hold it means that there is an edge in DE that contains neither a nor b and we can just iterate through entire DE to find the answer.
The overall complexity will be O(|V||E|) with O(|E|) additional memory.
I'm having some trouble trying to represent and manipulate dependency graphs in this scenario:
a node has some dependencies that have to be solved
every path must not have dependencies loops (like in DAG graphs)
every dependency could be solved by more than one other node
I starts from the target node and recursively look for its dependencies, but have to mantain the above properties, in particular the third one.
Just a little example here:
I would like to have a graph like the following one
(A)
/ \
/ \
/ \
[(B),(C),(D)] (E)
/\ \
/ \ (H)
(F) (G)
which means:
F,G,C,H,E have no dependencies
D dependends on H
B depends on F and G
A depends on E and
B or
C or
D
So, if I write down all the possible topological-sorted paths to A I should have:
E -> F -> G -> B -> A
E -> C -> A
E -> H -> D -> A
How can I model a graph with these properties? Which kind of data structure is the more suitable to do that?
You should use a normal adjacency list, with an additional property, wherein a node knows its the other nodes that would also satisfy the same dependency. This means that B,C,D should all know that they belong to the same equivalence class. You can achieve this by inserting them all into a set.
Node:
List<Node> adjacencyList
Set<Node> equivalentDependencies
To use this data-structure in a topo-sort, whenever you remove a source, and remove all its outgoing edges, also remove the nodes in its equivalency class, their outgoing edges, and recursively remove the nodes that point to them.
From wikipedia:
L ← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edges
while S is non-empty do
remove a node n from S
add n to tail of L
for each node o in the equivalency class of n <===removing equivalent dependencies
remove j from S
for each node k with an edge e from j to k do
remove edge e from the graph
if k has no other incoming edges then
insert k into S
for each node m with an edge e from n to m do
remove edge e from the graph
if m has no other incoming edges then
insert m into S
if graph has edges then
return error (graph has at least one cycle)
else
return L (a topologically sorted order)
This algorithm will give you one of the modified topologicaly-sorted paths.
Let G = (V, E) be a weighted, connected and undirected graph. Let T1 and T2 be 2 different MST's. Suppose we can write E = (A1 U B U A2) such that:
B is the intersection of the edges of T1 and T2, and
A1 = T1 - B
A2 = T2 - B
Assuming that every MST T in G contains all the edges of B, find an algorithm that decides whether there is a MST T that contains at least one edge in A1 and at least one edge in A2.
Edit: I've dropped the part that was here. I think that it does more harm than good.
you should sort your edge that the red edge is prefer to blue edge for choose.then you can use any MST algorithm same as Prim's algorithm :
If a graph is empty then we are done immediately. Thus, we assume
otherwise. The algorithm starts with a tree consisting of a single
vertex, and continuously increases its size one edge at a time, until
it spans all vertices. Input: A non-empty connected weighted graph
with vertices V and edges E (the weights can be negative). Initialize:
Vnew = {x}, where x is an arbitrary node (starting point) from V, Enew
= {} Repeat until Vnew = V: Choose an edge {u, v} with minimal weight such that u is in Vnew and v is not (if there are multiple edges with
the same weight, any of them may be picked) Add v to Vnew, and {u, v}
to Enew Output: Vnew and Enew describe a minimal spanning tree