private Formula ReadFormula(CompoundExpression exp, Dictionary<string, string> dParameterNameToType, bool bParamterized, Domain d)
 {
     bool bPredicate = true;
     //Console.WriteLine(exp);
     if (d!= null && d.IsFunctionExpression(exp.Type))
     {
         Predicate p = ReadFunctionExpression(exp, dParameterNameToType, d);
         return new PredicateFormula(p);
     }
     else if (IsUniversalQuantifier(exp))
     {
         CompoundExpression eParameter = (CompoundExpression)exp.SubExpressions[0];
         CompoundExpression eBody = (CompoundExpression)exp.SubExpressions[1];
         string sParameter = eParameter.Type;
         string sType = eParameter.SubExpressions[1].ToString();
         dParameterNameToType[sParameter] = sType;
         ParametrizedFormula cfQuantified = new ParametrizedFormula(exp.Type);
         cfQuantified.Parameters[sParameter] = sType;
         Formula fBody = ReadFormula(eBody, dParameterNameToType, true, d);
         cfQuantified.AddOperand(fBody);
         return cfQuantified;
     }
     else if (exp.Type == "probabilistic")
     {
         ProbabilisticFormula pf = new ProbabilisticFormula();
         int iExpression = 0;
         for (iExpression = 0; iExpression < exp.SubExpressions.Count; iExpression+=2)
         {
             //if (exp.SubExpressions[iExpression] is StringExpression)
             //    throw new InvalidDataException();
             string sProb = exp.SubExpressions[iExpression].ToString();
             double dProb = 0.0;
             if (sProb.Contains("/"))
             {
                 string[] a = sProb.Split('/');
                 dProb = double.Parse(a[0]) / double.Parse(a[1]);
             }
             else
             {
                 dProb = double.Parse(sProb);
             }
             Formula f = ReadFormula((CompoundExpression)exp.SubExpressions[iExpression + 1], dParameterNameToType, bParamterized, d);
             pf.AddOption(f, dProb);
         }
         return pf;
     }
     else
     {
         foreach (Expression eSub in exp.SubExpressions)
         {
             if (eSub is CompoundExpression)
             {
                 bPredicate = false;
                 break;
             }
         }
         if (bPredicate)
             return ReadPredicate(exp, dParameterNameToType, bParamterized, d);
         else
         {
             CompoundFormula cf = new CompoundFormula(exp.Type);
             int iExpression = 0;
             for (iExpression = 0; iExpression < exp.SubExpressions.Count; iExpression++)
             {
                 if (exp.SubExpressions[iExpression] is StringExpression)
                     throw new InvalidDataException();
                 Formula f = ReadFormula((CompoundExpression)exp.SubExpressions[iExpression], dParameterNameToType, bParamterized, d);
                 cf.SimpleAddOperand(f);
             }
             if (cf.Operator == "not" && cf.Operands[0] is PredicateFormula)
             {
                 PredicateFormula fNegate = new PredicateFormula(((PredicateFormula)cf.Operands[0]).Predicate.Negate());
                 return fNegate;
             }
             return cf;
         }
     }
 }
        /*
         *
                public CompoundFormula GetPreconditionsNoState(Dictionary<string, List<Predicate>> dTags, Domain d, List<string> lIncludedTags, List<string> lExcludedTags)
                {
                    CompoundFormula cfPreconditions = new CompoundFormula("and");
                    HashSet<Predicate> lKnowPreconditions = new HashSet<Predicate>();
                    if (Preconditions != null)
                    {
                        //foreach tag t, either KNot t | ?t, or forall precondition p, p|t
                        Preconditions.GetAllPredicates(lKnowPreconditions);
                        foreach (Predicate p in lKnowPreconditions)
                        {
                            if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                                cfPreconditions.AddOperand(p);
                        }

                        foreach (string sTag in lIncludedTags)
                        {

                            CompoundFormula cfAnd = new CompoundFormula("and");
                            foreach (Predicate p in lKnowPreconditions)
                            {
                                if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                                    continue;
                                else
                                {
                                    cfAnd.AddOperand(p.GenerateGiven(sTag));
                                }
                            }
                            if (cfAnd.Operands.Count > 0)
                                cfPreconditions.SimpleAddOperand(cfAnd.Simplify());

                        }
                    }
                    foreach (string sTag in lIncludedTags)
                    {
                        //this allows only actions on non-distinguishable tag sets - it is possible to allow actions that apply to distinguishable tag sets
                        if (sTag != lIncludedTags[0])
                        {
                            Predicate pKNotT = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag),new Constant(Domain.TAG, lIncludedTags[0]));
                            cfPreconditions.AddOperand(pKNotT.Negate());
                        }
                    }
                    foreach (string sTag in lExcludedTags)
                    {

                        Predicate pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag),new Constant(Domain.TAG, lIncludedTags[0]));

                        cfPreconditions.AddOperand(pNotTag);
                    }
                    //if (cfPreconditions.Operands.Count > 0)
                        return cfPreconditions;
                    //return null;
                }

        */
        public CompoundFormula GetKnowWhetherPreconditions(Dictionary<string, List<Predicate>> dTags, Domain d, string sActionTag)
        {
            Argument pTag = new Constant(Domain.TAG, sActionTag);
            CompoundFormula cfKWPreconditions = new CompoundFormula("and");
            HashSet<Predicate> lKnowPreconditions = new HashSet<Predicate>();
            CompoundFormula cfOr = null;
            if (Preconditions != null)
            {
                //foreach tag t, either KNot t | ?t, or forall precondition p, p|t
                Preconditions.GetAllPredicates(lKnowPreconditions);
                foreach (Predicate p in lKnowPreconditions)
                {
                    if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                        cfKWPreconditions.AddOperand(p);
                }

                foreach (string sTag in dTags.Keys)
                {
                    Predicate pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag), (Constant)pTag);
                    cfOr = new CompoundFormula("or");
                    CompoundFormula cfAnd = new CompoundFormula("and");
                    cfAnd.AddOperand(pNotTag.Negate());
                    foreach (Predicate p in lKnowPreconditions)
                    {
                        //if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                        if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                            continue;
                        else
                        {
                            cfAnd.AddOperand(p.GenerateGiven(sTag));
                            //if (!d.AlwaysKnown(p))
                            //    cfAnd.AddOperand(p.GenerateKnowGiven(sTag, true));
                        }
                    }

                    if (cfAnd.Operands.Count > 0)
                        cfOr.AddOperand(cfAnd);
                    if (sTag == sActionTag)
                    {
                        cfKWPreconditions.SimpleAddOperand(cfAnd);
                    }
                    else
                    {
                        cfOr.AddOperand(pNotTag);

                        cfKWPreconditions.SimpleAddOperand(cfOr.Simplify());
                    }
                }
            }

            if (cfKWPreconditions.Operands.Count > 0)
                return cfKWPreconditions;
            return null;
        }
        //this implementation requires ~Knot between all include tags, and Knot between every include and every exclude tags
        public CompoundFormula GetPreconditionsNoState(Dictionary<string, List<Predicate>> dTags, Domain d, List<string> lIncludedTags, List<string> lExcludedTags)
        {
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            if (Preconditions != null)
            {

                HashSet<Predicate> lKnowPreconditions = Preconditions.GetAllPredicates();
                foreach (Predicate p in lKnowPreconditions)
                {
                    if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                        cfPreconditions.AddOperand(p);
                }

                foreach (string sTag in lIncludedTags)
                {

                    CompoundFormula cfAnd = new CompoundFormula("and");
                    foreach (Predicate p in lKnowPreconditions)
                    {
                        if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                            continue;
                        else
                        {
                            cfAnd.AddOperand(p.GenerateGiven(sTag));
                        }
                    }
                    if (cfAnd.Operands.Count > 0)
                        cfPreconditions.SimpleAddOperand(cfAnd.Simplify());

                }
            }
            //this allows only actions on non-distinguishable tag sets - it is possible to allow actions that apply to distinguishable tag sets
            for (int iIncludeTag = 0; iIncludeTag < lIncludedTags.Count; iIncludeTag++)
            {
                for (int iOtherIncludeTag = iIncludeTag + 1; iOtherIncludeTag < lIncludedTags.Count; iOtherIncludeTag++)
                {
                    Predicate pKNotT = Predicate.GenerateKNot(new Constant(Domain.TAG, lIncludedTags[iIncludeTag]), new Constant(Domain.TAG, lIncludedTags[iOtherIncludeTag]));
                    cfPreconditions.AddOperand(pKNotT.Negate());

                }
            }
            foreach (string sIncludeTag in lIncludedTags)
            {
                foreach (string sExcludeTag in lExcludedTags)
                {

                    Predicate pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sIncludeTag), new Constant(Domain.TAG, sExcludeTag));

                    cfPreconditions.AddOperand(pNotTag);
                }
            }
            return cfPreconditions;
        }
        public List<Action> KnowCompilationSplitConditions(Dictionary<string, List<Predicate>> dTags, List<string> lAlwaysKnown, List<Predicate> lAdditionalPredicates)
        {
            List<Action> lActions = new List<Action>();

            ParametrizedAction aNewAdd = new ParametrizedAction(Name + "-Add");
            ParametrizedAction aNewRemove = new ParametrizedAction(Name + "-Remove");

            ParametrizedAction aNewTranslateAdd = new ParametrizedAction(Name + "-TranslateAdd");
            ParametrizedAction aNewTranslateRemove = new ParametrizedAction(Name + "-TranslateRemove");

            ParametrizedPredicate ppInFirst = new ParametrizedPredicate("P1-" + Name);
            ParametrizedPredicate ppInSecond = new ParametrizedPredicate("P2-" + Name);
            ParametrizedPredicate ppInThird = new ParametrizedPredicate("P3-" + Name);
            GroundedPredicate gpNotInAction = new GroundedPredicate("NotInAction");

            if (this is ParametrizedAction)
            {
                foreach (Parameter p in ((ParametrizedAction)this).Parameters)
                {
                    aNewAdd.AddParameter(p);
                    aNewRemove.AddParameter(p);
                    aNewTranslateAdd.AddParameter(p);
                    aNewTranslateRemove.AddParameter(p);

                    ppInFirst.AddParameter(p);
                    ppInSecond.AddParameter(p);
                    ppInThird.AddParameter(p);
                }
            }

            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            HashSet<Predicate> lKnowPreconditions = new HashSet<Predicate>();
            if (Preconditions != null)
            {
                Preconditions.GetAllPredicates(lKnowPreconditions);
                cfPreconditions.AddOperand(Preconditions);
                foreach (Predicate p in lKnowPreconditions)
                    if (!lAlwaysKnown.Contains(p.Name))
                        cfPreconditions.AddOperand(new PredicateFormula(new KnowPredicate(p)));
            }
            cfPreconditions.AddOperand(gpNotInAction);

            if (Effects == null)
                throw new NotImplementedException();

            HashSet<Predicate> lKnowEffects = new HashSet<Predicate>();
            CompoundFormula cfAddEffects = new CompoundFormula("and");
            CompoundFormula cfRemoveEffects = new CompoundFormula("and");
            CompoundFormula cfTranslateAddEffects = new CompoundFormula("and");
            CompoundFormula cfTranslateRemoveEffects = new CompoundFormula("and");
            List<Predicate> lRequireTranslation = new List<Predicate>();

            foreach (Formula f in lObligatory)
            {
                f.GetAllPredicates(lKnowEffects);
                cfAddEffects.AddOperand(f); //unconditional effects cannot conflict anyhow
            }

            foreach (Predicate p in lKnowEffects)
            {
                if (!lAlwaysKnown.Contains(p.Name))
                {
                    Predicate pKEffect = new KnowPredicate(p);
                    cfAddEffects.AddOperand(pKEffect);
                    pKEffect = new KnowPredicate(p.Negate());
                    cfRemoveEffects.AddOperand(pKEffect.Negate());
                    foreach (string sTag in dTags.Keys)
                    {
                        pKEffect = p.GenerateKnowGiven(sTag);
                        cfAddEffects.AddOperand(pKEffect);
                        pKEffect = p.Negate().GenerateKnowGiven(sTag);
                        cfRemoveEffects.AddOperand(pKEffect.Negate());
                    }
                }
            }
            if (lConditions.Count > 0)
            {
                lAdditionalPredicates.Add(ppInFirst);
                lAdditionalPredicates.Add(ppInSecond);
                lAdditionalPredicates.Add(ppInThird);

                aNewRemove.Preconditions = cfPreconditions;
                cfRemoveEffects.AddOperand(ppInFirst);
                cfRemoveEffects.AddOperand(gpNotInAction.Negate());

                aNewAdd.Preconditions = new PredicateFormula(ppInFirst);
                cfAddEffects.AddOperand(ppInSecond);
                cfAddEffects.AddOperand(ppInFirst.Negate());

                aNewTranslateRemove.Preconditions = new PredicateFormula(ppInSecond);
                cfTranslateRemoveEffects.AddOperand(ppInSecond.Negate());
                cfTranslateRemoveEffects.AddOperand(ppInThird);

                aNewTranslateAdd.Preconditions = new PredicateFormula(ppInThird);
                cfTranslateAddEffects.AddOperand(ppInThird.Negate());
                cfTranslateAddEffects.AddOperand(gpNotInAction);

                Dictionary<Predicate, Predicate> dTaggedPredicates = new Dictionary<Predicate,Predicate>();

                foreach (CompoundFormula cfCondition in lConditions)
                {
                    CompoundFormula cfAddCondition, cfRemoveCondition;
                    cfCondition.SplitAddRemove(dTaggedPredicates, out cfAddCondition, out cfRemoveCondition);
                    if (cfAddCondition != null)
                        cfAddEffects.AddOperand(cfAddCondition);
                    if (cfRemoveCondition != null)
                        cfRemoveEffects.AddOperand(cfRemoveCondition);

                    CompoundFormula cfK = CreateKnowledgeGainCondition(cfCondition, lAlwaysKnown, false);
                    if (cfK != null)
                    {
                        cfK.SplitAddRemove(dTaggedPredicates, out cfAddCondition, out cfRemoveCondition);
                        if (cfAddCondition != null)
                            cfAddEffects.AddOperand(cfAddCondition);
                        if (cfRemoveCondition != null)
                            cfRemoveEffects.AddOperand(cfRemoveCondition);
                    }

                    cfK = CreateKnowledgeLossCondition(cfCondition, lAlwaysKnown);
                    if (cfK != null)
                    {
                        cfK.SplitAddRemove(dTaggedPredicates, out cfAddCondition, out cfRemoveCondition);
                        if (cfAddCondition != null)
                            cfAddEffects.AddOperand(cfAddCondition);
                        if (cfRemoveCondition != null)
                            cfRemoveEffects.AddOperand(cfRemoveCondition);
                    }

                    foreach (string sTag in dTags.Keys)
                    {
                        cfK = CreateTaggedKnowledgeGainCondition(cfCondition, sTag, lAlwaysKnown, false);
                        if (cfK != null)
                        {
                            cfK.SplitAddRemove(dTaggedPredicates, out cfAddCondition, out cfRemoveCondition);
                            if (cfAddCondition != null)
                                cfAddEffects.AddOperand(cfAddCondition);
                            if (cfRemoveCondition != null)
                                cfRemoveEffects.AddOperand(cfRemoveCondition);
                        }
                        cfK = CreateTaggedKnowledgeLossCondition(cfCondition, sTag, lAlwaysKnown);
                        if (cfK != null)
                        {
                            cfK.SplitAddRemove(dTaggedPredicates, out cfAddCondition, out cfRemoveCondition);
                            if (cfAddCondition != null)
                                cfAddEffects.AddOperand(cfAddCondition);
                            if (cfRemoveCondition != null)
                                cfRemoveEffects.AddOperand(cfRemoveCondition);
                        }
                    }

                }
                aNewAdd.Effects = cfAddEffects.Simplify();
                aNewRemove.Effects = cfRemoveEffects.Simplify();
                lActions.Add(aNewRemove);
                lActions.Add(aNewAdd);

                foreach (KeyValuePair<Predicate, Predicate> pair in dTaggedPredicates)
                {
                    CompoundFormula cfWhen = new CompoundFormula("when");
                    CompoundFormula cfAnd = new CompoundFormula("and");
                    cfWhen.AddOperand(pair.Key);

                    cfAnd.SimpleAddOperand(pair.Value);
                    cfAnd.SimpleAddOperand(pair.Key.Negate());
                    cfWhen.SimpleAddOperand(cfAnd);

                    if (pair.Value.Negation)
                        cfTranslateRemoveEffects.AddOperand(cfWhen);
                    else
                        cfTranslateAddEffects.AddOperand(cfWhen);
                }

                aNewTranslateAdd.Effects = cfTranslateAddEffects;
                aNewTranslateRemove.Effects = cfTranslateRemoveEffects;
                lActions.Add(aNewTranslateRemove);
                lActions.Add(aNewTranslateAdd);
            }
            else
            {
                Action aK = AddTaggedConditions(dTags, lAlwaysKnown);
                lActions.Add(aK);
            }

            if (Observe != null)
            {
               throw new NotImplementedException();

            }
            return lActions;
        }
        public CompoundFormula GetKnowWhetherPreconditions(Dictionary<string, List<Predicate>> dTags, Domain d, List<string> lIncludedTags, List<string> lExcludedTags)
        {
            CompoundFormula cfKWPreconditions = new CompoundFormula("and");
            HashSet<Predicate> lKnowPreconditions = new HashSet<Predicate>();
            if (Preconditions != null)
            {
                //foreach tag t, either KNot t | ?t, or forall precondition p, p|t
                Preconditions.GetAllPredicates(lKnowPreconditions);
                foreach (Predicate p in lKnowPreconditions)
                {
                    if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                        cfKWPreconditions.AddOperand(new KnowPredicate(p));
                }

                foreach (string sTag in lIncludedTags)
                {

                    CompoundFormula cfAnd = new CompoundFormula("and");
                    foreach (Predicate p in lKnowPreconditions)
                    {
                        if (d.AlwaysKnown(p) && (d.AlwaysConstant(p)))
                            continue;
                        else
                        {
                            cfAnd.AddOperand(p.GenerateGiven(sTag));
                            if (!d.AlwaysKnown(p))
                                cfAnd.AddOperand(p.GenerateKnowGiven(sTag, true));
                        }
                    }
                    if (cfAnd.Operands.Count > 0)
                        cfKWPreconditions.SimpleAddOperand(cfAnd.Simplify());

                    //this allows only actions on non-distinguishable tag sets - it is possible to allow actions that apply to distinguishable tag sets
                    if (sTag != lIncludedTags[0])
                    {
                        Predicate pKNotT = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag),new Constant(Domain.TAG, lIncludedTags[0]));
                        cfKWPreconditions.AddOperand(pKNotT.Negate());
                    }

                }
            }
            foreach (string sTag in lExcludedTags)
            {

                Predicate pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag),new Constant(Domain.TAG, lIncludedTags[0]));

                cfKWPreconditions.AddOperand(pNotTag);
            }
            if(cfKWPreconditions.Operands.Count > 0)
                return cfKWPreconditions;
            return null;
        }
        public override Formula Simplify()
        {
            Formula fSimplified = null;
            if (Simplified)
                return this;
            if( Operator == "not" )
                fSimplified = Negate();
            if (Operands.Count == 1)
                fSimplified = Operands[0].Simplify();
            if (Operator == "when")
            {
                CompoundFormula cfNew = new CompoundFormula(Operator);
                Formula fFirst = Operands[0].Simplify();
                Formula fSecond = Operands[1].Simplify();

                cfNew.SimpleAddOperand(fFirst);

                if (IsSimpleAnd(fFirst) && IsSimpleAnd(fSecond))
                {
                    HashSet<Predicate> lFirst = fFirst.GetAllPredicates();
                    HashSet<Predicate> lSecond = fSecond.GetAllPredicates();
                    CompoundFormula cfSecond = new CompoundFormula("and");
                    foreach (Predicate p in lSecond)
                        if (!lFirst.Contains(p))
                            cfSecond.AddOperand(p);
                    cfNew.SimpleAddOperand(cfSecond);
                }
                else
                {
                    cfNew.SimpleAddOperand(fSecond);
                }
                cfNew.Simplified = true;
                fSimplified = cfNew;
            }
            else if (Operator == "and" || Operator == "or" || Operator == "oneof")
            {
                /*
                if (Operands.Count == 0)
                {
                    if (Operator == "and")
                        return new PredicateFormula(new GroundedPredicate(Domain.TRUE_PREDICATE));
                    if (Operator == "or" || Operator == "oneof")
                        return new PredicateFormula(new GroundedPredicate(Domain.FALSE_PREDICATE));
                }
                 * */
                CompoundFormula cfNew = new CompoundFormula(Operator);
                foreach (Formula f in Operands)
                {
                    Formula fSimplify = f.Simplify();
                    if (fSimplify is CompoundFormula)
                    {
                        CompoundFormula cf = (CompoundFormula)fSimplify;
                        if (cf.Operator == Operator)
                        {
                            foreach (Formula ff in cf.Operands)
                                cfNew.AddOperand(ff);
                        }
                        else
                            cfNew.AddOperand(cf);
                    }
                    else if (fSimplify is ProbabilisticFormula)
                    {
                        cfNew.AddOperand(fSimplify);
                    }
                    else
                    {
                        Predicate p = ((PredicateFormula)fSimplify).Predicate;
                        if (p.Name == Domain.TRUE_PREDICATE)
                        {
                            if (Operator == "or")
                                return fSimplify;
                        }
                        else if (p.Name == Domain.FALSE_PREDICATE)
                        {
                            if (Operator == "and")
                                return fSimplify;
                        }
                        else
                            cfNew.AddOperand(fSimplify);
                    }
                }
                if (cfNew.Operands.Count == 1)
                    return cfNew.Operands[0];
                if (cfNew.Operator == "or")
                    cfNew = cfNew.RemoveRedundancies();
                fSimplified = cfNew;
            }
            if( fSimplified is CompoundFormula )
                ((CompoundFormula)fSimplified).Simplified = true;
            return fSimplified;
        }
 public override Formula Clone()
 {
     CompoundFormula cfClone = new CompoundFormula(Operator);
     foreach (Formula f in Operands)
         cfClone.SimpleAddOperand(f.Clone());
     return cfClone;
 }
        public List<Action> TagCompilationSplitConditionsNoState(Dictionary<string, List<Predicate>> dTags, Domain d, List<string> lIncludedTags,
            List<string> lExcludedTags, List<Predicate> lAdditionalPredicates)
        {
            string sName = Name;
            foreach (string sTag in lIncludedTags)
                sName += "-" + sTag;
            ParametrizedAction aNew = new ParametrizedAction(sName);

            if (this is ParametrizedAction)
            {
                foreach (Parameter p in ((ParametrizedAction)this).Parameters)
                {
                    aNew.AddParameter(p);
                }
            }

            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);

            CompoundFormula cfPreconditions = new CompoundFormula("and");
            Formula cfNoStatePreconditions = GetPreconditionsNoState(dTags, d, lIncludedTags, lExcludedTags);
            cfPreconditions.AddOperand(cfNoStatePreconditions); //knowledge loss is the first action, so it will have all the preconditions
            aNew.Preconditions = cfPreconditions;

            if (Effects == null)
                throw new NotImplementedException();

            HashSet<Predicate> lKnowEffects = new HashSet<Predicate>();
            CompoundFormula cfStateEffects = new CompoundFormula("and");
            //CompoundFormula cfMandatoryEffects = new CompoundFormula("and");
            foreach (Formula f in lObligatory)
            {
                f.GetAllPredicates(lKnowEffects);
            }
            if (lKnowEffects.Count > 0)
            {
                foreach (string sTag in lIncludedTags)
                {
                    //~KNot t|?t -> effects|t
                    CompoundFormula cfKEffects = new CompoundFormula("and");

                    foreach (Predicate p in lKnowEffects)
                    {
                        Predicate pAdd = p.GenerateGiven(sTag);
                        cfKEffects.AddOperand(pAdd);
                    }
                    cfStateEffects.SimpleAddOperand(cfKEffects);
                }
            }

            List<Action> lActions = new List<Action>();

            if (lConditions.Count > 0)
            {
                foreach (CompoundFormula cfCondition in lConditions)
                {
                    CompoundFormula cfK = null, cfAnd = null;
                    HashSet<Predicate> lConditionEffects = cfCondition.Operands[1].GetAllPredicates();
                    cfAnd = new CompoundFormula("and");

                    foreach (string sTag in lIncludedTags)
                    {
                        cfK = CreateTaggedCondition(cfCondition, d, sTag);
                        if (cfK != null)
                        {
                            cfStateEffects.SimpleAddOperand(cfK);
                        }
                    }
                }
            }

            aNew.Effects = cfStateEffects.Simplify();

            if (lConditions.Count > 0 && SDRPlanner.SplitConditionalEffects)
                lActions.AddRange(aNew.SplitConditions(lAdditionalPredicates));
            else
            {
                ((CompoundFormula)aNew.Preconditions).AddOperand(new GroundedPredicate("NotInAction"));
                lActions.Add(aNew);
            }

            if (Observe != null)
            {
                throw new NotImplementedException();
            }
            return lActions;
        }
        public Action TagObservationTranslationNoState(Dictionary<string, List<Predicate>> dTags, Domain d, List<string> lIncludedTags, List<string> lExcludedTags)
        {
            string sName = Name;
            foreach (string sTag in lIncludedTags)
                sName += "-" + sTag;
            ParametrizedAction aNew = new ParametrizedAction(sName);
            if (this is ParametrizedAction)
            {
                foreach (Parameter p in ((ParametrizedAction)this).Parameters)
                    aNew.AddParameter(p);
            }

            if (Observe == null)
                throw new NotImplementedException();
            if (Effects != null)
                throw new NotImplementedException();
            Predicate pObserve = ((PredicateFormula)Observe).Predicate;

            aNew.Preconditions = GetPreconditionsNoState(dTags, d, lIncludedTags, lExcludedTags);
            ((CompoundFormula)aNew.Preconditions).AddOperand(new GroundedPredicate("NotInAction"));

            CompoundFormula cfEffects = new CompoundFormula("and");
            /*
            foreach (string sTag in lIncludedTags)
            {
                cfEffects.AddOperand(pObserve.GenerateKnowGiven(sTag, true));
            }
            */
            for (int i = 0; i < lIncludedTags.Count - 1; i++)
            {
                for (int j = i + 1; j < lIncludedTags.Count; j++)
                {
                    string sTag1 = lIncludedTags[i], sTag2 = lIncludedTags[j];
                    CompoundFormula cfWhen = new CompoundFormula("when");
                    CompoundFormula cfGiven = new CompoundFormula("and");
                    CompoundFormula cfEffect = new CompoundFormula("and");
                    cfGiven.AddOperand(pObserve.GenerateGiven(sTag1));
                    cfGiven.AddOperand(pObserve.GenerateGiven(sTag2).Negate());

                    Constant pTag1 = new Constant(Domain.TAG, sTag1);
                    Constant pTag2 = new Constant(Domain.TAG, sTag2);
                    Predicate ppKnowNot1Given2 = Predicate.GenerateKNot(pTag1, pTag2);
                    cfEffect.AddOperand(ppKnowNot1Given2);//no need to add the other side because all KNot will enforce t1 < t2

                    cfWhen.SimpleAddOperand(cfGiven);
                    cfWhen.SimpleAddOperand(cfEffect);

                    cfEffects.SimpleAddOperand(cfWhen);

                    cfWhen = new CompoundFormula("when");
                    cfGiven = new CompoundFormula("and");
                    cfGiven.AddOperand(pObserve.GenerateGiven(sTag1).Negate());
                    cfGiven.AddOperand(pObserve.GenerateGiven(sTag2));
                    cfWhen.SimpleAddOperand(cfGiven);
                    cfWhen.SimpleAddOperand(cfEffect);
                    cfEffects.SimpleAddOperand(cfWhen);

                }
            }

            aNew.Effects = cfEffects;

            return aNew;
        }
 public void SimplifyConditions()
 {
     Debug.WriteLine("Converting action " + Name);
     if (Effects != null)
     {
         CompoundFormula cfNewEffects = new CompoundFormula("and");
         List<CompoundFormula> lConditions = new List<CompoundFormula>();
         List<Formula> lMandatory = new List<Formula>();
         SplitEffects(lConditions, lMandatory);
         foreach (Formula f in lMandatory)
             cfNewEffects.SimpleAddOperand(f);
         int iCondition = 0, cConditions = lConditions.Count;
         foreach (CompoundFormula cfCondition in lConditions)
         {
             if(cfCondition.Operands[0] is PredicateFormula)
                 cfNewEffects.SimpleAddOperand(cfCondition);
             else
             {
                 CompoundFormula cfNewCondition = new CompoundFormula("when");
                 CompoundFormula cfNewFirst = (CompoundFormula)((CompoundFormula)cfCondition.Operands[0]).ToCNF();
                 cfNewCondition.AddOperand(cfNewFirst);
                 cfNewCondition.AddOperand(cfCondition.Operands[1]);
                 cfNewEffects.SimpleAddOperand(cfNewCondition);
             }
             iCondition++;
             Debug.Write("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + iCondition + "/" + cConditions);
         }
         Effects = cfNewEffects;
     }
 }
        public List<Action> SplitConditions(List<Predicate> lAdditionalPredicates)
        {
            List<Action> lActions = new List<Action>();

            ParametrizedAction aNewAdd = new ParametrizedAction(Name + "-Add");
            ParametrizedAction aNewRemove = new ParametrizedAction(Name + "-Remove");

            ParametrizedAction aNewTranslateRemove = new ParametrizedAction(Name + "-TranslateRemove");
            ParametrizedAction aNewTranslateAdd = new ParametrizedAction(Name + "-TranslateAdd");

            ParametrizedPredicate ppInFirst = new ParametrizedPredicate("P1-" + Name);
            ParametrizedPredicate ppInSecond = new ParametrizedPredicate("P2-" + Name);
            ParametrizedPredicate ppInThird = new ParametrizedPredicate("P3-" + Name);
            GroundedPredicate gpNotInAction = new GroundedPredicate("NotInAction");

            if (this is ParametrizedAction)
            {
                foreach (Parameter p in ((ParametrizedAction)this).Parameters)
                {
                    aNewAdd.AddParameter(p);
                    aNewRemove.AddParameter(p);
                    aNewTranslateAdd.AddParameter(p);
                    aNewTranslateRemove.AddParameter(p);

                    ppInFirst.AddParameter(p);
                    ppInSecond.AddParameter(p);
                    ppInThird.AddParameter(p);
                }
            }

            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            cfPreconditions.AddOperand(Preconditions);
            cfPreconditions.AddOperand(gpNotInAction);

            if (Effects == null)
                throw new NotImplementedException();

            HashSet<Predicate> lKnowEffects = new HashSet<Predicate>();
            CompoundFormula cfAddEffects = new CompoundFormula("and");
            CompoundFormula cfRemoveEffects = new CompoundFormula("and");
            CompoundFormula cfTranslateAddEffects = new CompoundFormula("and");
            CompoundFormula cfTranslateRemoveEffects = new CompoundFormula("and");
            List<Predicate> lRequireTranslation = new List<Predicate>();

            foreach (Formula f in lObligatory)
            {
                f.GetAllPredicates(lKnowEffects);
                cfAddEffects.AddOperand(f); //unconditional effects cannot conflict anyhow
            }

            if (lConditions.Count > 0)
            {
                lAdditionalPredicates.Add(ppInFirst);
                lAdditionalPredicates.Add(ppInSecond);
                lAdditionalPredicates.Add(ppInThird);

                aNewRemove.Preconditions = cfPreconditions;
                cfRemoveEffects.AddOperand(ppInFirst);
                cfRemoveEffects.AddOperand(gpNotInAction.Negate());

                aNewAdd.Preconditions = new PredicateFormula(ppInFirst);
                cfAddEffects.AddOperand(ppInSecond);
                cfAddEffects.AddOperand(ppInFirst.Negate());

                aNewTranslateRemove.Preconditions = new PredicateFormula(ppInSecond);
                cfTranslateRemoveEffects.AddOperand(ppInSecond.Negate());
                cfTranslateRemoveEffects.AddOperand(ppInThird);

                aNewTranslateAdd.Preconditions = new PredicateFormula(ppInThird);
                cfTranslateAddEffects.AddOperand(ppInThird.Negate());
                cfTranslateAddEffects.AddOperand(gpNotInAction);

                Dictionary<Predicate, Predicate> dTaggedPredicates = new Dictionary<Predicate, Predicate>();

                foreach (CompoundFormula cfCondition in lConditions)
                {
                    CompoundFormula cfAddCondition, cfRemoveCondition;
                    cfCondition.SplitAddRemove(dTaggedPredicates, out cfAddCondition, out cfRemoveCondition);
                    if (cfAddCondition != null)
                        cfAddEffects.AddOperand(cfAddCondition);
                    if (cfRemoveCondition != null)
                        cfRemoveEffects.AddOperand(cfRemoveCondition);

                }
                aNewAdd.Effects = cfAddEffects.Simplify();
                aNewRemove.Effects = cfRemoveEffects.Simplify();
                lActions.Add(aNewRemove);
                lActions.Add(aNewAdd);

                foreach (KeyValuePair<Predicate, Predicate> pair in dTaggedPredicates)
                {
                    CompoundFormula cfWhen = new CompoundFormula("when");
                    CompoundFormula cfAnd = new CompoundFormula("and");
                    cfWhen.AddOperand(pair.Key);

                    cfAnd.SimpleAddOperand(pair.Value);
                    cfAnd.SimpleAddOperand(pair.Key.Negate());
                    cfWhen.SimpleAddOperand(cfAnd);

                    if (pair.Value.Negation)
                        cfTranslateRemoveEffects.AddOperand(cfWhen);
                    else
                        cfTranslateAddEffects.AddOperand(cfWhen);
                }

                aNewTranslateAdd.Effects = cfTranslateAddEffects;
                aNewTranslateRemove.Effects = cfTranslateRemoveEffects;
                lActions.Add(aNewTranslateRemove);
                lActions.Add(aNewTranslateAdd);
            }
            else
                throw new NotImplementedException();

            if (Observe != null)
            {
                throw new NotImplementedException();

            }
            return lActions;
        }
        public List<Action> KnowWhetherTagCompilationSplitConditions(Dictionary<string, List<Predicate>> dTags, Domain d, List<string> lIncludedTags, 
            List<string> lExcludedTags, List<Predicate> lAdditionalPredicates)
        {
            string sName = Name + "-KW";
            foreach (string sTag in lIncludedTags)
                sName += "-" + sTag;
            ParametrizedAction aNewState = new ParametrizedAction(sName + "-State");
            ParametrizedAction aNewKnowledgeGain = new ParametrizedAction(sName + "-KnowledgeGain");
            ParametrizedAction aNewKnowledgeLoss = new ParametrizedAction(sName + "-KnowledgeLoss");

            ParametrizedPredicate ppInFirst = new ParametrizedPredicate("P1-" + sName);
            ParametrizedPredicate ppInSecond = new ParametrizedPredicate("P2-" + sName);
            GroundedPredicate gpNotInAction = new GroundedPredicate("NotInAction");

            if (this is ParametrizedAction)
            {
                foreach (Parameter p in ((ParametrizedAction)this).Parameters)
                {
                    aNewKnowledgeLoss.AddParameter(p);
                    aNewKnowledgeGain.AddParameter(p);
                    aNewState.AddParameter(p);
                    ppInFirst.AddParameter(p);
                    ppInSecond.AddParameter(p);
                }
            }

            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);

            CompoundFormula cfPreconditions = new CompoundFormula("and");
            Formula cfKWPreconditions = GetKnowWhetherPreconditions(dTags, d, lIncludedTags, lExcludedTags);
            cfPreconditions.AddOperand(cfKWPreconditions); //knowledge loss is the first action, so it will have all the preconditions
            cfPreconditions.AddOperand(gpNotInAction);

            if (Effects == null)
                throw new NotImplementedException();

            HashSet<Predicate> lKnowEffects = new HashSet<Predicate>();
            CompoundFormula cfStateEffects = new CompoundFormula("and");
            CompoundFormula cfKnowledgeLossEffects = new CompoundFormula("and");
            CompoundFormula cfKnowledgeGainEffects = new CompoundFormula("and");
            //CompoundFormula cfMandatoryEffects = new CompoundFormula("and");
            foreach (Formula f in lObligatory)
            {
                f.GetAllPredicates(lKnowEffects);
            }
            if (lKnowEffects.Count > 0)
            {
                foreach (string sTag in lIncludedTags)
                {
                    //~KNot t|?t -> effects|t
                    CompoundFormula cfKEffects = new CompoundFormula("and");

                    foreach (Predicate p in lKnowEffects)
                    {
                        Predicate pAdd = p.GenerateGiven(sTag);
                        cfKEffects.AddOperand(pAdd);
                        if (!d.AlwaysKnown(p))
                        {
                            pAdd = p.GenerateKnowGiven(sTag, true);
                            cfKEffects.AddOperand(pAdd);
                        }
                    }
                    cfStateEffects.SimpleAddOperand(cfKEffects);
                }
            }

            List<Action> lActions = new List<Action>();

            if (lConditions.Count > 0)
            {
                lAdditionalPredicates.Add(ppInFirst);
                lAdditionalPredicates.Add(ppInSecond);

                aNewKnowledgeLoss.Preconditions = cfPreconditions;
                aNewKnowledgeGain.Preconditions = new PredicateFormula(ppInFirst);
                aNewState.Preconditions = new PredicateFormula(ppInSecond);

                cfKnowledgeLossEffects.AddOperand(ppInFirst);
                cfKnowledgeLossEffects.AddOperand(gpNotInAction.Negate());

                cfKnowledgeGainEffects.AddOperand(ppInSecond);
                cfKnowledgeGainEffects.AddOperand(ppInFirst.Negate());

                cfStateEffects.AddOperand(ppInSecond.Negate());
                cfStateEffects.AddOperand(gpNotInAction);

                foreach (CompoundFormula cfCondition in lConditions)
                {
                    CompoundFormula cfK = null, cfAnd = null;
                    HashSet<Predicate> lConditionEffects = cfCondition.Operands[1].GetAllPredicates();
                    cfAnd = new CompoundFormula("and");

                    foreach (string sTag in lIncludedTags)
                    {
                        cfK = CreateTaggedCondition(cfCondition, d, sTag);
                        if (cfK != null)
                        {
                            cfStateEffects.SimpleAddOperand(cfK);
                        }
                    }

                    cfK = CreateTaggedKnowledgeWhetherGainConditions(cfCondition, d, lIncludedTags);
                    if (cfK != null)
                    {
                        cfKnowledgeGainEffects.SimpleAddOperand(cfK);
                    }

                    cfK = CreateTaggedKnowledgeWhetherLossCondition(cfCondition, d, lIncludedTags);
                    if (cfK != null && cfK.Operands.Count > 0)
                    {
                        cfKnowledgeLossEffects.SimpleAddOperand(cfK);
                    }
                }
                aNewKnowledgeGain.Effects = cfKnowledgeGainEffects.Simplify();
                aNewKnowledgeLoss.Effects = cfKnowledgeLossEffects.Simplify();
                lActions.Add(aNewKnowledgeLoss);
                lActions.Add(aNewKnowledgeGain);
            }
            else
            {
                aNewState.Preconditions = cfPreconditions;

            }
            aNewState.Effects = cfStateEffects.Simplify();
            lActions.Add(aNewState);

            if (Observe != null)
            {
                throw new NotImplementedException();
            }
            return lActions;
        }
        public Action KnowWhetherTagCompilation(Dictionary<string, List<Predicate>> dTags, Domain d, string sActionTag)
        {
            string sName = Name + "-KW-" + sActionTag;
            ParametrizedAction aNew = new ParametrizedAction(sName);
            if (this is ParametrizedAction)
            {
                foreach (Parameter p in ((ParametrizedAction)this).Parameters)
                    aNew.AddParameter(p);
            }

            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);

            aNew.Preconditions = GetKnowWhetherPreconditions(dTags, d, sActionTag);

            if (Effects != null)
            {
                HashSet<Predicate> lKnowEffects = new HashSet<Predicate>();
                CompoundFormula cfEffects = new CompoundFormula("and");
                CompoundFormula cfMandatoryEffects = new CompoundFormula("and");
                foreach (Formula f in lObligatory)
                {
                    f.GetAllPredicates(lKnowEffects);
                }
                if (lKnowEffects.Count > 0)
                {
                    foreach (string sTag in dTags.Keys)
                    {
                        //~KNot t|?t -> effects|t
                        CompoundFormula cfKEffects = new CompoundFormula("and");

                        foreach (Predicate p in lKnowEffects)
                        {
                            Predicate pAdd = p.GenerateGiven(sTag);
                            cfKEffects.AddOperand(pAdd);
                                //pAdd = p.GenerateKnowGiven(sTag, true);
                                //pAdd = p.GenerateGiven(sTag);
                                //cfKEffects.AddOperand(pAdd);

                        }

                        if (sTag == sActionTag)
                            cfEffects.SimpleAddOperand(cfKEffects);
                        else
                        {
                            CompoundFormula cfCondition = new CompoundFormula("when");
                            Predicate pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag),new Constant(Domain.TAG, sActionTag));

                            cfCondition.AddOperand(pNotTag.Negate());
                            cfCondition.AddOperand(cfKEffects);

                            cfEffects.SimpleAddOperand(cfCondition);
                        }
                    }
                }
                /*
                //forgetting: ~K~p
                foreach (Predicate p in lKnowEffects)
                {
                    Predicate pKNotp = new KnowPredicate(p.Negate());
                    cfEffects.AddOperand(pKNotp.Negate());
                }
                 * */
                foreach (CompoundFormula cfCondition in lConditions)
                {
                    CompoundFormula cfK = null, cfAnd = null;
                    HashSet<Predicate> lConditionEffects = cfCondition.Operands[1].GetAllPredicates();
                    cfAnd = new CompoundFormula("and");
                    /*
                    //since this action is done only for a part of the states, you lose all information in the effects
                    foreach (Predicate p in lConditionEffects)
                    {
                        if (p.Name != Domain.OPTION_PREDICATE)
                        {
                            Predicate pK = new KnowPredicate(p);
                            cfAnd.AddOperand(pK.Negate());
                            pK = new KnowPredicate(p.Negate());
                            cfAnd.AddOperand(pK.Negate());
                            pK = new KnowWhetherPredicate(p);
                            cfAnd.AddOperand(pK.Negate());
                        }
                    }
                    if (cfAnd.Operands.Count > 0)
                        cfEffects.SimpleAddOperand(cfAnd);
                     * */
                    foreach (string sTag in dTags.Keys)
                    {

                        cfK = CreateTaggedCondition(cfCondition, d, sTag);
                        if (cfK != null)
                        {
                            if (sTag == sActionTag)
                            {
                                cfEffects.SimpleAddOperand(cfK);
                            }
                            else
                            {
                                Predicate pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag),new Constant(Domain.TAG, sActionTag));

                                cfAnd = new CompoundFormula("and");
                                cfAnd.AddOperand(pNotTag.Negate());
                                if (cfK.Operator == "when")
                                {
                                    cfAnd.AddOperand(cfK.Operands[0]);
                                    cfK.Operands[0] = cfAnd;
                                    cfEffects.SimpleAddOperand(cfK);
                                }
                                else
                                    throw new NotImplementedException();
                            }
                        }
                    }
                    /*
                    cfK = CreateTaggedKnowledgeWhetherGainConditions(cfCondition, d, dTags.Keys, sActionTag);
                    if (cfK != null)
                    {
                        cfEffects.SimpleAddOperand(cfK);
                    }

                    cfK = CreateTaggedKnowledgeWhetherLossCondition(cfCondition, d, dTags.Keys, sActionTag);
                    if (cfK != null && cfK.Operands.Count > 0)
                    {
                        cfEffects.SimpleAddOperand(cfK);
                    }
                    */
                }
                aNew.Effects = cfEffects.Simplify();
            }
            if (Observe != null)
            {
                throw new NotImplementedException();
            }
            return aNew;
        }
        public Action KnowWhetherTagCompilation(Dictionary<string, List<Predicate>> dTags, Domain d, List<string> lIncludedTags, List<string> lExcludedTags)
        {
            string sName = Name + "-KW";
            foreach (string sTag in lIncludedTags)
                sName += "-" + sTag;
            ParametrizedAction aNew = new ParametrizedAction(sName);
            if (this is ParametrizedAction)
            {
                foreach (Parameter p in ((ParametrizedAction)this).Parameters)
                    aNew.AddParameter(p);
            }

            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);

            aNew.Preconditions = GetKnowWhetherPreconditions(dTags, d, lIncludedTags, lExcludedTags);

            if (Effects != null)
            {
                HashSet<Predicate> lKnowEffects = new HashSet<Predicate>();
                CompoundFormula cfEffects = new CompoundFormula("and");
                //CompoundFormula cfMandatoryEffects = new CompoundFormula("and");
                foreach (Formula f in lObligatory)
                {
                    f.GetAllPredicates(lKnowEffects);
                }
                if (lKnowEffects.Count > 0)
                {
                    List<Predicate> lFunctionExpressions = new List<Predicate>();
                    List<Predicate> lPredicates = new List<Predicate>();
                    foreach (Predicate p in lKnowEffects)
                    {
                        if (d.IsFunctionExpression(p.Name))
                            lFunctionExpressions.Add(p);
                        else
                            lPredicates.Add(p);
                    }

                    foreach (string sTag in lIncludedTags)
                    {
                        //~KNot t|?t -> effects|t
                        CompoundFormula cfKEffects = new CompoundFormula("and");

                        foreach (Predicate p in lPredicates)
                        {
                            Predicate pAdd = p.GenerateGiven(sTag);
                            cfKEffects.AddOperand(pAdd);
                            if (!d.AlwaysKnown(p))
                            {
                                pAdd = p.GenerateKnowGiven(sTag, true);
                                cfKEffects.AddOperand(pAdd);
                            }
                        }
                        cfEffects.SimpleAddOperand(cfKEffects);
                    }
                    foreach (Predicate p in lFunctionExpressions)
                        cfEffects.AddOperand(p);
                }
                List<Predicate> lAllKnowledgeToRemove = new List<Predicate>();
                foreach (CompoundFormula cfCondition in lConditions)
                {
                    CompoundFormula cfK = null, cfAnd = null;
                    HashSet<Predicate> lConditionEffects = cfCondition.Operands[1].GetAllPredicates();
                    cfAnd = new CompoundFormula("and");

                    foreach (string sTag in lIncludedTags)
                    {
                        cfK = CreateTaggedCondition(cfCondition, d, sTag);
                        if (cfK != null)
                        {
                            cfEffects.SimpleAddOperand(cfK);
                        }
                    }
                    if (SDRPlanner.RemoveAllKnowledge)
                    {
                        foreach (Predicate p in cfCondition.Operands[1].GetAllPredicates())
                        {
                            Predicate pTag = p;
                            if (p.Negation)
                                pTag = p.Negate();
                            if (!lAllKnowledgeToRemove.Contains(pTag))
                                lAllKnowledgeToRemove.Add(pTag);
                        }
                    }
                    else
                    {
                        cfK = CreateTaggedKnowledgeWhetherGainConditions(cfCondition, d, lIncludedTags);
                        if (cfK != null)
                        {
                            cfEffects.SimpleAddOperand(cfK);
                        }

                        cfK = CreateTaggedKnowledgeWhetherLossCondition(cfCondition, d, lIncludedTags);
                        if (cfK != null && cfK.Operands.Count > 0)
                        {
                            cfEffects.SimpleAddOperand(cfK);
                        }
                    }
                     /* causes the plan to add many merge actions
                    foreach (string sTag in lIncludedTags)
                    {
                        foreach (Predicate pForget in lConditionEffects)
                        {
                            if(pForget.Name != Domain.OPTION_PREDICATE)
                                cfEffects.AddOperand(pForget.GenerateKnowGiven(sTag, true).Negate());
                        }
                    }
                      * */
                }
                if (SDRPlanner.RemoveAllKnowledge)
                {
                    foreach (Predicate p in lAllKnowledgeToRemove)
                    {
                        foreach (string sTag in lIncludedTags)
                        {
                            Predicate pNegate = p.GenerateKnowGiven(sTag, true).Negate();
                            cfEffects.AddOperand(pNegate);
                        }
                    }
                }
                aNew.Effects = cfEffects.Simplify();
            }
            if (Observe != null)
            {
                throw new NotImplementedException();
            }
            return aNew;
        }
        private void ReadInitState(Problem p, Domain d, CompoundExpression eInitState)
        {
            foreach (Expression e in eInitState.SubExpressions)
            {
                CompoundExpression eSub = (CompoundExpression)e;
                if(d.IsFunctionExpression(eSub.Type))
                {
                    p.AddKnown(ReadFunctionExpression(eSub, null, d));
                }
                else if (d.ContainsPredicate(eSub.Type))
                {
                    p.AddKnown(ReadGroundedPredicate(eSub, d));
                }
                else
                {
                    if (eSub.Type != "unknown")
                    {
                        Formula f = ReadGroundedFormula(eSub, d);
                        if (f is CompoundFormula)
                            p.AddHidden((CompoundFormula)f);
                        if (f is PredicateFormula)//this happens in (not (p)) statments
                            p.AddKnown(((PredicateFormula)f).Predicate);
                    }
                    else
                    {
                        //causing a problem - add operand does some basic reasoning - adding p and ~p results in true for or statements.
                        //skipping unknown for now...

                        Predicate pUnknown = ReadGroundedPredicate((CompoundExpression)eSub.SubExpressions[0], d);
                        CompoundFormula cfOr = new CompoundFormula("or");
                        cfOr.SimpleAddOperand(pUnknown);
                        cfOr.SimpleAddOperand(pUnknown.Negate());
                        p.AddHidden(cfOr);

                    }
                }
            }
            p.ComputeRelevanceClosure();
        }
        //C->L  ==>   KWC/t->KWL/t
        private CompoundFormula CreateTaggedKnowledgeWhetherGainConditions(CompoundFormula cfCondition, Domain d, IEnumerable<string> lTags, string sActionTag)
        {
            HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
            HashSet<Predicate> lEffects = new HashSet<Predicate>();
            cfCondition.Operands[0].GetAllPredicates(lPreconditions);
            cfCondition.Operands[1].GetAllPredicates(lEffects);
            CompoundFormula cfAllConditions = new CompoundFormula("and");

            foreach (string sKWTag in lTags)
            {
                CompoundFormula cfWhen = new CompoundFormula("when");
                CompoundFormula cfPreconditions = new CompoundFormula("and");
                CompoundFormula cfEffects = new CompoundFormula("and");

                if (sKWTag != sActionTag)
                {
                    Predicate pNotKWTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sKWTag),new Constant(Domain.TAG, sActionTag));
                    cfPreconditions.AddOperand(pNotKWTag.Negate());
                }

                foreach (Predicate p in lPreconditions)
                {
                    if (p.Name == Domain.OPTION_PREDICATE)
                        return null;
                    Predicate pKGiven = null;

                    if (d.AlwaysKnown(p) && d.AlwaysConstant(p))
                    {
                        pKGiven = new KnowPredicate(p);
                        cfPreconditions.AddOperand(pKGiven);
                    }

                }

                foreach (string sTag in lTags)
                {
                    CompoundFormula cfAnd = new CompoundFormula("and");
                    foreach (Predicate p in lPreconditions)
                    {
                        Predicate pKGiven = null;

                        //if (d.AlwaysKnown(p) && d.AlwaysConstant(p))
                        if (d.AlwaysKnown(p))
                        {
                            continue;
                        }
                        else
                        {
                            /*
                            if (!d.AlwaysKnown(p))
                            {
                                pKGiven = p.GenerateKnowGiven(sTag, true);
                                cfAnd.AddOperand(pKGiven);
                            }
                             * */
                            pKGiven = p.GenerateGiven(sTag);
                            cfAnd.AddOperand(pKGiven);
                        }
                    }
                    if (cfAnd.Operands.Count > 0)//if there are no conditions then it is always true, and we don't need to care about whether the tag is consistent or not
                    {
                        if (sTag == sActionTag)
                        {
                            cfPreconditions.AddOperand(cfAnd);
                        }
                        else
                        {
                            CompoundFormula cfOr = new CompoundFormula("or");
                            Predicate pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag),new Constant(Domain.TAG, sActionTag));
                            cfOr.AddOperand(pNotTag);
                            cfOr.AddOperand(cfAnd);
                            cfPreconditions.AddOperand(cfOr);
                        }
                    }
                }

                foreach (Predicate p in lEffects)
                {
                    //Predicate pKEffect = p.GenerateKnowGiven(sKWTag, true);
                    Predicate pKEffect = p.GenerateGiven(sKWTag);
                    cfEffects.AddOperand(pKEffect);
                }

                cfWhen.AddOperand(cfPreconditions.Simplify());
                cfWhen.AddOperand(cfEffects.Simplify());
                cfAllConditions.SimpleAddOperand(cfWhen);
            }
            return cfAllConditions;
        }
 public CompoundFormula RemovePredicates(IEnumerable<Predicate> lPredicates)
 {
     CompoundFormula cfNew = new CompoundFormula(Operator);
     foreach (Formula f in Operands)
     {
         if (f is PredicateFormula)
         {
             if (!lPredicates.Contains(((PredicateFormula)f).Predicate))
                 cfNew.SimpleAddOperand(f);
         }
         else
             cfNew.SimpleAddOperand(((CompoundFormula)f).RemovePredicates(lPredicates));
     }
     return cfNew;
 }
        private CompoundFormula CreateTaggedKnowledgeWhetherLossCondition(CompoundFormula cfCondition, Domain d, IEnumerable<string> lTags, string sActionTag)
        {
            HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
            HashSet<Predicate> lEffects = new HashSet<Predicate>();
            cfCondition.Operands[0].GetAllPredicates(lPreconditions);
            cfCondition.Operands[1].GetAllPredicates(lEffects);
            bool bContainsOption = false;
            CompoundFormula cfAllConditions = new CompoundFormula("and");
            Predicate pNotTag = null;

            foreach (Predicate p in lPreconditions)
            {
                if (p.Name == Domain.OPTION_PREDICATE)
                    bContainsOption = true;
            }
            foreach (string sForgetTag in lTags)
            {
                CompoundFormula cfEffects = new CompoundFormula("and");
                foreach (Predicate p in lEffects)
                {
                    if (p.Name != Domain.OPTION_PREDICATE)
                    {
                        Predicate pKEffect = p.GenerateKnowGiven(sForgetTag, true);
                        cfEffects.AddOperand(pKEffect.Negate());
                    }
                }
                if (bContainsOption)
                {
                    CompoundFormula cfWhen = new CompoundFormula("when");
                    CompoundFormula cfPreconditions = new CompoundFormula("and");

                    if (sForgetTag != sActionTag)
                    {
                        pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sForgetTag),new Constant(Domain.TAG, sActionTag));
                        cfPreconditions.AddOperand(pNotTag.Negate());
                        cfWhen.AddOperand(cfPreconditions);
                        cfWhen.AddOperand(cfEffects);
                        cfAllConditions.SimpleAddOperand(cfWhen);
                    }
                    else
                    {
                        cfAllConditions.AddOperand(cfEffects);
                    }
                }
                else
                {
                    foreach (string sTag in lTags)
                    {

                        CompoundFormula cfWhen = new CompoundFormula("when");
                        CompoundFormula cfPreconditions = new CompoundFormula("and");

                        if (sForgetTag != sActionTag)
                        {
                            pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sForgetTag),new Constant(Domain.TAG, sActionTag));
                            cfPreconditions.AddOperand(pNotTag.Negate());
                        }

                        if (sTag != sActionTag)
                        {
                            pNotTag = Predicate.GenerateKNot(new Constant(Domain.TAG, sTag), new Constant(Domain.TAG, sActionTag));
                            cfPreconditions.AddOperand(pNotTag.Negate());
                        }

                        CompoundFormula cfOr = new CompoundFormula("or");
                        foreach (Predicate p in lPreconditions)
                        {
                            Predicate pKGiven = null, pGiven = null;

                            if (d.AlwaysKnown(p) && d.AlwaysConstant(p))
                            {
                                continue;//there is an underlying assumption here that always known + always constant means that it is also always true
                            }
                            else
                            {
                                if (!d.AlwaysKnown(p))
                                {
                                    pKGiven = p.GenerateKnowGiven(sTag, true);
                                    cfOr.AddOperand(pKGiven.Negate());
                                    //pGiven = p.GenerateGiven(sTag);
                                    //cfOr.AddOperand(pGiven.Negate());
                                }
                            }
                        }
                        if(cfOr.Operands.Count > 0)
                        {
                            cfPreconditions.AddOperand(cfOr);
                            cfWhen.AddOperand(cfPreconditions.Simplify());
                            cfWhen.AddOperand(cfEffects.Simplify());

                            cfAllConditions.AddOperand(cfWhen);
                        }
                    }
                }
            }
            return cfAllConditions;
        }
 public override Formula ApplyKnown(IEnumerable<Predicate> lKnown)
 {
     CompoundFormula cfNew = new CompoundFormula(Operator);
     if (Operator == "and" || Operator == "or" || Operator == "oneof")
     {
         foreach (Formula f in Operands)
         {
             Formula fTag = f.ApplyKnown(lKnown);
             if (fTag != null)
                 cfNew.SimpleAddOperand(fTag);
         }
     }
     else if (Operator == "when")
     {
         if (Operands[0].IsTrue(lKnown))
             return Operands[1];
         if (Operands[0].IsFalse(lKnown))
             return null;
         cfNew.AddOperand(Operands[0].ApplyKnown(lKnown));
         cfNew.AddOperand(Operands[1]);
     }
     else
         throw new NotImplementedException();
     return cfNew;
 }
        public Formula GetApplicableEffects(IEnumerable<Predicate> lPredicates, bool bContainsNegations)
        {
            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);
            CompoundFormula cfEffects = new CompoundFormula("and");
            foreach(Formula f in lObligatory)
                cfEffects.SimpleAddOperand(f);
            int iCondition = 0;
            List<Predicate> lEffects = new List<Predicate>();
            foreach(CompoundFormula cfWhen in lConditions)
            {
                if (cfWhen.Operands[0].ContainedIn(lPredicates, bContainsNegations))
                {
                    if (m_mMapConditionsChoices.ContainsKey(iCondition))
                    {
                        if (cfWhen.Operands[1] is CompoundFormula)
                        {
                            //cfEffects.AddOperand(((CompoundFormula)cfWhen.Operands[1]).Operands[m_mMapConditionsChoices[iCondition].First()]);
                            AddPredicatesToEffectList(lEffects,((CompoundFormula)cfWhen.Operands[1]).Operands[m_mMapConditionsChoices[iCondition].First()]);
                        }
                    }
                    else
                    {
                        //cfEffects.AddOperand(cfWhen.Operands[1]);
                        AddPredicatesToEffectList(lEffects, cfWhen.Operands[1]);

                    }
                }

                iCondition++;
            }
            foreach (Predicate p in lEffects)
            {
                cfEffects.AddOperand(p);
            }
            return cfEffects;
        }
 public override Formula ReduceConditions(IEnumerable<Predicate> lKnown)
 {
     CompoundFormula cfNew = new CompoundFormula(Operator);
     if (Operator == "and")// || Operator == "or" || Operator == "oneof")
     {
         foreach (Formula f in Operands)
         {
             if (f is CompoundFormula)
             {
                 Formula fTag = f.ReduceConditions(lKnown);
                 if (fTag != null)
                     cfNew.SimpleAddOperand(fTag);
             }
             else
                 cfNew.SimpleAddOperand(f);
         }
     }
     else if (Operator == "when")
     {
         Formula fReduced = Operands[0].Reduce(lKnown);
         if(fReduced.IsTrue(null))
             return Operands[1];
         if (fReduced.IsFalse(null))
             return null;
         cfNew.AddOperand(fReduced);
         cfNew.AddOperand(Operands[1]);
     }
     else
         throw new NotImplementedException();
     return cfNew;
 }
        /*
        public List<Action> KnowCompilationSplitConditions(Dictionary<string, List<Predicate>> dTags, List<string> lAlwaysKnown, List<Predicate> lAdditionalPredicates)
        {
            List<Action> lActions = new List<Action>();

            ParametrizedAction aNewState = new ParametrizedAction(Name + "-State");
            ParametrizedAction aNewKnowledgeGain = new ParametrizedAction(Name + "-KnowledgeGain");
            ParametrizedAction aNewKnowledgeLoss = new ParametrizedAction(Name + "-KnowledgeLoss");

            ParametrizedPredicate ppInFirst = new ParametrizedPredicate("P1-" + Name);
            ParametrizedPredicate ppInSecond = new ParametrizedPredicate("P2-" + Name);
            GroundedPredicate gpNotInAction = new GroundedPredicate("NotInAction");

            if (this is ParametrizedAction)
            {
                foreach (Parameter p in ((ParametrizedAction)this).Parameters)
                {
                    aNewKnowledgeLoss.AddParameter(p);
                    aNewKnowledgeGain.AddParameter(p);
                    aNewState.AddParameter(p);
                    ppInFirst.AddParameter(p);
                    ppInSecond.AddParameter(p);
                }
            }

            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            List<Predicate> lKnowPreconditions = new List<Predicate>();
            if (Preconditions != null)
            {
                Preconditions.GetAllPredicates(lKnowPreconditions);
                cfPreconditions.AddOperand(Preconditions);
                foreach (Predicate p in lKnowPreconditions)
                    if (!lAlwaysKnown.Contains(p.Name))
                        cfPreconditions.AddOperand(new PredicateFormula(new KnowPredicate(p)));
            }
            cfPreconditions.AddOperand(gpNotInAction);
            aNewKnowledgeGain.Preconditions = cfPreconditions;//knowledge gain is the first action, so it will have all the preconditions

            if (Effects == null)
                throw new NotImplementedException();

            List<Predicate> lKnowEffects = new List<Predicate>();
            CompoundFormula cfStateEffects = new CompoundFormula("and");
            CompoundFormula cfKnowledgeLossEffects = new CompoundFormula("and");
            CompoundFormula cfKnowledgeGainEffects = new CompoundFormula("and");

            foreach (Formula f in lObligatory)
            {
                f.GetAllPredicates(lKnowEffects);
                cfStateEffects.AddOperand(f);
            }

            foreach (Predicate p in lKnowEffects)
            {
                if (!lAlwaysKnown.Contains(p.Name))
                {
                    Predicate pKEffect = new KnowPredicate(p);
                    cfKnowledgeGainEffects.AddOperand(pKEffect);
                    pKEffect = new KnowPredicate(p.Negate());
                    cfKnowledgeGainEffects.AddOperand(pKEffect.Negate());
                    foreach (string sTag in dTags.Keys)
                    {
                        pKEffect = p.GenerateKnowGiven(sTag);
                        cfKnowledgeGainEffects.AddOperand(pKEffect);
                        pKEffect = p.Negate().GenerateKnowGiven(sTag);
                        cfKnowledgeGainEffects.AddOperand(pKEffect.Negate());
                    }
                }
            }
            if (lConditions.Count > 0)
            {
                lAdditionalPredicates.Add(ppInFirst);
                lAdditionalPredicates.Add(ppInSecond);

                aNewKnowledgeGain.Preconditions = cfPreconditions;
                aNewKnowledgeLoss.Preconditions = new PredicateFormula(ppInFirst);
                aNewState.Preconditions = new PredicateFormula(ppInSecond);

                cfKnowledgeGainEffects.AddOperand(ppInFirst);
                cfKnowledgeGainEffects.AddOperand(gpNotInAction.Negate());

                cfKnowledgeLossEffects.AddOperand(ppInSecond);
                cfKnowledgeLossEffects.AddOperand(ppInFirst.Negate());

                cfStateEffects.AddOperand(ppInSecond.Negate());
                cfStateEffects.AddOperand(gpNotInAction);

                foreach (CompoundFormula cfCondition in lConditions)
                {
                    cfStateEffects.AddOperand(cfCondition);
                    CompoundFormula cfK = CreateKnowledgeGainCondition(cfCondition, lAlwaysKnown, false);
                    if (cfK != null)
                        cfKnowledgeGainEffects.AddOperand(cfK);
                    cfK = CreateKnowledgeLossCondition(cfCondition, lAlwaysKnown);
                    if (cfK != null)
                        cfKnowledgeLossEffects.AddOperand(cfK);
                    foreach (string sTag in dTags.Keys)
                    {
                        cfK = CreateTaggedKnowledgeGainCondition(cfCondition, sTag, lAlwaysKnown, false);
                        if (cfK != null)
                            cfKnowledgeGainEffects.AddOperand(cfK);
                        cfK = CreateTaggedKnowledgeLossCondition(cfCondition, sTag, lAlwaysKnown);
                        if (cfK != null)
                            cfKnowledgeLossEffects.AddOperand(cfK);
                    }

                }
                aNewKnowledgeGain.Effects = cfKnowledgeGainEffects.Simplify();
                aNewKnowledgeLoss.Effects = cfKnowledgeLossEffects.Simplify();
                lActions.Add(aNewKnowledgeLoss);
                lActions.Add(aNewKnowledgeGain);
            }
            else
            {
                aNewState.Preconditions = cfPreconditions;
            }
            aNewState.Effects = cfStateEffects.Simplify();
            lActions.Add(aNewState);

            if (Observe != null)
            {
                throw new NotImplementedException();

            }
            return lActions;
        }
        */
        public Action KnowCompilation(Dictionary<string, List<Predicate>> dTags, Domain d)
        {
            Action aNew = Clone();
            aNew.Name = Name + "-K";
            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            HashSet<Predicate> lKnowPreconditions = new HashSet<Predicate>();
            if (Preconditions != null)
            {
                Preconditions.GetAllPredicates(lKnowPreconditions);
                foreach (Predicate p in lKnowPreconditions)
                {
                    cfPreconditions.AddOperand(new KnowPredicate(p));
                }
                aNew.Preconditions = cfPreconditions;
            }
            else
                aNew.Preconditions = null;
            if (Effects != null)
            {
                HashSet<Predicate> lKnowEffects = new HashSet<Predicate>();
                CompoundFormula cfEffects = new CompoundFormula("and");
                foreach (Formula f in lObligatory)
                {
                    f.GetAllPredicates(lKnowEffects);
                    //cfEffects.AddOperand(f);//BGUBGU - probably a bug here. Need to separate always known and the rest.
                }
                foreach (Predicate p in lKnowEffects)
                {

                    Predicate pKEffect = new KnowPredicate(p);
                    cfEffects.AddOperand(pKEffect);
                    Predicate pKNegateEffect = new KnowPredicate(p.Negate()).Negate();
                    cfEffects.AddOperand(pKNegateEffect);
                    /* why do we need all this?
                    pKEffect = new KnowPredicate(p.Negate());
                    cfEffects.AddOperand(pKEffect.Negate());
                    foreach (string sTag in dTags.Keys)
                    {
                        pKEffect = p.GenerateGiven(sTag);
                        cfEffects.AddOperand(pKEffect);
                        pKEffect = p.Negate().GenerateGiven(sTag);
                        cfEffects.AddOperand(pKEffect.Negate());
                    }
                        */
                }
                foreach (string sTag in dTags.Keys)
                {
                    //e|s
                    CompoundFormula cfKEffects = new CompoundFormula("and");
                    foreach (Predicate p in lKnowEffects)
                    {
                        Predicate pAdd = p.GenerateGiven(sTag);
                        cfKEffects.AddOperand(pAdd);
                    }
                    cfEffects.SimpleAddOperand(cfKEffects);
                }

                foreach (CompoundFormula cfCondition in lConditions)
                {
                    //cfEffects.AddOperand(cfCondition);//no longer valid? Perhaps needed if there are some "always known" conditions?
                    CompoundFormula cfK = CreateKnowledgeGainCondition(cfCondition, d.m_lAlwaysKnown, false);
                    if (cfK != null)
                        cfEffects.AddOperand(cfK);
                    cfK = CreateKnowledgeLossCondition(cfCondition, d.m_lAlwaysKnown, false);
                    if (cfK != null)
                    {
                        if(cfK.Operator == "and" || cfK.Operands[0] is PredicateFormula ||
                            cfK.Operands[0] is CompoundFormula && (((CompoundFormula)cfK.Operands[0]).Operands.Count > 0))
                            cfEffects.SimpleAddOperand(cfK);
                    }
                    //cfK = CreateKnowledgeGainCondition(cfCondition, d.m_lAlwaysKnown, true);
                    //if (cfK != null)
                    //    cfEffects.AddOperand(cfK);
                    cfK = CreateKnowledgeLossCondition(cfCondition, d.m_lAlwaysKnown, true);
                    if (cfK != null)
                    {
                        if (cfK.Operator == "and" || cfK.Operands[0] is PredicateFormula ||
                            cfK.Operands[0] is CompoundFormula && (((CompoundFormula)cfK.Operands[0]).Operands.Count > 0))
                            cfEffects.SimpleAddOperand(cfK);
                    }
                    foreach (string sTag in dTags.Keys)
                    {
                        cfK = CreateTaggedCondition(cfCondition, d, sTag);
                        cfEffects.AddOperand(cfK);
                        cfK = CreateTaggedKnowledgeWhetherGainCondition(cfCondition, d, sTag);
                        if (cfK != null)
                        {
                            cfEffects.SimpleAddOperand(cfK);
                        }
                        cfK = CreateTaggedKnowledgeWhetherLossCondition(cfCondition, d, sTag);
                        if (cfK != null)
                            cfEffects.SimpleAddOperand(cfK);
                    }

                }
                aNew.Effects = cfEffects.Simplify();
            }
            if (Observe != null)
            {
                throw new NotImplementedException();
            }
            return aNew;
        }