axiom_evaluator.cc 5.61 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#include "axiom_evaluator.h"
#include <queue>
#include <set>
#include "../../Meddly/operations_extension/userOperations.h"
#include "../../abstract_task.h"
#include "../sym_variables.h"

namespace symple {

// Some helper functions

bool SymAxiomEvaluator::is_primary(int var) const {
  return task->get_variable_axiom_layer(var) == -1;
}

int SymAxiomEvaluator::get_axiom_head(int axiom_id) const {
  return task->get_operator_effect(axiom_id, 0, true).var;
}

bool SymAxiomEvaluator::is_in_body(int var, int axiom_id) const {
  for (int cond = 0;
       cond < task->get_num_operator_effect_conditions(axiom_id, 0, true);
       cond++) {
    int pre_var =
        task->get_operator_effect_condition(axiom_id, 0, cond, true).var;
    if (pre_var == var) {
      return true;
    }
  }
  return false;
}

// Axiom sets head variable to default => not necessary!
bool SymAxiomEvaluator::is_trivial(int axiom_id) const {
  int head = get_axiom_head(axiom_id);
  return task->get_variable_default_axiom_value(head) ==
         task->get_operator_effect(axiom_id, 0, true).value;
}

MEDDLY::dd_edge SymAxiomEvaluator::get_body_evmdd(int axiom_id) const {
  MEDDLY::dd_edge res = sym_vars->get_constant_edge(1);
  for (int cond = 0;
       cond < task->get_num_operator_effect_conditions(axiom_id, 0, true);
       cond++) {
    int pre_var =
        task->get_operator_effect_condition(axiom_id, 0, cond, true).var;
    int pre_value =
        task->get_operator_effect_condition(axiom_id, 0, cond, true).value;
    if (is_primary(pre_var)) {
      MEDDLY::apply(USER_OPS::UNIONMIN, res,
                    sym_vars->get_predicate_edge(pre_var, pre_value), res);
    } else {
      MEDDLY::dd_edge cur = primary_representation.at(pre_var);
      if (task->get_variable_default_axiom_value(pre_var) == pre_value) {
        MEDDLY::apply(USER_OPS::MINUS, sym_vars->get_constant_edge(1), cur,
                      cur);
      }
      MEDDLY::apply(USER_OPS::UNIONMIN, res, cur, res);
    }
  }
  return res;
}

void SymAxiomEvaluator::create_axiom_body_layer() {
  std::set<int> effs;
  for (int ax_id = 0; ax_id < task->get_num_axioms(); ax_id++) {
    int body_level = -1;
    int eff_var = task->get_operator_effect(ax_id, 0, true).var;
    effs.insert(eff_var);

    for (int cond = 0;
         cond < task->get_num_operator_effect_conditions(ax_id, 0, true);
         cond++) {
      int pre_var =
          task->get_operator_effect_condition(ax_id, 0, cond, true).var;
      body_level =
          std::max(body_level, task->get_variable_axiom_layer(pre_var));
    }
    axiom_body_layer.push_back(body_level);
  }
}

void SymAxiomEvaluator::create_primary_representation(int layer) {
  std::cout << "LAYER " << layer << "..." << std::flush;
  std::vector<int> rules_in_layer;
  // add all "unproblematic" axioms to var bdd
  for (int ax_id = 0; ax_id < task->get_num_axioms(); ax_id++) {
    if (is_trivial(ax_id)) {
      continue;
    }
    if (task->get_variable_axiom_layer(get_axiom_head(ax_id)) == layer &&
        axiom_body_layer.at(ax_id) < layer) {
      MEDDLY::dd_edge body = get_body_evmdd(ax_id);
      primary_representation[get_axiom_head(ax_id)] += body;
    }
  }
  // add vars of this layer to queue
  std::queue<int> open_vars;
  for (auto &pr_evmdd : primary_representation) {
    int var = pr_evmdd.first;
    if (task->get_variable_axiom_layer(var) == layer) {
      // std::cout << g_variable_name[var] << std::endl;
      open_vars.push(var);
    }
  }

  // Recursively evaluate var evmdd
  while (!open_vars.empty()) {
    int var = open_vars.front();
    open_vars.pop();
    for (int ax_id = 0; ax_id < task->get_num_axioms(); ax_id++) {
      if (is_trivial(ax_id) ||
          task->get_variable_axiom_layer(get_axiom_head(ax_id)) != layer) {
        continue;
      }
      if (is_in_body(var, ax_id)) {
        int head = get_axiom_head(ax_id);

        /*if (axioms_layers[head] != layer) {
          g_axioms[i].dump();
        }*/
        assert(task->get_variable_axiom_layer(head) == layer);

        MEDDLY::dd_edge res = primary_representation[head];
        MEDDLY::dd_edge body = get_body_evmdd(ax_id);
        MEDDLY::apply(USER_OPS::UNIONMIN, body, primary_representation[var],
                      body);
        MEDDLY::apply(USER_OPS::INTERSECTIONMAX, res, body, res);
        if (res != primary_representation[head]) {
          open_vars.push(head);
        }
        primary_representation[head] = res;
        // std::cout << g_variable_name[head] << " updated" << std::endl;
      }
    }
  }
  std::cout << "done!" << std::endl;
}

void SymAxiomEvaluator::create_primary_representation() {
  create_axiom_body_layer();
  int num_axiom_layers = -1;
  for (int var = 0; var < task->get_num_variables(); var++) {
    if (!is_primary(var)) {
      primary_representation[var] = sym_vars->get_constant_edge(0);
      num_axiom_layers =
          std::max(num_axiom_layers, task->get_variable_axiom_layer(var));
    }
  }

  // Call for each layer the recursive procedure
  for (int i = 0; i < num_axiom_layers; i++) {
    create_primary_representation(i);
  }
}

SymAxiomEvaluator::SymAxiomEvaluator(std::shared_ptr<SymVariables> sym_vars,
                                     std::shared_ptr<AbstractTask> task)
    : sym_vars(sym_vars), task(task) {}

MEDDLY::dd_edge SymAxiomEvaluator::get_primary_representation(int var,
                                                              int val) const {
  MEDDLY::dd_edge res = primary_representation.at(var);

  // Negation if derived variable has default value
  if (task->get_variable_default_axiom_value(var) == val) {
    MEDDLY::apply(USER_OPS::MINUS, sym_vars->get_constant_edge(1), res, res);
  }
  return res;
}
}  // namespace symple