Пример #1
0
void join(Relation &lhs, Relation &rhs, vector<size_t> &vars, Relation &result) {
  DEBUG("Joining", "");
  DEBUG("  LHS size = ", lhs.size());
  DEBUG("  RHS size = ", rhs.size());
  Relation temp;
  Order order(vars);
  lhs.sort(order);
  rhs.sort(order);
  Relation::iterator lit = lhs.begin();
  Relation::iterator rit = rhs.begin();
  while (lit != lhs.end() && rit != rhs.end()) {
    Tuple joined;
    if (join(*lit, *rit, joined)) {
      Relation::iterator it;
      do {
        temp.push_back(joined);
        it = rit;
        for (++it; it != rhs.end() && join(*lit, *it, joined); ++it) {
          temp.push_back(joined);
        }
        ++lit;
      } while (lit != lhs.end() && join(*lit, *rit, joined));
      rit = it;
    } else if (order(*rit, *lit)) {
      ++rit;
    } else {
      ++lit;
    }
  }
  result.swap(temp);
  DEBUG("  Result size = ", result.size());
}
Пример #2
0
void print_relations(const Relation& relations)
{
    for (Relation::const_iterator rela_iter = relations.begin();
            rela_iter != relations.end(); rela_iter++) {
        copy(rela_iter->begin(), rela_iter->end(), ostream_iterator<int>(cout, " "));
        cout << endl;
    }
}
//! recreate html page if something changes
void MetadataItemPropertiesPanel::update()
{
    Database* db = dynamic_cast<Database*>(objectM);
    if (db && !db->isConnected())
    {
        objectM = 0;
        if (MetadataItemPropertiesFrame* f = getParentFrame())
            f->Close();

        // MB: This code used to use:
        //f->removePanel(this);
        // which would allow us to mix property pages from different
        // databases in the same Frame, but there are some mysterious
        // reasons why it causes heap corruption with MSVC

        return;
    }

    // if table or view columns change, we need to reattach
    if (objectM->getType() == ntTable || objectM->getType() == ntView)  // also observe columns
    {
        Relation* r = dynamic_cast<Relation*>(objectM);
        if (!r)
            return;

        SubjectLocker locker(r);
        r->ensureChildrenLoaded();
        for (ColumnPtrs::iterator it = r->begin(); it != r->end(); ++it)
            (*it)->attachObserver(this, false);
    }

    // if description of procedure params change, we need to reattach
    if (objectM->getType() == ntProcedure)
    {
        Procedure* p = dynamic_cast<Procedure*>(objectM);
        if (!p)
            return;

        SubjectLocker locker(p);
        p->ensureChildrenLoaded();
        for (ParameterPtrs::iterator it = p->begin(); it != p->end(); ++it)
            (*it)->attachObserver(this, false);
    }

    // with this set to false updates to the same page do not show the
    // "Please wait while the data is being loaded..." temporary page
    // this results in less flicker, but may also seem less responsive
    if (!htmlReloadRequestedM)
        requestLoadPage(false);
}
Пример #4
0
void act(Atom &atom, Relation &results) {
  DEBUG("Act: atom = ", atom);
  Index &index = atoms[atom.predicate];
  Relation::iterator result = results.begin();
  size_t max = atom.arguments.end - atom.arguments.begin;
  for (; result != results.end(); ++result) {
    Tuple tuple(max);
    size_t i;
    for (i = 0; i < max; ++i) {
      if (atom.arguments.begin[i].type == CONSTANT) {
        tuple[i] = atom.arguments.begin[i].get.constant;
        DEBUG("part ", tuple[i]);
      } else if (atom.arguments.begin[i].type == VARIABLE) {
        tuple[i] = result->at(atom.arguments.begin[i].get.variable);
        DEBUG("part ", tuple[i]);
      } else {
        cerr << "[ERROR] Lists and/or function in target atom are not currently supported." << endl;
        return;
      }
    }
    DEBUG("inserting (ignore this ->", max);
    index.insert(tuple);
  }
}
Пример #5
0
bool special(Condition &condition, Relation &intermediate, Relation &filtered) {
  if (condition.type != ATOMIC) {
    return false;
  }
  switch (condition.get.atom.type) {
    case ATOM:
    case MEMBERSHIP:
    case SUBCLASS:
    case FRAME:
      return false;
    case EQUALITY: {
      Term *lhs = &(condition.get.atom.get.sides[0]);
      Term *rhs = &(condition.get.atom.get.sides[1]);
      if (lhs->type == VARIABLE && rhs->type == CONSTANT) {
        swap(lhs, rhs);
      }
      if (rhs->type == CONSTANT) {
        if (lhs->get.constant != rhs->get.constant) {
          Relation empty;
          filtered.swap(empty);
        } else {
          filtered = intermediate;
        }
      } else if (lhs->type == CONSTANT) {
        Relation result;
        Relation::iterator it = intermediate.begin();
        for (; it != intermediate.end(); ++it) {
          if (it->size() <= rhs->get.variable) {
            it->resize(rhs->get.variable + 1);
          }
          if (it->at(rhs->get.variable) == 0) {
            result.push_back(*it);
            Tuple &t = result.back();
            t[rhs->get.variable] = lhs->get.constant;
          } else if (it->at(rhs->get.variable) == lhs->get.constant) {
            result.push_back(*it);
          }
        }
        filtered.swap(result);
      } else {
        varint_t maxvar = max(lhs->get.variable, rhs->get.variable);
        Relation result;
        Relation::iterator it = intermediate.begin();
        for (; it != intermediate.end(); ++it) {
          if (it->size() <= maxvar) {
            it->resize(maxvar + 1);
          }
          constint_t c1 = it->at(lhs->get.variable);
          constint_t c2 = it->at(rhs->get.variable);
          if (c1 == 0 && c2 == 0) {
            cerr << "[ERROR] Please make sure equality statements occur to the right of atomic formulas that bind a variable." << endl;
            return true;
          }
          if (c1 == 0) {
            result.push_back(*it);
            Tuple &t = result.back();
            t[lhs->get.variable] = c2;
          } else if (c2 == 0) {
            result.push_back(*it);
            Tuple &t = result.back();
            t[rhs->get.variable] = c1;
          } else if (c1 == c2) {
            result.push_back(*it);
          }
        }
        filtered.swap(result);
      }
      return true;
    }
    case EXTERNAL: {
      break; // just handle outside the messy switch statement
    }
    default: {
      cerr << "[ERROR] Unhandled case " << (int)condition.get.atom.type << " at line " << __LINE__ << endl;
      return false;
    }
  }

  ///// HANDLE BUILTIN (EXTERNAL) /////
  Builtin &builtin = condition.get.atom.get.builtin;
  switch (builtin.predicate) {
    case BUILTIN_PRED_LIST_CONTAINS: {
      if (builtin.arguments.end - builtin.arguments.begin != 2) {
        cerr << "[ERROR] Invalid use of list contains builtin, which should have exactly two arguments, but instead found " << builtin << endl;
        return false;
      }
      Term *arg1 = builtin.arguments.begin;
      Term *arg2 = arg1 + 1;
      if (arg1->type != LIST) {
        cerr << "[ERROR] First argument of list contains builtin must be a list, but instead found " << *arg1 << endl;
        return false;
      }
      switch (arg2->type) {
        case FUNCTION:
          cerr << "[ERROR] Functions not supported." << endl;
          return false;
        case LIST:
          cerr << "[ERROR] Currently not supporting nested lists." << endl;
          return false;
        case CONSTANT: {
          Term *t = arg1->get.termlist.begin;
          for (; t != arg1->get.termlist.end; ++t) {
            if (t->type == CONSTANT && t->get.constant == arg2->get.constant) {
              filtered = intermediate;
              return true;
            }
          }
          Relation empty;
          filtered.swap(empty);
          return true;
        }
        case VARIABLE:
          break; // just handle outside messy switch statement
        default:
          cerr << "[ERROR] Unhandled case " << (int)builtin.predicate << " at line " << __LINE__ << endl;
          return false;
      }
      Relation results;
      Relation::iterator it = intermediate.begin();
      for (; it != intermediate.end(); ++it) {
        if (it->size() <= arg2->get.variable) {
          it->resize(arg2->get.variable + 1);
        }
        constint_t c = it->at(arg2->get.variable);
        if (c == 0) {
          Term *t = arg1->get.termlist.begin;
          for (; t != arg1->get.termlist.end; ++t) {
            if (t->type == CONSTANT) {
              results.push_back(*it);
              results.back().at(arg2->get.variable) = t->get.constant;
            }
          }
        } else {
          Term *t = arg1->get.termlist.begin;
          for (; t != arg1->get.termlist.end; ++t) {
            if (t->type == CONSTANT && t->get.constant == c) {
              results.push_back(*it);
              break;
            }
          }
        }
      }
      filtered.swap(results);
      return true;
    }
    default: {
      cerr << "[ERROR] Builtin predicate " << (int)builtin.predicate << " is unsupported." << endl;
      return false;
    }
  }
}
Пример #6
0
void act(ActionBlock &action_block, Relation &results, Index &assertions, Index &retractions) {
  if (action_block.action_variables.begin != action_block.action_variables.end) {
    cerr << "[ERROR] Action variables are unsupported." << endl;
    return;
  }
  Action *action = action_block.actions.begin;
  for (; action != action_block.actions.end; ++action) {
    switch (action->type) {
      case ASSERT_FACT:
      case RETRACT_FACT: {
        if (action->get.atom.type == ATOM) {
          if (action->type == RETRACT_FACT) {
            cerr << "[ERROR] Retraction of atoms is currently unsupported." << endl;
            return;
          }
          act(action->get.atom.get.atom, results);
          continue;
        }
        if (action->get.atom.type != FRAME) {
          cerr << "[ERROR] For now, supporting only assertion of frames/triples." << endl;
          return;
        }
        Frame frame = action->get.atom.get.frame;
        Tuple triple(3);
        if (frame.object.type == LIST || frame.object.type == FUNCTION) {
          cerr << "[ERROR] Not supporting lists or functions in action target." << endl;
          return;
        }
        if (frame.object.type == CONSTANT) {
          triple[0] = frame.object.get.constant;
        }
        pair<Term, Term> *slot = frame.slots.begin;
        for (; slot != frame.slots.end; ++slot) {
          if (slot->first.type == LIST || slot->first.type == FUNCTION ||
              slot->second.type == LIST || slot->second.type == FUNCTION) {
            cerr << "[ERROR] Not supporting lists or function in action target." << endl;
            return;
          }
          if (slot->first.type == CONSTANT) {
            triple[1] = slot->first.get.constant;
          }
          if (slot->second.type == CONSTANT) {
            triple[2] = slot->second.get.constant;
          }
          if (!results.empty() && frame.object.type == CONSTANT && slot->first.type == CONSTANT && slot->second.type == CONSTANT) {
            if (action->type == ASSERT_FACT) {
              assertions.insert(triple);
            } else {
              retractions.insert(triple);
            }
            continue;
          }
          Relation::iterator tuple = results.begin();
          for (; tuple != results.end(); ++tuple) {
            if (frame.object.type == VARIABLE) {
              triple[0] = tuple->at(frame.object.get.variable);
            }
            if (slot->first.type == VARIABLE) {
              triple[1] = tuple->at(slot->first.get.variable);
            }
            if (slot->second.type == VARIABLE) {
              triple[2] = tuple->at(slot->second.get.variable);
            }
            if (action->type == ASSERT_FACT) {
              assertions.insert(triple);
            } else {
              retractions.insert(triple);
            }
          }
        }
        return;
      }
      default: {
        cerr << "[ERROR] Currently supporting on ASSERT_FACT and RETRACT_FACT actions." << endl;
        return;
      }
    }
  }
}
Пример #7
0
void query(Condition &condition, set<varint_t> &allvars, Relation &results) {
  deque<void*> negated;
  Relation intermediate;
  switch (condition.type) {
    case ATOMIC: {
      query(condition.get.atom, allvars, results);
      return;
    }
    case CONJUNCTION: {
      Condition *subformula = condition.get.subformulas.begin;
      for (; subformula != condition.get.subformulas.end; ++subformula) {
        if (subformula->type == NEGATION) {
          negated.push_back((void*)subformula->get.subformulas.begin);
          continue;
        }
        Relation subresult;
        set<varint_t> newvars;
        // TODO vvv this won't work right if a non-special query
        // has not been performed first
        if (special(*subformula, intermediate, subresult)) {
          if (subformula == condition.get.subformulas.begin) {
            cerr << "[ERROR] Must have non-special query at beginning of conjunction." << endl;
          }
          intermediate.swap(subresult);
          continue;
        }
        query(*subformula, newvars, subresult);
        if (subformula == condition.get.subformulas.begin) {
          intermediate.swap(subresult);
        } else {
          vector<size_t> joinvars(allvars.size() + newvars.size());
          vector<size_t>::iterator jit = set_intersection(allvars.begin(),
              allvars.end(), newvars.begin(), newvars.end(), joinvars.begin());
          joinvars.resize(jit - joinvars.begin());
          join(intermediate, subresult, joinvars, intermediate);
        }
        allvars.insert(newvars.begin(), newvars.end());
      }
      break;
    }
    case DISJUNCTION: {
      cerr << "[ERROR] Disjunction is not supported." << endl;
      return;
    }
    case EXISTENTIAL: {
      // assuming all quantified variables are uniquely named in the scope of the rule
      Condition *subformula = condition.get.subformulas.begin;
      for (; subformula != condition.get.subformulas.end; ++subformula) {
        if (subformula->type == NEGATION) {
          negated.push_back((void*)subformula->get.subformulas.begin);
        }
        Relation subresult;
        query(*subformula, allvars, subresult);
        intermediate.splice(intermediate.end(), subresult);
      }
      break;
    }
    case NEGATION: {
      cerr << "[ERROR] This should never happen.  query should not be called directly on negated formulas." << endl;
      return;
    }
    default: {
      cerr << "[ERROR] Unhandled case " << (int)condition.type << " on line " << __LINE__ << endl;
      return;
    }
  }
// TODO deal with negation later, if at all
#if 1
  deque<void*>::iterator it = negated.begin();
  for (; !intermediate.empty() && it != negated.end(); ++it) {
    Relation negresult;
    Condition *cond = (Condition*) *it;
    if (special(*cond, intermediate, negresult)) {
      intermediate.sort();
      negresult.sort();
      Relation leftover(intermediate.size());
      Relation::iterator iit = set_difference(intermediate.begin(),
          intermediate.end(), negresult.begin(), negresult.end(),
          leftover.begin());
      Relation newinter;
      newinter.splice(newinter.end(), leftover,
                      leftover.begin(), iit);
      intermediate.swap(newinter);
      continue;
    }
    query(*((Condition*)(*it)), allvars, negresult);
    minusrel(intermediate, negresult, intermediate);
  }
#endif
  results.swap(intermediate);
}