public EdgeList matchingStringsToEdgeList(BipartiteGraph G, List <string> M_String) { var M_to_EdgeListM = new EdgeList(); GraphNode nd1, nd2; foreach (string edg in M_String) { nd1 = G.GetNode(edg.Split('-')[0]); nd2 = G.GetNode(edg.Split('-')[1]); if (G.Contains(nd1, nd2)) { M_to_EdgeListM.Add(G.Edges.FindByNodes(nd1, nd2)); } else if (G.Contains(nd2, nd1)) { M_to_EdgeListM.Add(G.Edges.FindByNodes(nd2, nd1)); } //else //{ // M_to_EdgeListM.Add(new Edge(nd1,nd2,0)); //} } return(M_to_EdgeListM); }
private Node GetNode(string from) { if (G.duplicateModToModel.ContainsKey(from)) { from = G.duplicateModToModel[from]; } return(G.GetNode(from)); }
private bool IsFeasiblePath(BipartiteGraph G, MatchingList path, NodeList unmatchedNodes) { if (unmatchedNodes.Contains(G.GetNode(path[0])) || unmatchedNodes.Contains(G.GetNode(path[2]))) { return(true); } return(false); }
//YHB: this method find the graph G_minus by deleting given edge-e from the G i.e. given graph private static BipartiteGraph BuildGminus(BipartiteGraph G, Edge e) { BipartiteGraph Gminus = G.Clone(); GraphNode from = G.GetNode(e.FromNode.Value); GraphNode to = G.GetNode(e.ToNode.Value); if (G.Contains(from, to)) { Gminus.RemoveDirectedEdge(from, to); } else { Gminus.RemoveDirectedEdge(to, from); } return(Gminus); }
private Edge GetEdgeInPathNotInM(BipartiteGraph G, MatchingList M, MatchingList path) { Edge e = null; string edge = path.Except(M).ToList()[0]; string[] nodes = edge.Split('-'); GraphNode node1 = G.GetNode(nodes[0]); GraphNode node2 = G.GetNode(nodes[1]); if (G.Contains(node1, node2)) { e = G.Edges.FindByNodes(node1, node2); } else if (G.Contains(node2, node1)) { e = G.Edges.FindByNodes(node2, node1); } return(e); }
private Edge getEdgeInPathNotInM(BipartiteGraph G, List <String> M, List <String> path) { Edge e = null; String eString = path.Except(M).ToList()[0]; String[] eNodes = eString.Split('-'); GraphNode nd1 = G.GetNode(eNodes[0]); GraphNode nd2 = G.GetNode(eNodes[1]); if (G.Contains(nd1, nd2)) { e = G.Edges.FindByNodes(nd1, nd2); } else if (G.Contains(nd2, nd1)) { e = G.Edges.FindByNodes(nd2, nd1); } return(e); }
private bool isFeasiblePath(BipartiteGraph G, List <String> path, NodeList unmatchedNodes) { bool isFeasiblePath = false; if (unmatchedNodes.Contains(G.GetNode(path[0])) || unmatchedNodes.Contains(G.GetNode(path[2]))) { isFeasiblePath = true; } return(isFeasiblePath); }
public static EdgeList Get(BipartiteGraph bipartiteGraph) { NodeList models = bipartiteGraph.ModelsSet; if (models is null) { throw new ArgumentException("Graph has no models", nameof(bipartiteGraph)); } NodeList variables = bipartiteGraph.VariablesSet; if (variables is null) { throw new ArgumentException("Graph has no variables", nameof(bipartiteGraph)); } //Assigning int values to each node in the graph starting from 0. var modNodeIntMap = models.Select((m, i) => new KeyValuePair <string, int>(m.Value, i)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); //Creating Adjacency List var adjacencyList = new List <int[]>(variables.Count); foreach (GraphNode variable in variables) { adjacencyList.Add(variable.Neighbors.Select(n => modNodeIntMap[n.Value]).ToArray()); } // Get Match IList <int> match = new HopcroftKarpClass(adjacencyList, models.Count).GetMatching(); // Format the match var MatchingEdgeList = new EdgeList(); int idx = 0; foreach (Node variable in variables) { int matchedModelIndex = match[idx]; if (matchedModelIndex != -1) { string modelValue = modNodeIntMap.FirstOrDefault(x => x.Value == matchedModelIndex).Key; //matching edge list contains edges having direction from MatchingEdgeList.Add(bipartiteGraph.Edges.FindByNodes(variable, bipartiteGraph.GetNode(modelValue))); // 'variables set' to 'model set' idx++; } else { idx++; /*variable associated at that location is unmatched*/ //Implement to store unmatched variable information if required } } return(MatchingEdgeList); }
//This method find the corresponding edges of matching M(which contains edges from other Graph) for the given Graph G private static EdgeList CorrespondingEdgeList(BipartiteGraph G, EdgeList M) { var corresponding = new EdgeList(); foreach (Edge edge in M) { GraphNode from = G.GetNode(edge.FromNode.Value); GraphNode to = G.GetNode(edge.ToNode.Value); if (from == null && to == null) { continue; } if (G.Edges.FindByNodes(from, to) != null) { corresponding.Add(G.Edges.FindByNodes(from, to)); } else { corresponding.Add(G.Edges.FindByNodes(to, from)); } } return(corresponding); }
private EdgeList MatchingToEdgeList(BipartiteGraph G, MatchingList M_String) { var edgeList = new EdgeList(); foreach (string edg in M_String) { GraphNode node1 = G.GetNode(edg.Split('-')[0]); GraphNode node2 = G.GetNode(edg.Split('-')[1]); if (G.Contains(node1, node2)) { edgeList.Add(G.Edges.FindByNodes(node1, node2)); } else if (G.Contains(node2, node1)) { edgeList.Add(G.Edges.FindByNodes(node2, node1)); } //else //{ // M_to_EdgeListM.Add(new Edge(nd1,nd2,0)); //} } return(edgeList); }
private static EdgeList CorrespondingListForTheGraph(BipartiteGraph G, EdgeList M) //This method find the corresponding edges of matching M(which contains edges from other Graph) for the given Graph G { var M_corresp = new EdgeList(); foreach (Edge edg in M) { GraphNode frm = G.GetNode(edg.FromNode.Value); GraphNode to = G.GetNode(edg.ToNode.Value); if (frm == null && to == null) { goto xyz; } if (G.Edges.FindByNodes(frm, to) != null) { M_corresp.Add(G.Edges.FindByNodes(frm, to)); } else { M_corresp.Add(G.Edges.FindByNodes(to, frm)); } xyz :; } return(M_corresp); }
private MatchingList PathToMatching(BipartiteGraph G, MatchingList path) { var matching = new MatchingList(); string edge; for (int i = 0; i < path.Count() - 1; i++) { if (G.GetNode(path[i]).NodeType == GraphNode.Type.Type2) { edge = EdgeString(path[i], path[i + 1]); } else { edge = EdgeString(path[i + 1], path[i]); } matching.Add(edge); } return(matching); }
private List <String> pathToEdgesAsStrings(BipartiteGraph G, List <String> path) //04-01-2017 Added for MaximumMatchings { var pathAsStrings = new List <String>(); String str; for (int i = 0; i < path.Count() - 1; i++) { if (G.GetNode(path[i]).NodeType == GraphNode.Type.Type2) { str = path[i] + '-' + path[i + 1]; } else { str = path[i + 1] + '-' + path[i]; } pathAsStrings.Add(str); } return(pathAsStrings); }
private static BipartiteGraph G_minus_e(BipartiteGraph G, Edge e) {//YHB: this method find the graph G_minus by deleting given edge-e from the G i.e. given graph BipartiteGraph G_minus = G; if (G.Contains(G.GetNode(e.FromNode.Value), G.GetNode(e.ToNode.Value))) { G_minus.RemoveDirectedEdge(G.GetNode(e.FromNode.Value), G.GetNode(e.ToNode.Value)); } else { G_minus.RemoveDirectedEdge(G.GetNode(e.ToNode.Value), G.GetNode(e.FromNode.Value)); } return(G_minus); }
private static MatchingDictionary MatchModelsWithVariablesGlobal(List <Data> allData, List <WorkflowComponent> components, GlobalReversalMode mode) { if (mode == GlobalReversalMode.NoReversedModels || mode == GlobalReversalMode.Global) { List <WorkflowComponent> originalComponents = components.GetAllComponents(); Dictionary <string, IOStatus> status = originalComponents.GetInputsOutputsStatus(allData, out List <Data> inputs, out List <Data> outputs); foreach (string key in status.Keys) { if (status[key] == IOStatus.Conflict) { throw new ArgumentException($"The following varibale \"{key}\" is of non-reversible type and output of more than one model. Therefore the workflow cannot be created"); } } var inputsHash = new HashSet <string>(inputs.Select(d => d.Id)); var bipartite = new BipartiteGraph(); Primes.Reset(); var completeMatching = new MatchingDictionary(originalComponents.Select(c => c.Id)); // 1.1 Add Nodes for the Variables // Filter-out the selected inputs and outputs, as they don't belong to the bipartite graph foreach (Data data in allData.Where(d => !inputsHash.Contains(d.Id))) { bipartite.AddNode(data.Id, GraphNode.Type.Type1); } // 1.2 Add Nodes for the Models, and edges between Variables and Nodes foreach (WorkflowComponent component in originalComponents) { completeMatching.Add(component.Id, new HashSet <string>()); bipartite.AddNode(CS(component.Id), GraphNode.Type.Type2); GraphNode modelNode = bipartite.GetNode(CS(component.Id)); // Filter-out the selected inputs, as they don't belong to the bipartite graph foreach (Data data in component.ModelDataInputs.Where(d => !inputsHash.Contains(d.Id))) { bipartite.AddDirectedEdge(data.Id, modelNode, Primes.Next(), 1); } // Filter-out the selected inputs, as they don't belong to the bipartite graph foreach (Data data in component.ModelDataOutputs.Where(d => !inputsHash.Contains(d.Id))) { bipartite.AddDirectedEdge(data.Id, modelNode, Primes.Next(), 0); } // How many output the model need if (component.ModelDataOutputs.Count > 1) { bipartite.modelAndItsOutputs.Add(CS(component.Id), component.ModelDataOutputs.Count); //signle output models are not stored } } // 1.3 Associate matchings to each model, maping models to set of outputs var matches = new MaximumMatchings2(bipartite, true); if (matches.OverConstrainedModels.Count > 0) { throw new ArgumentException($"The inputs conbination is not valid as the following models are overconstraint:\r\n\t" + matches.OverConstrainedModels.Aggregate((total, last) => total += "\r\n\t" + last) + "\r\n"); } Matching matching = matches.OrderedFilteredMaximumMatchings.FirstOrDefault() ?? throw new NullReferenceException("NO suitable matchings were found"); completeMatching.CompleteWithMatching(matching); return(completeMatching); } else { Dictionary <string, IOStatus> status = components.GetInputsOutputsStatus(allData, out List <Data> inputs, out List <Data> outputs); var inputsHash = new HashSet <string>(inputs.Select(d => d.Id)); var outputsHash = new HashSet <string>(); List <WorkflowComponent> originalComponents = components.GetAllComponents(); Dictionary <string, IOStatus> originalStatus = originalComponents.GetDataStatus(allData); var nonReversibleData = allData.Where(d => !(d is DoubleData)).ToList(); Dictionary <string, IOStatus> nonReversibleStatus = components.GetDataStatus(nonReversibleData); foreach (string data in nonReversibleStatus.Keys) { if (nonReversibleStatus[data] == IOStatus.Input) { inputsHash.Add(data); // Should be already there } else if (nonReversibleStatus[data] == IOStatus.Output || nonReversibleStatus[data] == IOStatus.Both) { outputsHash.Add(data); } } var reversedInputsHash = new HashSet <string>(); var reversedOutputsHash = new HashSet <string>(); foreach (WorkflowComponent component in components) { if (component is IReversableWorkflow rw) { foreach (Data data in rw.ReversedInputs) { reversedInputsHash.Add(data.Id); } foreach (Data data in rw.ReversedOutputs) { reversedOutputsHash.Add(data.Id); } IEnumerable <Data> NonReversableReversedInputs = rw.ReversedInputs.Where(d => !(d is DoubleData)); IEnumerable <Data> NonReversableReversedOutputs = rw.ReversedOutputs.Where(d => !(d is DoubleData)); // If the model id the upper end of a reversal throug non-reversible variables. int difference = NonReversableReversedOutputs.Count() - NonReversableReversedInputs.Count(); while (difference > 0) { // Assign as many reversible variable to the inputs as reversals end in the component IEnumerable <Data> reversableReversedInputs = rw.ReversedInputs.Where(d => d is DoubleData); foreach (Data data in reversableReversedInputs.Take(difference)) { inputsHash.Add(data.Id); } } } } // Relax one input per reversal -> lowerEndOfReversal might have more elements than non-reversible reversal, but those should be already not in inputHash IEnumerable <string> lowerEndOfReversals = reversedOutputsHash.Except(reversedInputsHash); inputsHash.ExceptWith(lowerEndOfReversals); var bipartite = new BipartiteGraph(); Primes.Reset(); var completeMatching = new MatchingDictionary(originalComponents.Select(c => c.Id)); // 1.1 Add Nodes for the Variables // Filter-out the selected inputs and outputs, as they don't belong to the bipartite graph foreach (Data data in allData.Where(d => !inputsHash.Contains(d.Id) && !outputsHash.Contains(d.Id))) { bipartite.AddNode(data.Id, GraphNode.Type.Type1); } // 1.2 Add Nodes for the Models, and edges between Variables and Nodes foreach (WorkflowComponent component in originalComponents) { completeMatching.Add(component.Id, new HashSet <string>()); // if the component has all its inputs and outputs determined do not add to the graph bool addModel = component.ModelDataOutputs.Count > component.ModelDataOutputs.Where(d => inputsHash.Count > -1 && outputsHash.Contains(d.Id)).Count(); if (addModel) { bipartite.AddNode(component.Id, GraphNode.Type.Type2); } GraphNode modelNode = bipartite.GetNode(component.Id); int uniqueNonReversibleOutputs = 0; // Filter-out the selected inputs, as they don't belong to the bipartite graph foreach (Data data in component.ModelDataInputs.Where(d => !inputsHash.Contains(d.Id) && !outputsHash.Contains(d.Id))) { bipartite.AddDirectedEdge(data.Id, modelNode, Primes.Next(), 1); } // Filter-out the selected inputs, as they don't belong to the bipartite graph foreach (Data data in component.ModelDataOutputs.Where(d => !inputsHash.Contains(d.Id))) { if (outputsHash.Contains(data.Id)) { uniqueNonReversibleOutputs++; completeMatching[component.Id].Add(data.Id); } else { bipartite.AddDirectedEdge(data.Id, modelNode, Primes.Next(), 0); } } // How many output the model need if (component.ModelDataOutputs.Count - uniqueNonReversibleOutputs > 1 && addModel) { bipartite.modelAndItsOutputs.Add(component.Id, component.ModelDataOutputs.Count - uniqueNonReversibleOutputs); //signle output models are not stored } } // 1.3 Associate matchings to each model, maping models to set of outputs var matches = new MaximumMatchings2(bipartite, true); if (matches.OverConstrainedModels.Count > 0) { throw new ArgumentException($"The inputs conbination is not valid as the following models are overconstraint:\r\n\t" + matches.OverConstrainedModels.Aggregate((total, last) => total += "\r\n\t" + last) + "\r\n"); } Matching matching = matches.OrderedFilteredMaximumMatchings.FirstOrDefault() ?? throw new NullReferenceException("NO suitable matchings were found"); completeMatching.CompleteWithMatching(matching); return(completeMatching); } }
// A recursive function to find which vertices are connected. private void DFS(BipartiteGraph G, GraphNode v) { length2Path.Add(v.Value); if (_path2Count++ == 2) { return; } _count++; //mark this vertex as being visited _marked.Add(v.Value.ToString(), true); /* * for each vertex w in the linked list for vertex v * there exists an edge between v and w * if it is not in _marked it hasn't been visited * yet so mark it then check all the vertices * in it's linked list (it has edges to). * */ foreach (GraphNode w in v.Neighbors) { if (!_marked.ContainsKey(w.Value.ToString())) { if (_path2Count < 2) { DFS(G, w); } else if (_path2Count == 2) { if (unmatchedVertices.Contains(w) || unmatchedVertices.Contains(G.GetNode(length2Path[0]))) { DFS(G, w); } else { goto nextNeighbour; } } } else { goto nextNeighbour; } nextNeighbour :; } return; }
private static (MatchingDictionary completeMatching, MaximumMatchings2 matches) FindAllMatches(List <Data> inputs, List <Data> allData, List <WorkflowComponent> workflowComponents) { var inputsHash = new HashSet <string>(inputs.Select(d => d.Id)); var outputsHash = new HashSet <string>(); // 1.0. Check for non-reversible variables that are either only input or output var nonReversibleData = allData.Where(d => !(d is DoubleData)).ToList(); Dictionary <string, IOStatus> nonReversibleStatus = workflowComponents.GetDataStatus(nonReversibleData); //var collisionDictionary = new Dictionary<string, char>(); //foreach (var component in workflowComponents) //{ // foreach (var input in component.ModelDataInputs) // { // if (!(input is DoubleData)) // { // string inName = input.Id; // if (collisionDictionary.ContainsKey(inName)) // collisionDictionary[inName] = 'b'; // else // collisionDictionary[inName] = 'i'; // } // } // foreach (var output in component.ModelDataOutputs) // { // if (!(output is DoubleData)) // { // string outName = output.Id; // if (collisionDictionary.ContainsKey(outName)) // collisionDictionary[outName] = 'b'; // else // collisionDictionary[outName] = 'o'; // } // } //} foreach (string data in nonReversibleStatus.Keys) { if (nonReversibleStatus[data] == IOStatus.Input) { inputsHash.Add(data); } else if (nonReversibleStatus[data] == IOStatus.Output) { outputsHash.Add(data); } } var bipartite = new BipartiteGraph(); Primes.Reset(); var outputsDict = new MatchingDictionary(workflowComponents.Select(c => c.Id)); // 1.1 Add Nodes for the Variables // Filter-out the selected inputs and outputs, as they don't belong to the bipartite graph foreach (Data data in allData.Where(d => !inputsHash.Contains(d.Id) && !outputsHash.Contains(d.Id))) { bipartite.AddNode(data.Id, GraphNode.Type.Type1); } // 1.2 Add Nodes for the Models, and edges between Variables and Nodes foreach (WorkflowComponent component in workflowComponents) { int uniqueNonReversibleOutputs = 0; outputsDict.Add(component.Id, new HashSet <string>()); bipartite.AddNode(CS(component.Id), GraphNode.Type.Type2); GraphNode modelNode = bipartite.GetNode(CS(component.Id)); // Filter-out the selected inputs, as they don't belong to the bipartite graph foreach (Data data in component.ModelDataInputs.Where(d => !inputsHash.Contains(d.Id))) { if (outputsHash.Contains(data.Id)) { // Shouldn't arrive here uniqueNonReversibleOutputs++; outputsDict[component.Id].Add(data.Id); } else { bipartite.AddDirectedEdge(data.Id, modelNode, Primes.Next(), 1); } } // Filter-out the selected inputs, as they don't belong to the bipartite graph foreach (Data data in component.ModelDataOutputs.Where(d => !inputsHash.Contains(d.Id))) { if (outputsHash.Contains(data.Id)) { uniqueNonReversibleOutputs++; outputsDict[component.Id].Add(data.Id); } else { bipartite.AddDirectedEdge(data.Id, modelNode, Primes.Next(), 0); } } // How many output the model need if (component.ModelDataOutputs.Count - uniqueNonReversibleOutputs > 1) { bipartite.modelAndItsOutputs.Add(CS(component.Id), component.ModelDataOutputs.Count - uniqueNonReversibleOutputs); //signle output models are not stored } else if (component.ModelDataOutputs.Count - uniqueNonReversibleOutputs == 0) { bipartite.Remove(CS(component.Id)); } } // 1.3 Associate matchings to each model, maping models to set of outputs var matches = new MaximumMatchings2(bipartite, getAllMatchings: true); return(outputsDict, matches); }
public void findOverconstrainedModelsReversalCost(List <String> M, out List <string> overConstrainedModelsList, out List <string> unmappedVariablesList, out int revCost) { revCost = 0;//04102017 overConstrainedModelsList = new List <string>(); unmappedVariablesList = new List <string>(); if (M != null) //after filtering the matchings from list_AllMaximumMatchings { //foreach (GraphNode gn in web1.getUnmatchedVerticesOfGraph(maxT.list_AllMaximumMatchings[n])) //original code foreach (GraphNode gn in G.GetUnmatchedVertices(M)) //after filtering the matchings { if (gn.NodeType == GraphNode.Type.Type2) { if (G.duplicateModToModel.ContainsKey(gn.Value)) { overConstrainedModelsList.Add(G.duplicateModToModel[gn.Value]); } else { overConstrainedModelsList.Add(gn.Value); } } else { unmappedVariablesList.Add(gn.Value); } } //for finding revCost of this matching //04102017 foreach (string match in M) //04102017 { //04102017 Entire added on //04102017 Node fromNode; Node toNode; string[] split = match.Split('-'); string from = split[0]; string to = split[1]; if (G.duplicateModToModel.ContainsKey(from)) { fromNode = G.GetNode(G.duplicateModToModel[from]); } else { fromNode = G.GetNode(from); } if (G.duplicateModToModel.ContainsKey(to)) { toNode = G.GetNode(G.duplicateModToModel[to]); } else { toNode = G.GetNode(to); } //Node from = this.G.GetNode(); Edge e = G.Edges.FindByNodes(fromNode, toNode); if (e == null) { e = G.Edges.FindByNodes(toNode, fromNode); //04102017 } revCost += e.Cost2; //04102017 }//04102017 } }