@@ -260,6 +260,25 @@ static void update_affected_variables(
260260 }
261261}
262262
263+ // For backward deviations, preconditions are always affected and conditional
264+ // effects are always unaffected, since values are split in the target state
265+ // instead of the source state.
266+ static void update_affected_variables_backward (
267+ const OperatorProxy &op,
268+ int num_variables,
269+ vector<bool > &affected_vars,
270+ const Abstraction &abstraction) {
271+ affected_vars.assign (num_variables, false );
272+ const vector<FactPair> &uncond_effects = abstraction.get_unconditional_effects (op.get_id ());
273+ for (const FactPair &eff : uncond_effects) {
274+ affected_vars[eff.var ] = true ;
275+ }
276+ const vector<FactPair> &pre = abstraction.get_preconditions (op.get_id ());
277+ for (const FactPair &precondition : pre ) {
278+ affected_vars[precondition.var ] = true ;
279+ }
280+ }
281+
263282struct FactPairHash {
264283 size_t operator ()(FactPair fact) const {
265284 utils::HashState hash_state;
@@ -528,6 +547,7 @@ static void get_deviation_splits(
528547static void get_backward_deviation_splits (
529548 const AbstractState &abs_state,
530549 const AbstractState &flaw_search_state,
550+ const vector<CondEffect> &cond_effects,
531551 const vector<bool > &affected_variables,
532552 const AbstractState &source_abs_state,
533553 const vector<int > &domain_sizes,
@@ -557,19 +577,94 @@ static void get_backward_deviation_splits(
557577 for (size_t var = 0 ; var < domain_sizes.size (); ++var) {
558578 for (int value = 0 ; value < domain_sizes[var]; ++value) {
559579 // Direct deviations in unaffected variables.
560- if (fact_count[var][value] && !source_abs_state.contains (var, value)) {
561- // Note: we could precompute the "wanted" vector, but not the split.
562- vector<int > wanted;
563- for (int value = 0 ; value < domain_sizes[var]; ++value) {
564- if (abs_state.contains (var, value) &&
565- source_abs_state.contains (var, value)) {
566- wanted.push_back (value);
580+ if (fact_count[var][value] && !source_abs_state.contains (var, value) &&
581+ !flaw_search_state.intersects (source_abs_state, var)) {
582+ // If there is some conditional effect in var, the wanted values
583+ // are all possibly triggered effects.
584+ // If it is always triggered in the source abstract state because
585+ // all conditions are always satisfied, then the triggered
586+ // effects are the only wanted values, otherwise the values of
587+ // the source abstract state are also wanted.
588+ // If there is not satisfied conditional effects, then only
589+ // the values of the source abstract state are wanted.
590+ bool always_triggered = false ;
591+ unordered_set<int > wanted;
592+ for (const CondEffect &eff : cond_effects) {
593+ if (eff.effect .var == static_cast <int >(var) && eff.effect .value != value &&
594+ abs_state.contains (eff.effect .var , eff.effect .value )) {
595+ bool satisfied = true ;
596+ bool effect_always_triggered = true ;
597+ for (const FactPair &cond : eff.conds ) {
598+ if (source_abs_state.contains (cond.var , cond.value )) {
599+ if (effect_always_triggered && source_abs_state.count (cond.var ) > 1 ) {
600+ effect_always_triggered = false ;
601+ }
602+ } else {
603+ satisfied = false ;
604+ break ;
605+ }
606+ }
607+ if (satisfied) {
608+ wanted.insert (eff.effect .value );
609+ if (effect_always_triggered) {
610+ always_triggered = true ;
611+ break ;
612+ }
613+ }
614+ }
615+ }
616+ if (!always_triggered) {
617+ for (int value = 0 ; value < domain_sizes[var]; ++value) {
618+ if (abs_state.contains (var, value) &&
619+ source_abs_state.contains (var, value)) {
620+ wanted.insert (value);
621+ }
622+ }
623+ }
624+ if (!wanted.empty ()) {
625+ add_backward_split (splits, Split (
626+ abs_state.get_id (), var, value, vector<int >(wanted.begin (), wanted.end ()),
627+ 1 ));
628+ }
629+ } else if (fact_count[var][value]) {
630+ // Deviation produced because the condition must be satisfied
631+ // in the source abstract state to trigger the effect and so
632+ // change the value of a variable modified by a conditional
633+ // effect. For each conditional effect:
634+ // 1. Check that the effect value is in the target in the
635+ // variable of such effect and it is not in the source
636+ // abstract state.
637+ // 2. Check that all conditions may be satisfied in the source
638+ // state.
639+ // 3. The wanted value is the value of the condition.
640+ for (const CondEffect &eff : cond_effects) {
641+ if (flaw_search_state.contains (eff.effect .var , eff.effect .value ) &&
642+ !source_abs_state.contains (eff.effect .var , eff.effect .value ) &&
643+ !flaw_search_state.intersects (source_abs_state, eff.effect .var )) {
644+ int cond_value = -1 ;
645+ bool conds_satisfied = true ;
646+ for (const FactPair &cond : eff.conds ) {
647+ if (!source_abs_state.contains (cond.var , cond.value )) {
648+ conds_satisfied = false ;
649+ break ;
650+ }
651+ if (cond.var == static_cast <int >(var)) {
652+ if (flaw_search_state.contains (cond.var , cond.value )) {
653+ // The condition is satisfied in the flaw-search state,
654+ // and so this condition is not the source of deviation.
655+ break ;
656+ } else {
657+ cond_value = cond.value ;
658+ }
659+ }
660+ }
661+ if (conds_satisfied && cond_value >= 0 ) {
662+ add_backward_split (splits, Split (
663+ abs_state.get_id (), var, value, {cond_value},
664+ 1 ));
665+ }
567666 }
568667 }
569- assert (!wanted.empty ());
570- add_backward_split (splits, Split (
571- abs_state.get_id (), var, value, move (wanted),
572- 1 ));
573668 }
574669 }
575670 }
@@ -880,10 +975,11 @@ unique_ptr<Split> FlawSearch::create_backward_split(AbstractState &&state, int a
880975 << " , source: " << source << endl;
881976 }
882977 const AbstractState &source_state = abstraction.get_state (source);
883- update_affected_variables (op, n_vars, source_state, affected_vars, conditionally_affected_vars , abstraction);
978+ update_affected_variables_backward (op, n_vars, affected_vars, abstraction);
884979 get_backward_deviation_splits (
885980 abstract_state,
886981 state,
982+ abstraction.get_conditional_effects (op.get_id ()),
887983 affected_vars,
888984 source_state, domain_sizes,
889985 backward_deviation_fact_count, splits);
0 commit comments