public Tcsp(ConstraintNetwork constraintNetwork) { Nodes = constraintNetwork.Nodes; Edges = new Dictionary <Tuple <Node, Node>, MetricEdge>(); foreach (var edgeKey in constraintNetwork.Edges.Keys) { MetricEdge edge = (MetricEdge)constraintNetwork.Edges[edgeKey]; edge.GenerateAllowedIntervals(); Edges.Add(edgeKey, edge); } }
/// <summary> /// Recursively solves a TCSP /// </summary> /// <param name="unprocessedEdges">The TCSP unprocessed edges</param> /// <param name="selectedLabels">The current active edge intervals</param> /// <returns>The first consistent solution</returns> private Stp SolveTcsp(Dictionary <Tuple <Node, Node>, MetricEdge> unprocessedEdges, Dictionary <Tuple <Node, Node>, Interval> selectedLabels) { if (selectedLabels.Count == this.edgesCounts) { Stp completeStp; stopwatch1.Start(); completeStp = new Stp(selectedLabels); completeStp.ApplyDPC(completeStp.Nodes); stopwatch1.Stop(); this.ExaminedStps++; if (completeStp.IsConsistent) { completeStp.ApplyAPSP(); return(completeStp); } else { return(null); } } else { // Ordering the edges has a huge impact on the performance // Here the Beginning of time edges are processed first Tuple <Node, Node> currEdgeKey = unprocessedEdges.Keys.OrderBy(x => x.Item1).First(); MetricEdge currEdge = unprocessedEdges[currEdgeKey]; // Removing the explored edge unprocessedEdges.Remove(currEdgeKey); // Explore all possible intervals in the selected edge foreach (var interval in currEdge.AllowedIntervals) { Stp partialStp; // inserting the interval data in the selected labels selectedLabels.Add(currEdgeKey, interval); stopwatch55.Start(); partialStp = new Stp(selectedLabels); partialStp.ApplyDPC(partialStp.Nodes); stopwatch55.Stop(); // If the partial assignment is consistent continue with the assignment if (partialStp.IsConsistent) { Stp solution = SolveTcsp(unprocessedEdges, selectedLabels); // If a solution is available return it if (solution != null) { return(solution); } else { // The current labeling has to be removed before continuing selectedLabels.Remove(currEdgeKey); } } else { // The current labeling has to be removed before continuing selectedLabels.Remove(currEdgeKey); } } // If no solution is found the edge is returned to the list of unprocessed ones unprocessedEdges.Add(currEdgeKey, currEdge); return(null); } }
/// <summary> /// Adds a configuration constraint /// </summary> /// <param name="constraint">The constraint to add</param> /// <param name="constrNetworks">The list of possible constraint networks where the constraint can e added</param> /// <param name="log"></param> private static void ApplyMetricConstraint(ConfigurationConstraint constraint, List <ConstraintNetwork> constrNetworks, Log log) { IMetricRelation relation = constraint.AllowedRelations[0] as IMetricRelation; if (relation == null) { log.AddItem(LogType.Warning, String.Format("A constraint ({0}) is skipped during the generation of a metric constraint network, because it is {1} relation and not recognized as metric.", constraint.DomainConstraint.Name, constraint.AllowedRelations[1].RelationFamily.Name)); } else { ConstraintNetwork constraintNetwork = constrNetworks.Single(x => constraint.GetIncludedNodes().All(y => x.Nodes.Contains(y))); Node startNode = (relation as BinaryRelation).GetStartNode(constraint); Node endNode = (relation as BinaryRelation).GetEndNode(constraint); Tuple <Node, Node> edgeKey = new Tuple <Node, Node>(startNode, endNode); Tuple <Node, Node> reverseEdgeKey = new Tuple <Node, Node>(endNode, startNode); List <Interval> intervals = relation.GetDifferenceIntervals(constraint); // Check if the edge already exists if (constraintNetwork.Edges.ContainsKey(edgeKey)) { // Adding the current constraint to the edge MetricEdge edge = constraintNetwork.Edges[edgeKey] as MetricEdge; ConfigurationConstraint equalConstraint = edge.Constraints.SingleOrDefault(x => x.Equals(constraint)); // Add the constraint if an equal one doesn't already exist if (equalConstraint == null) { edge.AddConstraintIntervals(constraint, intervals, log); } else { // Adding the constraints as implied by a previous one edge.ImpliedConstraints.Add(constraint); constraint.EqualActiveConstraint = equalConstraint; } } // Check if the reverse of the edge exists else if (constraintNetwork.Edges.ContainsKey(reverseEdgeKey)) { // Adding the inverse constraint to the mirror edge MetricEdge edge = constraintNetwork.Edges[reverseEdgeKey] as MetricEdge; IMetricRelation asMetricConstraint = (IMetricRelation)constraint.AllowedRelations[0]; ConfigurationConstraint inverseConstraint = asMetricConstraint.GetInverseConstraint(constraint); IMetricRelation inverseAsMetricConstraint = (IMetricRelation)inverseConstraint.AllowedRelations[0]; ConfigurationConstraint equalConstraint = edge.Constraints.SingleOrDefault(x => x.Equals(inverseConstraint)); // Since the inverse constraint is used, it should be included instead of the current one in the constraint tree constraint.OwningTree.SwitchConstraint(constraint, inverseConstraint); // Add the constraint if an equal one doesn't already exist if (equalConstraint == null) { edge.AddConstraintIntervals(inverseConstraint, inverseAsMetricConstraint.GetDifferenceIntervals(inverseConstraint), log); } else { // Adding the constraints as implied by a previous one edge.ImpliedConstraints.Add(inverseConstraint); inverseConstraint.EqualActiveConstraint = equalConstraint; } } // Adding the new edge with the found intervals else { MetricEdge edge = new MetricEdge(constraintNetwork, edgeKey.Item1, edgeKey.Item2); edge.AddConstraintIntervals(constraint, intervals, log); constraintNetwork.Edges.Add(edgeKey, edge); } } }