/// <summary>
        /// Generates a list containing the decision variables of the branches, which can be used to derive a single decision variable of the constraint tree.
        /// <para>Basically, this generates the carthesian product of the decision variables of the branches</para>
        /// This can be used to generate constraints of sort:
        /// Tree-Constraint-1-Satisfied = Branch-A-Satisfied OR Branch-B-Satisfied
        /// </summary>
        /// <param name="constraintTree"></param>
        /// <returns></returns>
        public static IEnumerable <IEnumerable <string> > GetSatDVarParts(this ConfigurationConstraintTree constraintTree)
        {
            if (constraintTree.IsCombination)
            {
                List <List <string> > branchDvarLists = new List <List <string> >();
                IEnumerable <IEnumerable <string> > dvarsCarthesianProduct = new[] { Enumerable.Empty <string>() };

                // For each branch we find its satisfaction decision variables
                foreach (var branch in constraintTree.ConstraintBranches)
                {
                    List <String> branchDvars = branch.GetSatDVarNames();
                    if (branchDvars.Count > 0)
                    {
                        branchDvarLists.Add(branch.GetSatDVarNames());
                    }
                }

                // Then the carthesian product of the decision variables is calculated
                dvarsCarthesianProduct = branchDvarLists.Aggregate(
                    dvarsCarthesianProduct,
                    (accumulator, sequence) =>
                    from accseq in accumulator
                    from item in sequence
                    select accseq.Concat(new[] { item }));

                return(dvarsCarthesianProduct);
            }

            // if this is not a combination constraint tree return empty list
            return(new List <List <string> >());
        }
        /// <summary>
        /// Creates a constraint tree for a set of components from a domain constraint.
        /// </summary>
        /// <param name="parent">The parent of the current constraint tree</param>
        /// <param name="derivedFrom">The domain constraint from which the tree is derived</param>
        /// <param name="components">The components for which to apply the relevant DomainConstraint</param>
        /// <param name="log">The processing log</param>
        internal ConfigurationConstraintTree(ConfigurationConstraintTree parent, DomainConstraint derivedFrom, List <GKOComponent> components, Log log)
        {
            if (derivedFrom == null)
            {
                throw new ArgumentNullException("The derived from domain constraints has to be set for a configuration constraints tree!");
            }

            this.Parent = parent;

            // assigning the right DomainConstraint
            if (derivedFrom is ITransformDomainConstraint)
            {
                this.derivedFrom = (derivedFrom as ITransformDomainConstraint).TransformConstraint();
            }
            else
            {
                this.derivedFrom = derivedFrom;
            }

            if (this.DerivedFrom is DomainConstraintCombination)
            {
                this.CreateFromCombinationConstraint((DomainConstraintCombination)this.DerivedFrom, components, log);
            }
            else
            {
                this.CreateFromNormalConstraint(this.DerivedFrom, components, log);
            }
        }
        /// <summary>
        /// Finds the list of satisfaction variables for the current tree.
        /// Takes in consideration the branches of the tree (if any), but does not return their decision variables.
        /// If the tree has configuration constraints returns a list of their decision variables names.
        /// </summary>
        /// <param name="constraintTree"></param>
        /// <returns></returns>
        public static List <string> GetSatDVarNames(this ConfigurationConstraintTree constraintTree)
        {
            List <string> dVarNames = new List <string>();

            if (constraintTree.IsCombination)
            {
                IEnumerable <IEnumerable <string> > dvarsCarthesianProduct = constraintTree.GetSatDVarParts();

                // Create the decision variables based on the included branch variables
                foreach (var dVarList in dvarsCarthesianProduct)
                {
                    dVarNames.Add(constraintTree.GetSatDVarName(dVarList));
                }
            }
            else
            {
                foreach (var constraint in constraintTree.ConfigurationConstraints)
                {
                    dVarNames.Add(constraint.GetSatDVarName());
                }
            }

            return(dVarNames);
        }
 /// <summary>
 /// Generates the satisfaction decision variable name for the current constraint tree, when using a specific decision variables of the branches
 /// </summary>
 /// <param name="constraintTree"></param>
 /// <param name="parts">An ordered list of the chosen decision variables of the included branches</param>
 /// <returns></returns>
 public static string GetSatDVarName(this ConfigurationConstraintTree constraintTree, IEnumerable <string> parts)
 {
     return(string.Format("{0}-{1}-satisfied", constraintTree.DerivedFrom.Name, parts.Aggregate((x, y) => x + "-" + y)));
 }