private PartiallySpecifiedState Apply(Action aOrg, out Formula fObserve, bool bPropogateOnly)
        {
            //Debug.WriteLine("Executing " + a.Name);
            fObserve = null;
            if (aOrg is ParametrizedAction)
                return null;

            DateTime dtStart = DateTime.Now;

            Action a = aOrg.ApplyObserved(m_lObserved);

            //no need to check pre during propogation - they were already confirmed the first time
            if (!bPropogateOnly && a.Preconditions != null && !IsApplicable(a))
                return null;

            a.ComputeRegressions();

            tsPre += DateTime.Now - dtStart;
            dtStart = DateTime.Now;

            State sNew = null;
            if (!bPropogateOnly && UnderlyingEnvironmentState != null)
                sNew = UnderlyingEnvironmentState.Apply(a);

            CompoundFormula cfAndChoices = null;
            if (!bPropogateOnly && a.ContainsNonDeterministicEffect)
            {
                a = a.RemoveNonDeterminism(Time, out cfAndChoices);
            }

            PartiallySpecifiedState bsNew = new PartiallySpecifiedState(this, a);
            if (sNew != null)
            {
                bsNew.UnderlyingEnvironmentState = sNew;
                if (!bPropogateOnly && bsNew.Time != sNew.Time)
                    Debug.WriteLine("BUGBUG");

            }

            if (a.Effects != null)
            {
                if (a.HasConditionalEffects)
                {
                    List<CompoundFormula> lApplicableConditions = ApplyKnown(a.GetConditions());
                    bsNew.ApplyKnowledgeLoss(lApplicableConditions);
                    HashSet<Predicate> lAddEffects = new HashSet<Predicate>(), lRemoveEffects = new HashSet<Predicate>();
                    a.GetApplicableEffects(m_lObserved,lAddEffects, lRemoveEffects, true);
                    //first removing then adding
                    foreach (Predicate p in lRemoveEffects)
                        bsNew.AddEffect(p);
                    foreach (Predicate p in lAddEffects)
                        bsNew.AddEffect(p);
                    //bsNew.UpdateHidden(a, m_lObserved);
                    bsNew.UpdateHidden();
                }
                else
                {
                    bsNew.AddEffects(a.Effects);
                }
            }

            //if(m_sPredecessor != null)//the first one holds all knowns, to avoid propogation from the initial belief
             //   RemoveDuplicateObserved(bsNew.m_lObserved);//if p is true at t+1 and p is true at t, there is no point in maintaining the copy at t

            tsEffects += DateTime.Now - dtStart;
            dtStart = DateTime.Now;

            if (!bPropogateOnly && a.Observe != null)
            {
                //first applying the action (effects) and then observing
                fObserve = bsNew.UnderlyingEnvironmentState.Observe(a.Observe);

                bsNew.GeneratingObservation = fObserve;
                bsNew.AddObserved(fObserve);

                /*
                if (ReviseInitialBelief(fObserve))
                    bsNew.PropogateObservedPredicates();
                 * */
                HashSet<int> hsModified = m_bsInitialBelief.ReviseInitialBelief(fObserve, this);
                if (hsModified.Count > 0)
                {
                    if (!SDRPlanner.OptimizeMemoryConsumption)
                        bsNew.PropogateObservedPredicates();
                }

            }

            tsObs += DateTime.Now - dtStart;

            if (bsNew != null && cfAndChoices != null)
                m_bsInitialBelief.AddInitialStateFormula(cfAndChoices);

            if (!bPropogateOnly && bsNew.Time != sNew.Time)
                Debug.WriteLine("BUGBUG");

            return bsNew;
        }
        public HashSet<int> ReviseInitialBelief(Formula fObserve, PartiallySpecifiedState pssLast)
        {
            DateTime dtBefore = DateTime.Now;
            Stack<PartiallySpecifiedState> sTrace = new Stack<PartiallySpecifiedState>();
            Stack<List<Formula>> sForumalsTrace = new Stack<List<Formula>>();
            PartiallySpecifiedState pssCurrent = pssLast, pssSuccessor = null;
            HashSet<int> hsModifiedClauses = new HashSet<int>();
            //Formula fToRegress = fObserve, fRegressed = null;
            bool bTrueRegression = false;
            int cSteps = 0;

            count_revisions++;
            List<Formula> lCurrentFormulas = new List<Formula>();
            List<Formula> lRegressedFormulas = new List<Formula>();

            lCurrentFormulas.Add(fObserve);

            //TimeSpan ts1 = new TimeSpan(0), ts2 = new TimeSpan(0);
            //DateTime dtStart = DateTime.Now;
            while (pssCurrent.Predecessor != null)
            {
                sTrace.Push(pssCurrent);
                sForumalsTrace.Push(lCurrentFormulas);
                lRegressedFormulas = new List<Formula>();
                HashSet<Predicate> hsNew = new HashSet<Predicate>();
                foreach (Formula fCurrent in lCurrentFormulas)
                {
                    if (fCurrent.IsTrue(pssCurrent.Observed))
                        continue;//used to be break but I think that if we got here then there is no point in continuing...
                    //is false doesn't properly work here
                    //Debug.Assert(fCurrent.IsFalse(pssCurrent.Observed), "Rgression of an observation returned false");
                    //pssCurrent.GeneratingAction.ClearConditionsChoices();
                    //pssCurrent.GeneratingAction.RemoveImpossibleOptions(pssCurrent.Observed); Need to this after the regression (below)
                    //DateTime dt = DateTime.Now;
                    Formula fRegressed = pssCurrent.RegressObservation(fCurrent);
                    //ts1 += DateTime.Now - dt;
                    if (fRegressed is CompoundFormula)
                    {
                        CompoundFormula cf = (CompoundFormula)fRegressed;
                        if (cf.Operator != "and")
                        {
                            lRegressedFormulas.Add(fRegressed);
                        }
                        else
                        {
                            foreach (Formula f in cf.Operands)
                                lRegressedFormulas.Add(f);
                        }

                    }
                    else
                        lRegressedFormulas.Add(fRegressed);

                    //dt = DateTime.Now;
                    //must be after the regression so as not to make everything already known
                    if (!Problem.Domain.IsSimple || !SDRPlanner.OptimizeMemoryConsumption)
                        hsNew.UnionWith(pssCurrent.AddObserved(fCurrent));
                    //ts2 += DateTime.Now - dt;
                    //pssCurrent.AddObserved(fToRegress); //Not sure that this is valid!

                    if (!fRegressed.Equals(fCurrent))
                        //if (bTrueRegression || !fRegressed.Equals(fToRegress))
                        bTrueRegression = true;
                }
                if (hsNew.Count > 0 && pssSuccessor != null)
                {
                    hsNew = pssSuccessor.PropogateObservedPredicates(hsNew);
                    /*
                    for (int i = 0; i < sTrace.Count; i++)
                    {
                        PartiallySpecifiedState pssUpdate = sTrace.ElementAt(i);
                        hsNew = pssUpdate.PropogateObservedPredicates(hsNew);
                        if (hsNew.Count == 0)
                            break;
                    }
                     * */
                }
                pssSuccessor = pssCurrent;
                pssCurrent = pssCurrent.Predecessor;
                cSteps++;
                lCurrentFormulas = lRegressedFormulas;
            }

            Formula fFinal = null;
            if (lCurrentFormulas.Count == 0)
                return hsModifiedClauses;
            if (lCurrentFormulas.Count == 1)
            {
                fFinal = lCurrentFormulas[0].Reduce(Observed);
                fFinal = fFinal.ToCNF();
            }
            else
            {
                CompoundFormula cf = new CompoundFormula("and");
                foreach (Formula f in lCurrentFormulas)
                {
                    Formula fReduced = f.Reduce(Observed).Simplify();
                    Formula fCNF = null;
                    if (fReduced is CompoundFormula)
                        fCNF = ((CompoundFormula)fReduced).ToCNF();
                    else
                        fCNF = fReduced;
                    cf.AddOperand(fCNF);
                }
                fFinal = cf;

            }
            //Debug.WriteLine("Total time in regressobs " + ts1.TotalSeconds + " propogate " + ts2.TotalSeconds +
            //     " all " + (DateTime.Now - dtStart).TotalSeconds + " size " + fFinal.Size);

            if (fFinal.IsTrue(null))
                return hsModifiedClauses;
            DateTime dtAfterRegression = DateTime.Now;

            DateTime dtAfterReasoning = DateTime.Now;
            //Seems likely but I am unsure: if there was no real regression, then learned things can be applied to all states as is

            HashSet<Predicate> lLearned = null;
            if (BeliefState.UseEfficientFormulas)
                lLearned = AddReasoningFormulaEfficient(fFinal);
            else
                lLearned = AddReasoningFormula(fFinal, hsModifiedClauses);

            HashSet<Predicate> lOriginalLearned = new HashSet<Predicate>(lLearned);

            if (lLearned.Count > 0)
            {
                //HashSet<Predicate> lLearned = pssCurrent.ApplyReasoning(); not needed since we got the learned predicates from the belief update
                if (!Problem.Domain.IsSimple || !SDRPlanner.ComputeCompletePlanTree)
                    pssCurrent.AddObserved(lLearned);
                dtAfterReasoning = DateTime.Now;
                if (bTrueRegression)
                {
                    //while (bUpdate && sTrace.Count > 0)
                    while (sTrace.Count > 0 && lLearned.Count > 0)
                    {
                        pssCurrent = sTrace.Pop();
                        //bUpdate = pssCurrent.PropogateObservedPredicates();
                        lLearned = pssCurrent.PropogateObservedPredicates(lLearned);
                    }
                    if (SDRPlanner.OptimizeMemoryConsumption && lLearned.Count > 0)
                    {
                        pssLast.AddObserved(lLearned);
                    }
                }
                else
                {
                    if (!SDRPlanner.OptimizeMemoryConsumption)
                    {
                        while (sTrace.Count > 0)
                        {
                            pssCurrent = sTrace.Pop();
                            pssCurrent.AddObserved(lLearned);
                        }
                    }
                    else
                        pssLast.AddObserved(lLearned);
                }

            }
            /*
            Console.WriteLine("Time for belief update: " +
                (DateTime.Now - dtBefore).TotalSeconds +
                " regression " + (dtAfterRegression - dtBefore).TotalSeconds +
                " reasoning " + (dtAfterReasoning - dtAfterRegression).TotalSeconds +
                " update " + (DateTime.Now - dtAfterReasoning).TotalSeconds);
            */

            return hsModifiedClauses;
        }