hash_set<size_t> seen_steps;
hashing::hash_set<size_t> seen_steps;
formula_value(const Formula& formula, size_t step_id, const Plan& plan,	      const Domain& domain, const PlanningGraph& pg,	      bool reuse = false) {  const Bindings* bindings = plan.bindings();  if (reuse) {    const Literal* literal = dynamic_cast<const Literal*>(&formula);    if (literal != NULL) {      StepTime gt = start_time(*literal);      if (!domain.static_predicate(literal->predicate())) {	hash_set<size_t> seen_steps;	for (const StepChain* sc = plan.steps(); sc != NULL; sc = sc->tail) {	  const Step& step = sc->head;	  if (step.id() != 0 && seen_steps.find(step.id()) == seen_steps.end()	      && plan.orderings().possibly_before(step.id(), STEP_START,						  step_id, gt)) {	    seen_steps.insert(step.id());	    const EffectList& effs = step.action().effects();	    for (EffectListIter ei = effs.begin(); ei != effs.end(); ei++) {	      const Effect& e = **ei;	      StepTime et = end_time(e);	      if (plan.orderings().possibly_before(step.id(), et,						   step_id, gt)) {		if (typeid(*literal) == typeid(Atom)) {		  const AtomList& adds = e.add_list();		  for (AtomListIter fi = adds.begin();		       fi != adds.end(); fi++) {		    if ((bindings != NULL && bindings->unify(*literal, step_id,							     **fi, step.id()))			|| (bindings == NULL			    && Bindings::unifiable(*literal, step_id,						   **fi, step.id()))) {		      return HeuristicValue::ZERO_COST_UNIT_WORK;		    }		  }		} else {		  const NegationList& dels = e.del_list();		  for (NegationListIter fi = dels.begin();		       fi != dels.end(); fi++) {		    if ((bindings != NULL && bindings->unify(*literal, step_id,							     **fi, step.id()))			|| (bindings == NULL			    && Bindings::unifiable(*literal, step_id,						   **fi, step.id()))) {		      return HeuristicValue::ZERO_COST_UNIT_WORK;		    }		  }		}	      }	    }	  }	}      }    } else {      const Disjunction* disj = dynamic_cast<const Disjunction*>(&formula);      if (disj != NULL) {	HeuristicValue h = HeuristicValue::INFINITE;	for (FormulaListIter fi = disj->disjuncts().begin();	     fi != disj->disjuncts().end(); fi++) {	  h = min(h, formula_value(**fi, step_id, plan, domain, pg, true));	}	return h;      } else {	const Conjunction* conj = dynamic_cast<const Conjunction*>(&formula);	if (conj != NULL) {	  HeuristicValue h = HeuristicValue::ZERO;	  for (FormulaListIter fi = conj->conjuncts().begin();	       fi != conj->conjuncts().end(); fi++) {	    h += formula_value(**fi, step_id, plan, domain, pg, true);	  }	  return h;	} else {	  const ExistsFormula* exists =	    dynamic_cast<const ExistsFormula*>(&formula);	  if (exists != NULL) {	    return formula_value(exists->body(), step_id, plan, domain, pg,				 true);	  }	}      }    }  }  HeuristicValue h;  formula.heuristic_value(h, pg, step_id, bindings);  return h;}