//Constructor
 public ConfiguratorSession(BusinessObjects.Model model, BusinessObjects.Configuration configuration, Z3Context context)
 {
     _model = model;
     _context = context;
     _configuration = configuration;
 }
        private static ISolverStatement TransformToStatement(Z3Context context, BLL.BusinessObjects.CustomFunction customFunction)
        {
            ISolverStatement returnStatement = null;

            return returnStatement;
        }
 private static ISolverStatement TransformToStatement(Z3Context context, BLL.BusinessObjects.CompositionRule compositionRule)
 {
     ISolverStatement returnStatement = null;
     switch (compositionRule.CompositionRuleType)
     {
         case BusinessObjects.CompositionRuleTypes.Dependency:
             returnStatement = context.MakeImplies(compositionRule.FirstFeature.SlvMapIdentifier, compositionRule.SecondFeature.SlvMapIdentifier);
             break;
         case BusinessObjects.CompositionRuleTypes.MutualDependency:
             returnStatement = context.MakeEquivalence(compositionRule.FirstFeature.SlvMapIdentifier, compositionRule.SecondFeature.SlvMapIdentifier);
             break;
         case BusinessObjects.CompositionRuleTypes.MutualExclusion:
             returnStatement = context.MakeExcludes(compositionRule.FirstFeature.SlvMapIdentifier, compositionRule.SecondFeature.SlvMapIdentifier);
             break;
     }
     return returnStatement;
 }
        private static ISolverStatement TransformToStatement(Z3Context context, BLL.BusinessObjects.GroupRelation groupRelation)
        {
            ISolverStatement returnStatement = null;
            switch (groupRelation.GroupRelationType)
            {
                case BusinessObjects.GroupRelationTypes.OR:
                    ISolverStatement innerOr1 = context.MakeOr(groupRelation.ChildFeatures.Select(k => k.SlvMapIdentifier).ToArray());
                    returnStatement = context.MakeEquivalence(groupRelation.ParentFeature.SlvMapIdentifier, innerOr1);
                    break;

                case BusinessObjects.GroupRelationTypes.XOR:
                    ISolverStatement orStatement = context.MakeOr(groupRelation.ChildFeatures.Select(k => k.SlvMapIdentifier).ToArray());
                    ISolverStatement negatedAnds = context.MakeNegatedAndCombinations(groupRelation.ChildFeatures.Select(k => k.SlvMapIdentifier).ToArray());
                    ISolverStatement equivalence2 = context.MakeEquivalence(groupRelation.ParentFeature.SlvMapIdentifier, orStatement);
                    returnStatement = context.MakeAnd(equivalence2, negatedAnds);
                    break;

                case BusinessObjects.GroupRelationTypes.Cardinal:

                    //Sum value customFunction statement :  >= lowerbound AND <= upperbound
                    List<ISolverStatement> intConversions = new List<ISolverStatement>();
                    groupRelation.ChildFeatures.ForEach(c => intConversions.Add(context.MakeBoolToInt(c.SlvMapIdentifier)));
                    ISolverStatement sumLesserThan = context.MakeLowerOrEqual(context.MakeAdd(intConversions.ToArray()), context.MakeNumeral((int)groupRelation.UpperBound));
                    ISolverStatement sumGreaterThan = context.MakeGreaterOrEqual(context.MakeAdd(intConversions.ToArray()), context.MakeNumeral((int)groupRelation.LowerBound));
                    ISolverStatement sumEqualsZero = context.MakeEquals(context.MakeAdd(intConversions.ToArray()), context.MakeNumeral(0));
                    ISolverStatement sumValStatement = context.MakeAnd(sumLesserThan, context.MakeOr(sumGreaterThan, sumEqualsZero));

                    //Issue - when lowerbound is = 0, the solver does not allow all elements in a groupRelation to be set to 0
                    ISolverStatement orStatement2 = context.MakeOr(groupRelation.ChildFeatures.Select(k => k.SlvMapIdentifier).ToArray());
                    ISolverStatement equivalence3 = context.MakeEquivalence(groupRelation.ParentFeature.SlvMapIdentifier, orStatement2);
                    returnStatement = context.MakeAnd(equivalence3, sumValStatement);
                    break;
            }
            return returnStatement;
        }
 private static ISolverStatement TransformToStatement(Z3Context context, BLL.BusinessObjects.Relation relation)
 {
     ISolverStatement returnStatement = null;
     switch (relation.RelationType)
     {
         case BusinessObjects.RelationTypes.Mandatory:
             returnStatement = context.MakeEquivalence(relation.ParentFeature.SlvMapIdentifier, relation.ChildFeature.SlvMapIdentifier);
             break;
         case BusinessObjects.RelationTypes.Optional:
             returnStatement = context.MakeImplies(relation.ChildFeature.SlvMapIdentifier, relation.ParentFeature.SlvMapIdentifier);
             break;
     }
     return returnStatement;
 }
        //Public methods
        public static Z3Context CreateNewContext(BusinessObjects.Model model)
        {
            //Create a new SolverContext
            Z3Context context = new Z3Context();

            //Create variables for Features and Attributes
            foreach (BLL.BusinessObjects.Feature feature in model.Features)
            {
                //Feature
                context.AddVariable(feature.SlvMapIdentifier, VariableDataTypes.Boolean);

                //Attributes
                feature.Attributes.ForEach(attribute =>
                {
                    switch (attribute.AttributeDataType)
                    {
                        case BusinessObjects.AttributeDataTypes.Integer:
                            context.AddVariable(attribute.SlvMapIdentifier, VariableDataTypes.Integer);
                            break;
                        case BusinessObjects.AttributeDataTypes.Boolean:
                            context.AddVariable(attribute.SlvMapIdentifier, VariableDataTypes.Boolean);
                            break;
                        case BusinessObjects.AttributeDataTypes.String:
                            //throw new Exception("String attributes not supported yet");
                            break;
                    }
                });

                //feature.Attributes.ForEach(attribute =>
                //{
                //    if (attribute.AttributeDataType == BusinessObjects.AttributeDataTypes.Integer && !String.IsNullOrEmpty(attribute.ConstantValue))
                //        context.AddImpliedValueAssumption(feature.ID.ToString(), featuresCategory, attribute.ID.ToString(), attributesCategory, VariableDataTypes.Integer, int.Parse(attribute.ConstantValue));
                //});
            }

            //Create customFunctions
            model.Relations.ForEach(rel => context.AddConstraint(rel.SlvMapIdentifier, TransformToStatement(context, rel)));
            model.GroupRelations.ForEach(groupRel => context.AddConstraint(groupRel.SlvMapIdentifier, TransformToStatement(context, groupRel)));
            model.CompositionRules.ForEach(compositionRule => context.AddConstraint(compositionRule.SlvMapIdentifier, TransformToStatement(context, compositionRule)));
            //model.CustomFunctions.ForEach(customFunction => context.AddCustomFunction(customFunction.SlvMapIdentifier, TransformToStatement(context, customFunction)));

            //Create an initial restore point and return the new context
            context.CreateInitialRestorePoint();
            return context;
        }