/// <summary> /// Generates TmsConstraints for the current constraint tree (including branches). /// Note: It does not generate constraints for the included configuration constraints, rather it only deals with branch combination logic /// </summary> /// <returns></returns> public List <TmsConstraint> GenerateTmsConstraints() { List <TmsConstraint> constraints = new List <TmsConstraint>(); // Only trees with branches generate constraints. The configuration constraints are not processed in this function if (this.IsCombination) { GKODomainAbstract boolDomain = TmsManager.GenerateBoolDomain(); IEnumerable <IEnumerable <string> > constraintDescriptions = this.GetSatDVarParts(); // Adding the constraints from each branch foreach (var branch in this.ConstraintBranches) { constraints.AddRange(branch.GenerateTmsConstraints()); } // Generating the TMS constraints for the current level foreach (var constraintDescription in constraintDescriptions) { TmsConstraint constraint = new TmsConstraint(); string currentDvarName = this.GetSatDVarName(constraintDescription); // The first elements of the constraint are the decision variables of the branches constraint.VariableTuple = constraintDescription.ToList(); // The last element is the decision variable of the constraint represented by the current tree constraint.VariableTuple.Add(currentDvarName); switch (this.CombinationType) { case DomainConstraintCombinationType.And: constraint.ConstraintType = constraintDescription.Count().GetAndCTName(); break; case DomainConstraintCombinationType.Or: constraint.ConstraintType = constraintDescription.Count().GetOrCTName(); break; case DomainConstraintCombinationType.ExactlyOne: constraint.ConstraintType = constraintDescription.Count().GetExactlyOneCTName(); break; default: throw new Exception("The chosen constraint combination type is not recognized!"); } constraints.Add(constraint); // This prohibits the constraint to be violated if it is hard constraint if (!this.DerivedFrom.CanBeViolated) { constraints.Add(TmsConstraint.GenerateSingleValueConstraint(boolDomain, currentDvarName, TmsManager.TrueValue)); } } } return(constraints); }
/// <summary> /// ! Use this only once (not for every relation) per edge constraint ! /// </summary> /// <param name="constraint"></param> /// <param name="edge"></param> /// <returns></returns> public override List <TmsConstraint> GetTmsConstraints(ConfigurationConstraint constraint, Edge edge) { ////OLD: Rem: Qualitative relations use composition constraints and constraint limiting the allowed relations between components, hence there are no constraints implied by a single relation //throw new NotSupportedException("A single qualitative relation do not imply a constraint!"); List <TmsConstraint> result = new List <TmsConstraint>(); RelationFamily relFamily = constraint.AllowedRelations[0].RelationFamily; if (!(edge is QualitativeEdge)) { edge.Network.SturcturalReasonerLog.AddItem(LogType.Warning, string.Format("Edge {0} is not a qualitative edge. The requested TMS constraints will not be added.", edge.GetUId())); } else if (!edge.Constraints.Contains(constraint)) { edge.Network.SturcturalReasonerLog.AddItem(LogType.Warning, string.Format("The constraint {0} is not found in the edge {1}. The requested TMS constraints will not be added.", constraint.DomainConstraint.Name, edge.GetUId())); } else if (relFamily == StructuralRelationsManager.GetRelationFamily(RelationFamilyNames.MetricRelationsName)) { edge.Network.SturcturalReasonerLog.AddItem(LogType.Warning, string.Format("The constraint {0} is metric while the needed relation for edge {1} is qualitative. The requested TMS constraints will not be added.", constraint.DomainConstraint.Name, edge.GetUId())); } else { QualitativeEdge qualEdge = (QualitativeEdge)edge; GKODomain calculusDomain = StructuralRelationsManager.GetDomain(constraint.AllowedRelations[0].RelationFamily.GetTmsRelationsDomainName()); TmsConstraint exactlyOneHoldsConstraint = new TmsConstraint(); List <string> relDvars = new List <string>(); // holds all relation variables GKODomain boolDomain = TmsManager.GenerateBoolDomain(); string dVarSat = constraint.GetSatDVarName(); // This will create a constraint saying that the edge dvar is matching the chosen relation and the relation's dvar is TRUE, or if they are not matching and the relation's dvar is FALSE foreach (var relation in constraint.AllowedRelations) { TmsConstraint tmsConstraint = new TmsConstraint(); string edgeDVar = qualEdge.GetDVarName(); string edgeRelDVar = qualEdge.GetDVarName((QualitativeRelation)relation); string constraintTypeName = calculusDomain.GetIndividualValueCTName(relation.Name); relDvars.Add(edgeRelDVar); tmsConstraint.ConstraintType = constraintTypeName; tmsConstraint.VariableTuple = new List <string>() { edgeDVar, edgeRelDVar }; result.Add(tmsConstraint); } // This will create the constraint saying that one of the relation dvars has to be set // This works because the calculi are JEPD exactlyOneHoldsConstraint.ConstraintType = relDvars.Count.GetExactlyOneCTName(); exactlyOneHoldsConstraint.VariableTuple = new List <string>(relDvars); exactlyOneHoldsConstraint.VariableTuple.Add(dVarSat); // This prohibits the constraint to be violated if (!constraint.CanBeViolated) { result.Add(TmsConstraint.GenerateSingleValueConstraint(boolDomain, dVarSat, TmsManager.TrueValue)); } result.Add(exactlyOneHoldsConstraint); } return(result); }
internal SolutionDataMetric SolveMetric(StructuralReasonerOptions options, TmsManager tms) { SolutionDataMetric solutionInformation = new SolutionDataMetric(this); solutionInformation.StartTime = DateTime.Now; //try //{ if (options.MetricReasoningAlgorithm == MetricReasoningAlgorithm.Tcsp) { Tcsp tcsp = new Tcsp(this); Stp solution = null; if (this.Edges.Values.Any(x => x.AllConstraints.Any(y => !y.OwningTreeRoot.IsValidForTcsp))) { solutionInformation.Log.AddItem(LogType.Error, string.Format("Disjunctive domain constraints are not allowed in TCSP!", this.UId)); } else { solutionInformation.Log.AddItem(LogType.Info, string.Format("Solving metric network {0} with TCSP", this.UId)); solution = tcsp.Solve(); solutionInformation.Log.AddItem(LogType.Info, string.Format("TCSP solving process complete ({0} ms)", (DateTime.Now - solutionInformation.StartTime).TotalMilliseconds)); } if (solution != null && solution.IsConsistent) { solutionInformation.SolutionFound = true; solutionInformation.Solution = solution.GetSolution(); } else { solutionInformation.SolutionFound = false; } } else { List <TmsDecisionVariable> tmsVariables = new List <TmsDecisionVariable>(); // Normal TMS variables List <TmsDecisionVariable> tmsUtilityVariables = new List <TmsDecisionVariable>(); // Utility TMS variables List <TmsConstraint> tmsConstraints = new List <TmsConstraint>(); HashSet <ConfigurationConstraintTree> relevantConstraintTrees = new HashSet <ConfigurationConstraintTree>(); GKODomainAbstract satisfiedDomain = tms.BoolDomain; GKODomainAbstract metricDomain = tms.MetricDomain; solutionInformation.Log.AddItem(LogType.Info, string.Format("Solving metric network {0} with CDA* started", this.UId)); solutionInformation.Stopwatch.Start(); // Adding all node decision variables foreach (var node in this.Nodes) { // The biginning of time is not relevant for the CDA* if (node != null) { tmsVariables.Add(new TmsDecisionVariable(metricDomain, node.GetDVarName())); } } // Processing configuration constraints in edges foreach (var edge in this.Edges.Values) { foreach (var constraint in edge.Constraints) { List <MetricRelationPart> metricParts = constraint.RelationParts.Where(x => x is MetricRelationPart).Select(x => (MetricRelationPart)x).ToList(); TmsConstraint tmsConstraint = new TmsConstraint(); // Creating the TMS constraint implied by the configuration constraint tmsConstraints.AddRange(constraint.AllowedRelations[0].GetTmsConstraints(constraint, edge)); // Each metric part in the constraint has its own decision variable which has to be created // Additionally, there is a hard constraint restricting the value of the variable to the single selected values foreach (var metricPart in metricParts) { // If the value of the metric part is already used it will have the same decision variable name if (!tmsVariables.Any(x => x.Name == metricPart.GetDVarName())) { tmsVariables.Add(new TmsDecisionVariable(metricDomain, metricPart.GetDVarName())); tmsConstraints.Add(TmsConstraint.GenerateSingleValueConstraint(StructuralRelationsManager.MetricDomain, metricPart.GetDVarName(), metricPart.GetValue())); } } } // Adding all configuration trees, from which the configuration constraints in edge are derived, in a set. This set is used later to generate the constraints combination and utility TMS variables and TMS constraints foreach (var constraint in edge.AllConstraints) { relevantConstraintTrees.Add(constraint.OwningTreeRoot); } } // Generating the constraints and variables for each constraint tree foreach (var constraintTree in relevantConstraintTrees) { tmsConstraints.AddRange(constraintTree.GenerateTmsConstraints()); tmsVariables.AddRange(constraintTree.GetNonUtilityDecisionVariables()); tmsUtilityVariables.AddRange(constraintTree.GetUtilityDecisionVariables()); } // Since some decision variables can be duplicated, we have to find the distinct ones // Additionally, for utility variables their utility factor has to be recalculated as needed tmsVariables = TmsDecisionVariable.GetDistinctVariables(tmsVariables, false); tmsUtilityVariables = TmsDecisionVariable.GetDistinctVariables(tmsUtilityVariables, true); // It is possible that a variable is defined in both lists so it has to be removed from this one tmsVariables = tmsVariables.Where(x => !tmsUtilityVariables.Any(y => x.Name == y.Name)).ToList(); solutionInformation.Stopwatch.Stop(); solutionInformation.Log.AddItem(LogType.Info, string.Format("TMS variables and constraints generated ({0} ms)", solutionInformation.Stopwatch.ElapsedMilliseconds)); solutionInformation.Log.AddItem(LogType.Info, string.Format("TMS solution process started", solutionInformation.Stopwatch.ElapsedMilliseconds)); solutionInformation.Log.AddItem(LogType.Info, string.Format("Variables (excl. soft): {0}", tmsVariables.Count)); solutionInformation.Log.AddItem(LogType.Info, string.Format("Variables for soft constraints: {0}", tmsUtilityVariables.Count)); solutionInformation.Log.AddItem(LogType.Info, string.Format("Constraints: {0}", tmsConstraints.Count)); solutionInformation.Stopwatch.Restart(); this.SolveWithTms(solutionInformation, tms, tmsVariables, tmsUtilityVariables, tmsConstraints); solutionInformation.Stopwatch.Stop(); solutionInformation.Log.AddItem(LogType.Info, string.Format("TMS solution process complete ({0} ms)", solutionInformation.Stopwatch.ElapsedMilliseconds)); } //} //catch (Exception e) //{ // solutionInformation.Log.AddItem(LogType.Error, e.ToString()); //} solutionInformation.SolutionFinished(); return(solutionInformation); }