internal static ConstraintNetwork GenerateQualitativeConstraintNetwork(GKOStructuringContext strContext, RelationFamily calculus, Log log) { ConstraintNetwork resultNetwork = new ConstraintNetwork(calculus, strContext.Id + "_" + calculus.Name, log); List <ConfigurationConstraintTree> constraintTrees = strContext.StructuralConstraints.Where(x => x.RelationFamily == calculus).ToList(); // Creating the constraints restricting that self edges should be labeled with the Equals relation from the calculus DomainConstraint equalsDomainConstraint = DomainConstraint.SelfEqualsConstraint(calculus); ConfigurationConstraintTree equalsConstraint = new ConfigurationConstraintTree(null, equalsDomainConstraint, strContext.Components.Where(x => x.Active).ToList(), log); // Adding the constraints restricting that self edges should be labeled with the Equals relation from the calculus constraintTrees.Add(equalsConstraint); resultNetwork.Context = strContext; // Adding all components as nodes in the constraint network strContext.Components.Where(x => x.Active).ToList().ForEach(x => resultNetwork.Nodes.Add(new Node(x))); // Creating all edges in the constraint network, so it is a complete graph foreach (var startNode in resultNetwork.Nodes) { foreach (var endNode in resultNetwork.Nodes) { QualitativeEdge edge = new QualitativeEdge(resultNetwork, startNode, endNode); resultNetwork.Edges.Add(new Tuple <Node, Node>(startNode, endNode), edge); } } // Each constraint tree has a number of configuration constraints foreach (var constraintTree in constraintTrees) { List <ConfigurationConstraint> constraints = constraintTree.GetAllConfigurationConstraints(); // ToDo: Add check for equal constraints to avoid redundancy // Adding all constraints as edges in the networks constraints.ForEach(x => { // Hack: this uses the fact that each constraint has at least one allowed relation and all have the same signature and logic (i.e. start and end node) Node startNode = x.AllowedRelations[0].GetStartNode(x); Node endNode = x.AllowedRelations[0].GetEndNode(x); Tuple <Node, Node> edgeKey = new Tuple <Node, Node>(startNode, endNode); QualitativeEdge edge = resultNetwork.Edges[edgeKey] as QualitativeEdge; // Adding the constraint to the edge edge.Constraints.Add(x); }); } return(resultNetwork); }
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); }