public void AddConstant(Constant c)
 {
     ((List<Constant>)Constants).Add(c);
     m_sCachedToString = null;
 }
        private Formula ReadPredicate(CompoundExpression exp, Dictionary<string, string> dParameterNameToType, bool bParametrized, Domain d)
        {
            Predicate p = null;
            int iExpression = 0;
            string sName = "";

            if (bParametrized)
                p = new ParametrizedPredicate(exp.Type);
            else
                p = new GroundedPredicate(exp.Type);
            bool bAllConstants = true;
            for (iExpression = 0; iExpression < exp.SubExpressions.Count; iExpression++)
            {
                sName = exp.SubExpressions[iExpression].ToString();
                if (bParametrized)
                {
                    Argument a = null;
                    if (sName.StartsWith("?"))
                    {
                        a = new Parameter(dParameterNameToType[sName], sName);
                        bAllConstants = false;
                    }
                    else
                    {
                        a = new Constant(d.ConstantNameToType[sName], sName);
                    }
                    ((ParametrizedPredicate)p).AddParameter(a);
                }
                else
                {
                    try
                    {
                        Constant c = new Constant(d.ConstantNameToType[sName], sName);
                        ((GroundedPredicate)p).AddConstant(c);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine();
                    }
                }
            }
            if (bParametrized)
                if (!MatchParametersToPredicateDeclaration((ParametrizedPredicate)p, d))
                    throw new NotImplementedException();

            if (bParametrized && bAllConstants)
            {
                GroundedPredicate gp = new GroundedPredicate(p.Name);
                foreach (Constant c in ((ParametrizedPredicate)p).Parameters)
                    gp.AddConstant(c);
                p = gp;
            }

            PredicateFormula vf = new PredicateFormula(p);
            return vf;
        }
        /*
         *
                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 Predicate ReadFunctionExpression(CompoundExpression exp, Dictionary<string, string> dParameterNameToType, Domain d)
        {
            Constant c = null;
            string sName = exp.SubExpressions[0].ToString();

            if (exp.Type == "=")
            {
                string sParam1 = exp.SubExpressions[0].ToString();
                string sParam2 = exp.SubExpressions[1].ToString();
                if (!dParameterNameToType.ContainsKey(sParam1))
                    throw new ArgumentException("First argument of = must be a parameter");
                ParametrizedPredicate pp = new ParametrizedPredicate("=");
                pp.AddParameter(new Parameter(dParameterNameToType[sParam1], sParam1));
                if (dParameterNameToType.ContainsKey(sParam2))
                    pp.AddParameter(new Parameter(dParameterNameToType[sParam2], sParam2));
                else
                    pp.AddParameter(new Constant(d.ConstantNameToType[sParam2], sParam2));
                return pp;

            }

            GroundedPredicate p = new GroundedPredicate(exp.Type);
            double dValue = 0.0;
            if (d.Functions.Contains(sName))
                c = new Constant("Function", sName);
            else
                throw new ArgumentException("First argument of increase or decrease must be a function");
            p.AddConstant(c);

            sName = exp.SubExpressions[1].ToString();
            if (double.TryParse(sName, out dValue))
                c = new Constant("Number", sName);
            else
                throw new ArgumentException("Second argument of increase or decrease must be a number");
            p.AddConstant(c);
            return p;
        }
        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;
        }