public void AddInitialStateFormula(CompoundFormula cf)
        {
            if (false && !cf.IsSimpleFormula())
            {
                CompoundFormula cfCNF = (CompoundFormula)cf.ToCNF();
                foreach (CompoundFormula cfSub in cfCNF.Operands)
                    AddInitialStateFormula(cfSub);
                return;
            }

            m_lOriginalHiddenFormulas.Add(cf);
            m_lHiddenFormulas.Add((CompoundFormula)cf);
            EfficientFormula ef = new EfficientFormula(cf.Operator);
            ef.OriginalFormula = cf;
            m_lEfficientHidden.Add(ef);
            HashSet<Predicate> lHidden = cf.GetAllPredicates();
            foreach (Predicate p in lHidden)
            {
                GroundedPredicate pCanonical = (GroundedPredicate)p.Canonical();
                if (!Unknown.Contains(pCanonical))
                    Unknown.Add(pCanonical);
                if (!m_dMapPredicatesToFormulas.ContainsKey(pCanonical))
                {
                    m_dMapPredicatesToFormulas[pCanonical] = new List<int>();

                    int iIndex = m_dMapIndexToPredicate.Count;
                    m_dMapIndexToPredicate.Add(pCanonical);
                    m_dMapPredicatesToIndexes[pCanonical] = iIndex;
                    m_dMapPredicateToEfficientFormula.Add(new List<int>());
                }

                int iPredicate = m_dMapPredicatesToIndexes[pCanonical];

                ef.SetVariableValue(iPredicate, !p.Negation);
                m_dMapPredicateToEfficientFormula[iPredicate].Add(m_lEfficientHidden.Count - 1);

                m_dMapPredicatesToFormulas[pCanonical].Add(m_lHiddenFormulas.Count - 1);

            }

            m_cfCNFHiddenState.AddOperand(cf);
            if (!cf.IsSimpleConjunction() && !cf.IsSimpleOneOf() && SDRPlanner.EnforceCNF)
            {

                m_cfCNFHiddenState = (CompoundFormula)m_cfCNFHiddenState.ToCNF();
            }
        }
        /*
        public CompoundFormula ToTimeFormula(int iTime, List<Predicate> lObserved, List<Predicate> lUnknown)
        {
            //currently we will only do the conditional effects
            List<CompoundFormula> lConditions = GetConditions();
            CompoundFormula cfAnd = new CompoundFormula("and");
            Dictionary<Predicate, List<Formula>> dAdd = new Dictionary<Predicate, List<Formula>>();
            Dictionary<Predicate, List<Formula>> dDelete = new Dictionary<Predicate, List<Formula>>();
            List<Predicate> lAllEffects = new List<Predicate>();
            foreach (CompoundFormula cfCondition in lConditions)
            {
                //no need to add known effects into the belief
                if (!cfCondition.Operands[0].IsTrue(lObserved) && !cfCondition.Operands[0].IsFalse(lObserved))
                {
                    Formula fReducedCondition = cfCondition.Operands[0].Reduce(lObserved);
                    List<Predicate> lPredicates = cfCondition.Operands[1].GetAllPredicates();
                    foreach (Predicate p in lPredicates)
                    {
                        Predicate pTrue = p;
                        if (p.Negation)
                            pTrue = p.Negate();
                        if (!dAdd.ContainsKey(pTrue))
                        {
                            dAdd[pTrue] = new List<Formula>();
                            lAllEffects.Add(pTrue);
                        }
                        if (!dDelete.ContainsKey(pTrue))
                            dDelete[pTrue] = new List<Formula>();
                        if (p.Negation)
                            dDelete[pTrue].Add(fReducedCondition);
                        else
                            dAdd[pTrue].Add(fReducedCondition);
                    }
                }
            }
            foreach (Predicate p in lAllEffects)
            {
                CompoundFormula cfOneof1 = new CompoundFormula("oneof");
                CompoundFormula cfOrDeletes = new CompoundFormula("or");
                CompoundFormula cfOrAdds = new CompoundFormula("or");
                CompoundFormula cfEffectAndNotDelete = new CompoundFormula("and");
                CompoundFormula cfNotDeleteOrAdd = new CompoundFormula("or");

                foreach (Formula f in dDelete[p])
                    cfOrDeletes.AddOperand(f);

                foreach(Formula f in dAdd[p])
                    cfOrAdds.AddOperand(f);

                if (!lObserved.Contains(p.Negate()))
                {
                    cfEffectAndNotDelete.AddOperand(p);
                    cfEffectAndNotDelete.AddOperand(cfOrDeletes.Negate());
                    if(!cfEffectAndNotDelete.IsFalse(lObserved))
                        cfNotDeleteOrAdd.AddOperand(cfEffectAndNotDelete);
                }
                cfNotDeleteOrAdd.AddOperand(cfOrAdds);

                //seems right - can still have bugs
                if (cfNotDeleteOrAdd.IsFalse(lObserved))
                {
                    cfAnd.AddOperand(new TimePredicate(p.Negate(), iTime));
                }
                else if (cfNotDeleteOrAdd.IsTrue(lObserved))
                {
                    cfAnd.AddOperand(new TimePredicate(p, iTime));
                }
                else
                {
                    cfOneof1.AddOperand(cfNotDeleteOrAdd.AddTime(iTime - 1));
                    cfOneof1.AddOperand(new TimePredicate(p.Negate(), iTime));

                    cfAnd.AddOperand(cfOneof1);
                }

                CompoundFormula cfOneof2 = new CompoundFormula("oneof");
                CompoundFormula cfNotEffectAndNotAdd = new CompoundFormula("and");
                CompoundFormula cfNotAddOrDelete = new CompoundFormula("or");

                if (!lObserved.Contains(p))
                {
                    cfNotEffectAndNotAdd.AddOperand(p.Negate());
                    cfNotEffectAndNotAdd.AddOperand(cfOrAdds.Negate());
                    if (!cfNotEffectAndNotAdd.IsFalse(lObserved))
                        cfNotAddOrDelete.AddOperand(cfNotEffectAndNotAdd);
                }
                cfNotAddOrDelete.AddOperand(cfOrDeletes);

                //seems right - can still have bugs
                if (cfNotAddOrDelete.IsFalse(lObserved))
                {
                    cfAnd.AddOperand(new TimePredicate(p, iTime));
                }
                else if (cfNotAddOrDelete.IsTrue(lObserved))
                {
                    cfAnd.AddOperand(new TimePredicate(p.Negate(), iTime));
                }
                else
                {
                    cfOneof2.AddOperand(cfNotAddOrDelete.AddTime(iTime - 1));
                    cfOneof2.AddOperand(new TimePredicate(p, iTime));

                    cfAnd.AddOperand(cfOneof2);
                }
            }
            foreach (Predicate p in lUnknown)
            {
                if (!dAdd.ContainsKey(p))
                {
                    CompoundFormula cfOneOf = new CompoundFormula("oneof");
                    cfOneOf.AddOperand(new TimePredicate(p.Negate(), iTime - 1));
                    cfOneOf.AddOperand(new TimePredicate(p, iTime));
                    cfAnd.AddOperand(cfOneOf);
                }
            }
            return cfAnd.ToCNF();
        }

        */
        public CompoundFormula ToTimeFormula(int iTime, HashSet<Predicate> lObserved, HashSet<Predicate> lUnknown)
        {
            //currently we will only do the conditional effects
            List<CompoundFormula> lConditions = GetConditions();
            CompoundFormula cfAnd = new CompoundFormula("and");
            Dictionary<Predicate, List<Formula>> dAdd = new Dictionary<Predicate, List<Formula>>();
            Dictionary<Predicate, List<Formula>> dDelete = new Dictionary<Predicate, List<Formula>>();
            List<Predicate> lEffects = new List<Predicate>();
            foreach (CompoundFormula cfCondition in lConditions)
            {
                //no need to add known effects into the belief
                if (!cfCondition.Operands[0].IsTrue(lObserved) && !cfCondition.Operands[0].IsFalse(lObserved))
                {
                    Formula fNotCondition = cfCondition.Operands[0].Reduce(lObserved).Negate();
                    HashSet<Predicate> lPredicates = cfCondition.Operands[1].GetAllPredicates();
                    foreach (Predicate p in lPredicates)
                    {
                        CompoundFormula cfOr = new CompoundFormula("or");
                        cfOr.AddOperand(fNotCondition.AddTime(iTime - 1));
                        cfOr.AddOperand(new TimePredicate(p, iTime));
                        cfAnd.AddOperand(cfOr);

                        Predicate pTrue = p;
                        if (p.Negation)
                            pTrue = p.Negate();
                        if (!dAdd.ContainsKey(pTrue))
                        {
                            dAdd[pTrue] = new List<Formula>();
                            dDelete[pTrue] = new List<Formula>();
                            lEffects.Add(pTrue);
                        }
                        if(p.Negation)
                            dDelete[pTrue].Add(cfCondition.Operands[0].Reduce(lObserved));
                        else
                            dAdd[pTrue].Add(cfCondition.Operands[0].Reduce(lObserved));
                    }
                }
            }
            foreach (Predicate p in lEffects)
            {
                CompoundFormula cfOr = new CompoundFormula("or");
                cfOr.AddOperand(new TimePredicate(p, iTime - 1));
                foreach (Formula f in dAdd[p])
                {
                    cfOr.AddOperand(f.AddTime(iTime - 1));
                }
                cfOr.AddOperand(new TimePredicate(p.Negate(), iTime));
                cfAnd.AddOperand(cfOr);

                cfOr = new CompoundFormula("or");
                cfOr.AddOperand(new TimePredicate(p.Negate(), iTime - 1));
                foreach (Formula f in dDelete[p])
                {
                    cfOr.AddOperand(f.AddTime(iTime - 1));
                }
                cfOr.AddOperand(new TimePredicate(p, iTime));
                cfAnd.AddOperand(cfOr);
            }

            HashSet<Predicate> lMandatory = GetMandatoryEffects();
            foreach (Predicate p in lUnknown)
            {
                if (!lEffects.Contains(p) && !lMandatory.Contains(p))
                {
                    CompoundFormula cfOneOf = new CompoundFormula("oneof");
                    cfOneOf.AddOperand(new TimePredicate(p.Negate(), iTime - 1));
                    cfOneOf.AddOperand(new TimePredicate(p, iTime));
                    cfAnd.AddOperand(cfOneOf);
                }
            }
            return (CompoundFormula)cfAnd.ToCNF();
        }