public TmsManager(StructuralReasonerOptions structuralReasonerOptions, Log log) { this.structuralReasonerOptions = structuralReasonerOptions; this.log = log; cdaStarTms = new Workspace(); CreateDomains(); CreateConstraintTypes(); }
/// <summary> /// Solves the constraint network /// </summary> internal SolutionData Solve(StructuralReasonerOptions options, TmsManager tms) { if (this.Type == ConstraintNetworkType.QualitativeNetwork) { return(this.SolveQualitative(options, tms)); } else if (this.Type == ConstraintNetworkType.MetricNetwork) { return(this.SolveMetric(options, tms)); } return(null); }
/// <summary> /// Generates the metric constraint network for the structured components /// </summary> /// <param name="structuringContexts">The list of structured components to generate the networks for. /// They must include the metric relation family in the list of included ones</param> /// <returns></returns> internal static List <ConstraintNetwork> GenerateMetricConstraintNetworks(List <GKOStructuringContext> structuringContexts, TmsManager tms, StructuralReasonerOptions options, Log log) { List <ConstraintNetwork> constraintNetworks = new List <ConstraintNetwork>(); List <List <Node> > clusters = new List <List <Node> >(); List <ConfigurationConstraintTree> constraintTrees = new List <ConfigurationConstraintTree>(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // Adding all constraint trees to the list foreach (var context in structuringContexts) { context.StructuralConstraints.ForEach(x => { // Additionally assign the special metric values based on the context of the constraints x.AssignSpecialMetricValues(context); constraintTrees.Add(x); }); } stopwatch.Stop(); log.AddItem(LogType.Info, String.Format("Assigning special metric values finished ({0} ms).", stopwatch.ElapsedMilliseconds)); stopwatch.Restart(); // Combine the nodes in the constraint trees in linked clusters, // this serve as base for generating the constraint networks foreach (var constraintTree in constraintTrees) { clusters.AddRange(constraintTree.GetNodeClusters()); ConstraintNetwork.NormalizeClusters(clusters); } stopwatch.Stop(); log.AddItem(LogType.Info, String.Format("Finding node clusters finished ({0} ms).", stopwatch.ElapsedMilliseconds)); #region TCSP specific // These constraints limit the domain of the decision variables for TCSP if (options.MetricReasoningAlgorithm == MetricReasoningAlgorithm.Tcsp) { stopwatch.Restart(); List <Node> nodes = clusters.SelectMany(x => x).Where(x => x != null).Distinct().ToList(); // Add min and max constraint for the constrained attributes foreach (var constrAttribute in nodes) { List <GKOComponent> compList = new List <GKOComponent>() { constrAttribute.Component }; DomainConstraint minConstraint = DomainConstraint.MinValueConstraint(constrAttribute.Attribute, tms.MetricDomain); DomainConstraint maxConstraint = DomainConstraint.MaxValueConstraint(constrAttribute.Attribute, tms.MetricDomain); ConfigurationConstraintTree minTree = new ConfigurationConstraintTree(null, minConstraint, compList, log); ConfigurationConstraintTree maxTree = new ConfigurationConstraintTree(null, maxConstraint, compList, log); constraintTrees.Add(minTree); constraintTrees.Add(maxTree); } stopwatch.Stop(); log.AddItem(LogType.Info, String.Format("Creating Min/Max constraints for TCSP finished ({0} ms).", stopwatch.ElapsedMilliseconds)); } #endregion stopwatch.Restart(); // Generating a new constraint network for each found node cluster foreach (var nodeCluster in clusters) { ConstraintNetwork network = new ConstraintNetwork(StructuralRelationsManager.MetricRelationsFamily, log); network.Nodes = nodeCluster; constraintNetworks.Add(network); } // Adding all configuration constraints in the constraint networks foreach (var constraintTree in constraintTrees) { ConfigurationConstraint[] treeConstraints = constraintTree.GetAllConfigurationConstraints().ToArray(); for (int i = 0; i < treeConstraints.Length; i++) { ConstraintNetwork.ApplyMetricConstraint(treeConstraints[i], constraintNetworks, log); } } // UId has to be assigned to the networks for (int i = 0; i < constraintNetworks.Count; i++) { constraintNetworks[i].UId = "MetricConstraintNetwork_" + (i + 1).ToString(); } stopwatch.Stop(); log.AddItem(LogType.Info, String.Format("Generating the constraint networks finished ({0} ms).", stopwatch.ElapsedMilliseconds)); return(constraintNetworks); }
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); }
internal SolutionDataQualitative SolveQualitative(StructuralReasonerOptions options, TmsManager tms) { SolutionDataQualitative solutionInformation = new SolutionDataQualitative(this); 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 calculusDomain = tms.CalculiDomains.Single(x => x.Name == this.RelationFamily.GetTmsRelationsDomainName()); solutionInformation.StartTime = DateTime.Now; //try //{ solutionInformation.Stopwatch.Start(); // For each edge adds the decion variables of the edge and generates the TMS constraints for each configuration constraint foreach (var edge in this.Edges.Values) { QualitativeEdge qualEdge = (edge as QualitativeEdge); string edgeDVar = qualEdge.GetDVarName(); // Adding the edge decision variable tmsVariables.Add(new TmsDecisionVariable(calculusDomain, edgeDVar)); // Adding the bool dvar for each relation used in a constraint of the edge // They are mapped to the edge dvar later with a constraint foreach (var relation in edge.Constraints.SelectMany(x => x.AllowedRelations).Distinct()) { tmsVariables.Add(new TmsDecisionVariable(satisfiedDomain, qualEdge.GetDVarName((QualitativeRelation)relation))); } foreach (var constraint in edge.Constraints) { // ToDo: Make the GetTmsConstraints more consistent - now it is actually working on a constraint lvl for qualitative relations // Adding the TMS constraints derivde by the relation tmsConstraints.AddRange(constraint.AllowedRelations[0].GetTmsConstraints(constraint, edge)); } // 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); // Generating the composition constraints foreach (var nodeA in this.Nodes) { foreach (var nodeB in this.Nodes) { foreach (var nodeC in this.Nodes) { QualitativeEdge edgeAB = (QualitativeEdge)this.Edges[new Tuple <Node, Node>(nodeA, nodeB)]; QualitativeEdge edgeBC = (QualitativeEdge)this.Edges[new Tuple <Node, Node>(nodeB, nodeC)]; QualitativeEdge edgeAC = (QualitativeEdge)this.Edges[new Tuple <Node, Node>(nodeA, nodeC)]; string edgeABDVar = edgeAB.GetDVarName(); string edgeBCDVar = edgeBC.GetDVarName(); string edgeACDVar = edgeAC.GetDVarName(); TmsConstraint compositionConstraint = new TmsConstraint(); // Creating the constraint restricting the allowed relations by the edge compositionConstraint.ConstraintType = this.RelationFamily.GetTmsCompositionConstraintName(); compositionConstraint.VariableTuple = new List <string>() { edgeABDVar, edgeBCDVar, edgeACDVar }; tmsConstraints.Add(compositionConstraint); } } } 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); }