Example #1
0
        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);
        }