public Action KnowWhetherCompilation(Dictionary<string, List<Predicate>> dTags, Domain d)
        {
            Action aNew = Clone();
            aNew.Name = Name + "-KW";
            List<CompoundFormula> lConditions = new List<CompoundFormula>();
            List<Formula> lObligatory = new List<Formula>();
            SplitEffects(lConditions, lObligatory);
            CompoundFormula cfKWPreconditions = new CompoundFormula("and");
            HashSet<Predicate> lKnowPreconditions = new HashSet<Predicate>();
            if (Preconditions != null)
            {
                Preconditions.GetAllPredicates(lKnowPreconditions);
                foreach (Predicate p in lKnowPreconditions)
                {
                    if(!d.AlwaysKnown(p))
                        cfKWPreconditions.AddOperand(new KnowWhetherPredicate(p));
                    if(d.AlwaysKnown(p) && d.AlwaysConstant(p))
                        cfKWPreconditions.AddOperand(new KnowPredicate(p));
                }
                if (cfKWPreconditions.Operands.Count > 0)
                    aNew.Preconditions = cfKWPreconditions;
                else
                    aNew.Preconditions = null;
            }
            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);
                    //cfEffects.AddOperand(f);//BGUBGU - probably a bug here. Need to separate always known and the rest.
                }
                if (lKnowEffects.Count > 0)
                {
                    foreach (string sTag in dTags.Keys)
                    {
                        //K(preconditions|s)->K(effects|s)
                        CompoundFormula cfKEffects = new CompoundFormula("and");
                        CompoundFormula cfKPreconditions = new CompoundFormula("and");
                        foreach (Predicate p in lKnowPreconditions)
                        {
                            if (d.AlwaysKnown(p) && d.AlwaysConstant(p))
                                continue;
                            else
                                cfKPreconditions.AddOperand(p.GenerateGiven(sTag));
                        }
                        foreach (Predicate p in lKnowEffects)
                        {
                            Predicate pAdd = p.GenerateGiven(sTag);
                            cfKEffects.AddOperand(pAdd);
                            //Predicate pDelete = p.Negate().GenerateKnowGiven(sTag).Negate();
                            //cfKEffects.AddOperand(pDelete);
                        }
                        if (cfKPreconditions.Operands.Count > 0)
                        {
                            CompoundFormula cfCondition = new CompoundFormula("when");
                            cfCondition.AddOperand(cfKPreconditions);
                            cfCondition.AddOperand(cfKEffects);
                            cfEffects.AddOperand(cfCondition);
                        }
                        else
                            cfEffects.AddOperand(cfKEffects);
                    }
                }
                //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, cfOr = null, cfAnd = null;
                    //cfK = CreateKnowledgeGainCondition(cfCondition, d.m_lAlwaysKnown, false);
                    //if (cfK != null)
                    //    cfEffects.AddOperand(cfK);
                    cfK = CreateKnowledgeLossCondition(cfCondition, d.m_lAlwaysKnown, false);
                    if (cfK != null)
                    {
                        cfOr = new CompoundFormula("or");
                        foreach (Predicate p in lKnowPreconditions)
                        {
                            Predicate pKNot = new KnowPredicate(p.Negate());
                            cfOr.AddOperand(pKNot.Negate());
                        }
                        if (cfK.Operator == "when")
                        {
                            if (cfK.Operands[0] is CompoundFormula && ((CompoundFormula)cfK.Operands[0]).Operands.Count > 0)
                                cfOr.AddOperand(cfK.Operands[0]);
                            cfK.Operands[0] = cfOr.Simplify();
                        }
                        else
                        {
                            CompoundFormula cfWhen = new CompoundFormula("when");
                            cfWhen.AddOperand(cfOr.Simplify());
                            cfWhen.AddOperand(cfK);
                            cfK = cfWhen;
                        }
                        cfEffects.AddOperand(cfK);
                    }
                    //cfK = CreateKnowledgeGainCondition(cfCondition, d.m_lAlwaysKnown, true);
                    //if (cfK != null)
                    //    cfEffects.AddOperand(cfK);
                    cfK = CreateKnowledgeLossCondition(cfCondition, d.m_lAlwaysKnown, true);
                    if (cfK != null)
                    {
                        cfOr = new CompoundFormula("or");
                        foreach (Predicate p in lKnowPreconditions)
                        {
                            Predicate pKNot = new KnowPredicate(p.Negate());
                            cfOr.AddOperand(pKNot.Negate());
                        }
                        if (cfK.Operator == "when")
                        {
                            if (cfK.Operands[0] is PredicateFormula || ((CompoundFormula)cfK.Operands[0]).Operands.Count > 0)
                                cfOr.AddOperand(cfK.Operands[0]);
                            cfK.Operands[0] = cfOr.Simplify();
                        }
                        else
                        {
                            CompoundFormula cfWhen = new CompoundFormula("when");
                            cfWhen.AddOperand(cfOr.Simplify());
                            cfWhen.AddOperand(cfK);
                            cfK = cfWhen;
                        }
                        cfEffects.AddOperand(cfK);
                    }
                    foreach (string sTag in dTags.Keys)
                    {
                        cfK = CreateTaggedCondition(cfCondition, d, sTag);
                        if (cfK != null)
                        {
                            cfAnd = new CompoundFormula("and");
                            foreach (Predicate p in lKnowPreconditions)
                            {
                                if (d.AlwaysKnown(p) && d.AlwaysConstant(p))
                                    cfAnd.AddOperand(new KnowPredicate(p));
                                else
                                    cfAnd.AddOperand(p.GenerateGiven(sTag));
                            }
                            if (cfK.Operator == "when")
                            {
                                cfAnd.AddOperand(cfK.Operands[0]);
                                cfK.Operands[0] = cfAnd;
                                cfEffects.AddOperand(cfK);
                            }
                            else
                                throw new NotImplementedException();
                        }

                        cfK = CreateTaggedKnowledgeWhetherGainCondition(cfCondition, d, sTag);
                        if (cfK != null)
                        {
                            cfAnd = new CompoundFormula("and");
                            foreach (Predicate p in lKnowPreconditions)
                            {
                                if (d.AlwaysKnown(p) && d.AlwaysConstant(p))
                                    cfAnd.AddOperand(new KnowPredicate(p));
                                else
                                    cfAnd.AddOperand(p.GenerateGiven(sTag));
                            }
                            if (cfK.Operator == "when")
                            {
                                cfAnd.AddOperand(cfK.Operands[0]);
                                cfK.Operands[0] = cfAnd;
                                cfEffects.AddOperand(cfK);
                            }
                            else
                                throw new NotImplementedException();
                        }

                        cfK = CreateTaggedKnowledgeWhetherLossCondition(cfCondition, d, sTag);
                        if (cfK != null)
                        {
                            cfOr = new CompoundFormula("or");
                            foreach (Predicate p in lKnowPreconditions)
                            {
                                Predicate pKNot = new KnowPredicate(p.Negate());
                                cfOr.AddOperand(pKNot.Negate());
                            }
                            if (cfK.Operator == "when")
                            {
                                if (cfK.Operands[0] is PredicateFormula || ((CompoundFormula)cfK.Operands[0]).Operands.Count > 0)
                                    cfOr.AddOperand(cfK.Operands[0]);
                                cfK.Operands[0] = cfOr.Simplify();
                            }
                            else
                            {
                                CompoundFormula cfWhen = new CompoundFormula("when");
                                cfWhen.AddOperand(cfOr.Simplify());
                                cfWhen.AddOperand(cfK);
                                cfK = cfWhen;
                            }
                        }
                    }

                }
                aNew.Effects = cfEffects.Simplify();
            }
            if (Observe != null)
            {
                throw new NotImplementedException();
            }
            return aNew;
        }
 //given f->g replacing f with (f and g)
 private CompoundFormula ApplyCondition(CompoundFormula cfCondition)
 {
     Formula fPremise = cfCondition.Operands[0];
     CompoundFormula cfConclusion = new CompoundFormula("and");
     cfConclusion.AddOperand(cfCondition.Operands[0]);
     cfConclusion.AddOperand(cfCondition.Operands[1]);
     return (CompoundFormula)Replace(fPremise, cfConclusion.Simplify());
 }
 public CompoundFormula ApplyConditionsII(List<CompoundFormula> lConditions)
 {
     Dictionary<Formula, Formula> dTranslations = new Dictionary<Formula, Formula>();
     foreach (CompoundFormula cfCondition in lConditions)
     {
         Formula fRest = null;
         if (cfCondition.ConditionDeletesPrecondition(out fRest))
             dTranslations[cfCondition.Operands[0].Simplify()] = fRest;
         else
         {
             CompoundFormula cfAnd = new CompoundFormula("and");
             cfAnd.AddOperand(cfCondition.Operands[0].Simplify());
             cfAnd.AddOperand(cfCondition.Operands[1].Simplify());
             dTranslations[cfCondition.Operands[0].Simplify()] = cfAnd.Simplify();
         }
     }
     if (dTranslations.Count == 0)
         return this;
     return (CompoundFormula)Replace(dTranslations);
 }
        public Formula RegressNonDet(Action a)
        {
            CompoundFormula cfAndNot = new CompoundFormula("and");
            CompoundFormula cfOr = new CompoundFormula("or");
            int iCondition = 0;
            Predicate pNegate = Predicate.Negate();
            foreach (CompoundFormula cfCondition in a.GetConditions())
            {
                HashSet<Predicate> lEffects = cfCondition.Operands[1].GetAllPredicates();
                HashSet<Predicate> lOptionalEffects = cfCondition.Operands[1].GetAllOptionalPredicates();
                if (lEffects.Contains(Predicate))
                {
                    int iChoice = cfCondition.GetChoiceIndex(Predicate);
                    cfOr.AddOperand(cfCondition.Operands[0].CreateRegression(Predicate, iChoice));
                    a.SetChoice(iCondition, iChoice);
                }
                else if (lEffects.Contains(pNegate))
                {

                    if (!lOptionalEffects.Contains(pNegate))
                        cfAndNot.AddOperand(cfCondition.Operands[0].Negate());
                    else
                    {
                        int iChoice = cfCondition.GetChoiceIndex(pNegate);
                        int iOtherChoice = cfCondition.GetOtherChoiceIndex(pNegate);
                        cfAndNot.AddOperand(cfCondition.Operands[0].CreateRegression(pNegate, iChoice).Negate());
                        a.SetChoice(iCondition, iOtherChoice);
                    }
                }
                iCondition++;
            }
            cfOr.AddOperand(this);
            cfAndNot.AddOperand(cfOr);
            return cfAndNot.Simplify();
        }
        public override Formula RemoveUniversalQuantifiers(List<Constant> lConstants, List<Predicate> lConstantPredicates, Domain d)
        {
            CompoundFormula fNew = new CompoundFormula(Operator);
            //if (ToString().Contains("faulty") && !ToString().Contains("P_FALSE"))
            //    Console.WriteLine("**");
            foreach (Formula f in Operands)
            {
                Formula fRemoved = f.RemoveUniversalQuantifiers(lConstants, lConstantPredicates, d);
                if (fRemoved != null)
                {
                    if (fRemoved is PredicateFormula)
                    {
                        Predicate p = ((PredicateFormula)fRemoved).Predicate;
                        if (p.Name == Domain.TRUE_PREDICATE)
                        {
                            if (Operator == "and")
                                continue;
                            if (Operator == "or")
                                return fRemoved;
                            if (Operator == "when")
                            {
                                if (fNew.Operands.Count == 0)
                                {
                                    fNew.Operator = "and";
                                    continue;
                                }
                                else
                                    throw new NotImplementedException();
                            }
                            else
                                throw new NotImplementedException();
                        }
                        if (p.Name == Domain.FALSE_PREDICATE)
                        {
                            if (Operator == "and")
                                return fRemoved;
                            if (Operator == "or")
                                continue;
                            if (Operator == "when")
                            {
                                if (fNew.Operands.Count == 0)
                                {
                                    return null;
                                }
                                else
                                    throw new NotImplementedException();
                            }
                            else
                                throw new NotImplementedException();
                        }
                    }

                    fNew.AddOperand(fRemoved);
                }
            }

            if (fNew.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));
            }

            Formula fSimplified = fNew.Simplify();

            return fSimplified;
        }
        /*
         *
                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;
        }
        public Formula RegressDet(Action a)
        {
            Formula f = a.RegressDet(Predicate);
            if (f != null)
                return f;

            CompoundFormula cfAndNot = new CompoundFormula("and");
            CompoundFormula cfOr = new CompoundFormula("or");
            int iCondition = 0;
            Predicate pNegate = Predicate.Negate();
            foreach (CompoundFormula cfCondition in a.GetConditions())
            {
                HashSet<Predicate> lEffects = cfCondition.Operands[1].GetAllPredicates();
                if (lEffects.Contains(Predicate))
                {
                    cfOr.AddOperand(cfCondition.Operands[0].CreateRegression(Predicate, -1));
                }
                else if (lEffects.Contains(pNegate))
                {
                    cfAndNot.AddOperand(cfCondition.Operands[0].CreateRegression(pNegate, -1).Negate());
                }
                iCondition++;
            }
            cfOr.AddOperand(this);
            cfAndNot.AddOperand(cfOr);
            return cfAndNot.Simplify();
        }
 //(f->g) ==> (Kf->Kg)
 private CompoundFormula CreateKnowledgeGainCondition(CompoundFormula cfCondition, List<string> lAlwaysKnown, bool bKnowWhether)
 {
     CompoundFormula cfWhen = new CompoundFormula("when");
     HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
     HashSet<Predicate> lEffects = new HashSet<Predicate>();
     cfCondition.Operands[0].GetAllPredicates(lPreconditions);
     cfCondition.Operands[1].GetAllPredicates(lEffects);
     Formula fPreconditions = cfCondition.Operands[0].GetKnowledgeFormula(lAlwaysKnown, bKnowWhether);
     CompoundFormula cfEffects = new CompoundFormula("and");
     foreach (Predicate p in lEffects)
     //if (lAlwaysKnown == null || !lAlwaysKnown.Contains(p.Name))
     {
         if (bKnowWhether)
             cfEffects.AddOperand(new KnowWhetherPredicate(p));
         else
         {
             cfEffects.AddOperand(new KnowPredicate(p));
             cfEffects.AddOperand(new KnowPredicate(p.Negate()).Negate());
         }
     }
     if (cfEffects.Operands.Count == 0)
         return null;
     cfWhen.AddOperand(fPreconditions);
     cfWhen.AddOperand(cfEffects.Simplify());
     return cfWhen;
 }
 //(f->g) ==> (Kf->Kg)
 private CompoundFormula CreateKnowledgeGainConditionII(CompoundFormula cfCondition, List<string> lAlwaysKnown, bool bKnowWhether)
 {
     CompoundFormula cfWhen = new CompoundFormula("when");
     HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
     HashSet<Predicate> lEffects = new HashSet<Predicate>();
     cfCondition.Operands[0].GetAllPredicates(lPreconditions);
     cfCondition.Operands[1].GetAllPredicates(lEffects);
     CompoundFormula cfPreconditions = new CompoundFormula("and");
     //cfPreconditions.AddOperand(cfCondition.Operands[0].Simplify());
     foreach (Predicate p in lPreconditions)
     //if (lAlwaysKnown == null || !lAlwaysKnown.Contains(p.Name))
     {
         if (p.Name == Domain.OPTION_PREDICATE)
             return null;//we never know an option value
         if (bKnowWhether)
             cfPreconditions.AddOperand(new KnowWhetherPredicate(p));
         else
             cfPreconditions.AddOperand(new KnowPredicate(p));
     }
     CompoundFormula cfEffects = new CompoundFormula("and");
     foreach (Predicate p in lEffects)
     //if (lAlwaysKnown == null || !lAlwaysKnown.Contains(p.Name))
     {
         if (bKnowWhether)
             cfEffects.AddOperand(new KnowWhetherPredicate(p));
         else
         {
             cfEffects.AddOperand(new KnowPredicate(p));
             cfEffects.AddOperand(new KnowPredicate(p.Negate()).Negate());
         }
     }
     if (cfEffects.Operands.Count == 0)
         return null;
     cfWhen.AddOperand(cfPreconditions.Simplify());
     cfWhen.AddOperand(cfEffects.Simplify());
     return cfWhen;
 }
        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> 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 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 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;
        }
        //(f->g) ==> (~K~f->~K~g)
        private CompoundFormula CreateKnowledgeLossCondition(CompoundFormula cfCondition, List<string> lAlwaysKnown, bool bKnowWhether)
        {
            CompoundFormula cfWhen = new CompoundFormula("when");
            HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
            HashSet<Predicate> lEffects = new HashSet<Predicate>();
            cfCondition.Operands[0].GetAllPredicates(lPreconditions);
            cfCondition.Operands[1].GetAllPredicates(lEffects);
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            //cfPreconditions.AddOperand(cfCondition.Operands[0].Simplify().Negate());
            bool bOptionPrecondition = false;
            foreach (Predicate p in lPreconditions)
            {
                if (p.Name == Domain.OPTION_PREDICATE)
                    bOptionPrecondition = true;//we never know or not know the value of an option so we always forget here
                if (lAlwaysKnown == null || !lAlwaysKnown.Contains(p.Name))
                {
                    if(bKnowWhether)
                        cfPreconditions.AddOperand(new KnowWhetherPredicate(p.Negate()).Negate());
                    else
                        cfPreconditions.AddOperand(new KnowPredicate(p.Negate()).Negate());
                 }
            }
            //if (bAllKnown)
            //    return null;
            if (cfPreconditions.Operands.Count == 0)//if all given are known then there is no knowledge loss
                return null;
            CompoundFormula cfEffects = new CompoundFormula("and");
            foreach (Predicate p in lEffects)
            {
                if (p.Name == Domain.OPTION_PREDICATE)
                    continue;
                if (lAlwaysKnown == null || !lAlwaysKnown.Contains(p.Name))
                {
                    if (bKnowWhether)
                        cfEffects.AddOperand(new KnowWhetherPredicate(p.Negate()).Negate());
                    else
                        cfEffects.AddOperand(new KnowPredicate(p.Negate()).Negate());

                }
            }
            if (cfEffects.Operands.Count == 0)
                return null;
            if (bOptionPrecondition)
                return cfEffects;
            cfWhen.AddOperand(cfPreconditions.Simplify());
            cfWhen.AddOperand(cfEffects.Simplify());
            return cfWhen;
        }
        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;
        }
        //C->L  ==>   C/t->L/t
        private CompoundFormula CreateTaggedCondition(CompoundFormula cfCondition, Domain d, string sTag)
        {
            CompoundFormula cfWhen = new CompoundFormula("when");
            HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
            HashSet<Predicate> lEffects = new HashSet<Predicate>();
            cfCondition.Operands[0].GetAllPredicates(lPreconditions);
            cfCondition.Operands[1].GetAllPredicates(lEffects);
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            CompoundFormula cfEffects = new CompoundFormula("and");

            foreach (Predicate p in lPreconditions)
            {
                //Predicate pKGiven = p.Negate().GenerateGiven(sTag);
                //cfPreconditions.AddOperand(pKGiven.Negate());
                Predicate pKGiven = null;
                if (d.AlwaysKnown(p) && d.AlwaysConstant(p))
                    pKGiven = p;
                else
                    pKGiven = p.GenerateGiven(sTag);
                cfPreconditions.AddOperand(pKGiven);
            }
            foreach (Predicate p in lEffects)
            {
                Predicate pKEffect = p.GenerateGiven(sTag);
                cfEffects.AddOperand(pKEffect);
            }
            cfWhen.AddOperand(cfPreconditions.Simplify());
            cfWhen.AddOperand(cfEffects.Simplify());
            return cfWhen;
        }
        //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;
        }
 //C->L  ==>   KC/t->KL/t
 private CompoundFormula CreateTaggedKnowledgeGainCondition(CompoundFormula cfCondition, string sTag, List<string> lAlwaysKnown, bool bNonDetEffect)
 {
     CompoundFormula cfWhen = new CompoundFormula("when");
     HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
     HashSet<Predicate> lEffects = new HashSet<Predicate>();
     cfCondition.Operands[0].GetAllPredicates(lPreconditions);
     cfCondition.Operands[1].GetAllPredicates(lEffects);
     Formula cfPreconditions = cfCondition.Operands[0].GenerateGiven(sTag, lAlwaysKnown);
     CompoundFormula cfEffects = new CompoundFormula("and");
     foreach (Predicate p in lEffects)
     {
         if (lAlwaysKnown == null || !lAlwaysKnown.Contains(p.Name))
         {
             Predicate pKEffect = p.GenerateKnowGiven(sTag);
             cfEffects.AddOperand(pKEffect);
             if (bNonDetEffect)
             {
                 KnowPredicate pK = new KnowPredicate(p);
                 cfEffects.AddOperand(pK.Negate());
             }
         }
     }
     if (cfEffects.Operands.Count == 0)
         return null;
     cfWhen.AddOperand(cfPreconditions.Simplify());
     cfWhen.AddOperand(cfEffects.Simplify());
     return cfWhen;
 }
 public Formula RegressDetII(Action a)
 {
     CompoundFormula cfAndNot = new CompoundFormula("and");
     CompoundFormula cfOr = new CompoundFormula("or");
     foreach (CompoundFormula cfCondition in a.GetConditions())
     {
         HashSet<Predicate> lEffects = new HashSet<Predicate>();
         cfCondition.Operands[1].GetAllPredicates(lEffects);
         if (lEffects.Contains(Predicate))
         {
             cfOr.AddOperand(cfCondition.Operands[0]);
         }
         if (lEffects.Contains(Predicate.Negate()))
             cfAndNot.AddOperand(cfCondition.Operands[0].Negate());
     }
     cfAndNot.AddOperand(this);
     cfOr.AddOperand(cfAndNot);
     return cfOr.Simplify();
 }
 //C->L  ==>   ~K~C/t->~K~L/t
 private CompoundFormula CreateTaggedKnowledgeLossCondition(CompoundFormula cfCondition, string sTag, List<string> lAlwaysKnown)
 {
     CompoundFormula cfWhen = new CompoundFormula("when");
     HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
     HashSet<Predicate> lEffects = new HashSet<Predicate>();
     cfCondition.Operands[0].GetAllPredicates(lPreconditions);
     cfCondition.Operands[1].GetAllPredicates(lEffects);
     CompoundFormula cfPreconditions = new CompoundFormula("and");
     bool bAllKnown = true;
     foreach (Predicate p in lPreconditions)
     {
         if (lAlwaysKnown == null || !lAlwaysKnown.Contains(p.Name))
         {
             Predicate pKGiven = p.Negate().GenerateKnowGiven(sTag);
             cfPreconditions.AddOperand(pKGiven.Negate());
             bAllKnown = false;
         }
         else
             cfPreconditions.AddOperand(p);
     }
     if (bAllKnown)//when all given are known then there is no knowledge loss
         return null;
     CompoundFormula cfEffects = new CompoundFormula("and");
     foreach (Predicate p in lEffects)
     {
         if (lAlwaysKnown == null || !lAlwaysKnown.Contains(p.Name))
         {
             Predicate pKGiven = p.Negate().GenerateKnowGiven(sTag);
             cfEffects.AddOperand(pKGiven.Negate());
         }
     }
     if (cfEffects.Operands.Count == 0)
         return null;
     cfWhen.AddOperand(cfPreconditions.Simplify());
     cfWhen.AddOperand(cfEffects.Simplify());
     return cfWhen;
 }
 private Formula AddPreconditions(Action a)
 {
     CompoundFormula cfOr = new CompoundFormula("or");
     CompoundFormula cfAnd = new CompoundFormula("and");
     cfAnd.AddOperand(a.Preconditions);
     cfAnd.AddOperand(Negate());
     cfOr.AddOperand(cfAnd);
     cfOr.AddOperand(this);
     return cfOr.Simplify();
 }
        //C->L  ==>   KWC/t->KWL/t
        private CompoundFormula CreateTaggedKnowledgeWhetherGainConditions(CompoundFormula cfCondition, Domain d, List<string> lIncludedTags)
        {
            HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
            HashSet<Predicate> lEffects = new HashSet<Predicate>();
            cfCondition.Operands[0].GetAllPredicates(lPreconditions);
            cfCondition.Operands[1].GetAllPredicates(lEffects);

            CompoundFormula cfWhen = new CompoundFormula("when");
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            CompoundFormula cfEffects = new CompoundFormula("and");
            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 sKWTag in lIncludedTags)
            {

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

                    if (d.AlwaysKnown(p) && d.AlwaysConstant(p))
                    {
                        continue;
                    }
                    else
                    {
                        if (!d.AlwaysKnown(p))
                        {
                            pKGiven = p.GenerateKnowGiven(sKWTag, true);
                            cfAnd.AddOperand(pKGiven);
                        }
                        pKGiven = p.GenerateGiven(sKWTag);
                        cfAnd.AddOperand(pKGiven);
                    }
                }
                if (cfAnd.Operands.Count > 0)
                {
                    cfPreconditions.AddOperand(cfAnd);
                }

                foreach (Predicate p in lEffects)
                {
                    Predicate pKEffect = p.GenerateKnowGiven(sKWTag, true);
                    cfEffects.AddOperand(pKEffect);
                }
            }
            cfWhen.AddOperand(cfPreconditions.Simplify());
            cfWhen.AddOperand(cfEffects.Simplify());

            return cfWhen;
        }
 public CompoundFormula ToCNF2()
 {
     if (IsSimpleFormula())
         return this;
     if (IsCNF())
         return this;
     if (IsSimpleDisjunction())
     {
         CompoundFormula cfAnd = new CompoundFormula("and");
         cfAnd.AddOperand(this);
         return cfAnd;
     }
     bool bChanged = true;
     CompoundFormula cfRevised = new CompoundFormula(Operator);
     List<CompoundFormula> lSimpleOneOf = new List<CompoundFormula>();
     foreach (Formula f in Operands)
     {
         if (f is CompoundFormula)
         {
             CompoundFormula cf = (CompoundFormula)f;
             if (cf.IsSimpleOneOf())
                 lSimpleOneOf.Add(cf);
             else
                 cfRevised.AddOperand(((CompoundFormula)f).RemoveOneof(out bChanged));
         }
         else
             cfRevised.AddOperand(f);
     }
     cfRevised = (CompoundFormula)cfRevised.Simplify();
     bChanged = true;
     while (bChanged)
     {
         bChanged = false;
         cfRevised = (CompoundFormula)cfRevised.RemoveNestedConjunction(out bChanged);
     }
     /*
     if (cfRevised.Operator != "and")
     {
         CompoundFormula cfAnd = new CompoundFormula("and");
         cfAnd.AddOperand(cfRevised);
         cfRevised = cfAnd;
     }
      */
     foreach (CompoundFormula cf in lSimpleOneOf)
         cfRevised.AddOperand(cf);
     Debug.Assert(cfRevised.IsCNF());
     return cfRevised;
 }
        //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;
        }
 //given f->g replace f everywhere with (~f or f and g)
 //possible problem - results in always true statements. When previous formula was f1 xor f2, and f1 was replaced, now the f1 revision is always true and f2 must be false
 private CompoundFormula ApplyConditionII(CompoundFormula cfCondition)
 {
     Formula fPremise = cfCondition.Operands[0];
     CompoundFormula cfConclusion = new CompoundFormula("and");
     cfConclusion.AddOperand(cfCondition.Operands[0]);
     cfConclusion.AddOperand(cfCondition.Operands[1]);
     Formula fNegatePremise = fPremise.Negate();
     CompoundFormula cfOr = new CompoundFormula("or");
     cfOr.AddOperand(fNegatePremise);
     cfOr.AddOperand(cfConclusion.Simplify());
     return (CompoundFormula)Replace(fPremise, cfOr);
 }
        //C->L  ==>   ~KW~C/t->~KW~L/t
        private CompoundFormula CreateTaggedKnowledgeWhetherLossCondition(CompoundFormula cfCondition, Domain d, string sTag)
        {
            CompoundFormula cfWhen = new CompoundFormula("when");
            HashSet<Predicate> lPreconditions = new HashSet<Predicate>();
            HashSet<Predicate> lEffects = new HashSet<Predicate>();
            cfCondition.Operands[0].GetAllPredicates(lPreconditions);
            cfCondition.Operands[1].GetAllPredicates(lEffects);
            CompoundFormula cfPreconditions = new CompoundFormula("and");
            bool bContainsOption = false;
            foreach (Predicate p in lPreconditions)
            {
                if (p.Name == Domain.OPTION_PREDICATE)
                    bContainsOption = true;
                Predicate pKGiven = null;
                if (!d.AlwaysKnown(p))
                {
                    pKGiven = p.GenerateKnowGiven(sTag, true);
                    cfPreconditions.AddOperand(pKGiven.Negate());
                }
            }
            if (cfPreconditions.Operands.Count == 0)
                return null;
            CompoundFormula cfEffects = new CompoundFormula("and");
            foreach (Predicate p in lEffects)
            {
                if (p.Name == Domain.OPTION_PREDICATE)
                    continue;
                Predicate pKGiven = p.Negate().GenerateKnowGiven(sTag, true);
                cfEffects.AddOperand(pKGiven.Negate());
            }
            if (cfEffects.Operands.Count == 0)
                return null;

            if (bContainsOption)
                return cfEffects;
            cfWhen.AddOperand(cfPreconditions.Simplify());
            cfWhen.AddOperand(cfEffects.Simplify());
            return cfWhen;
        }
 public override Formula Regress(Action a)
 {
     CompoundFormula cfNew = new CompoundFormula(Operator);
     foreach (Formula f in Operands)
     {
         //Formula fRgressed = f.Regress(a, lObserved);
         Formula fRgressed = f.Regress(a);
         //what happens if we get  "TRUE" or "FALSE"?
         cfNew.AddOperand(fRgressed);
     }
     return cfNew.Simplify();
 }
        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;
        }