5036 lines
165 KiB
C++
5036 lines
165 KiB
C++
/*
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
|
Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
----
|
|
|
|
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
|
|
//[TOC] [\tableofcontents]
|
|
|
|
Started March 2012, Fabio Vald\'{e}s
|
|
|
|
[TOC]
|
|
|
|
\section{Overview}
|
|
This is the implementation of the Symbolic Trajectory Algebra.
|
|
|
|
\section{Defines and Includes}
|
|
|
|
*/
|
|
#include "Algebra.h"
|
|
#include "NestedList.h"
|
|
#include "NList.h"
|
|
#include "QueryProcessor.h"
|
|
#include "ConstructorTemplates.h"
|
|
#include "StandardTypes.h"
|
|
#include "Algebras/Temporal/TemporalAlgebra.h"
|
|
#include "Algebras/TemporalExt/TemporalExtAlgebra.h"
|
|
#include "DateTime.h"
|
|
#include "CharTransform.h"
|
|
#include "Stream.h"
|
|
#include "SecParser.h"
|
|
#include "NestedList.h"
|
|
#include "ListUtils.h"
|
|
#include "Algebras/RTree/RTreeAlgebra.h"
|
|
#include "Algebras/FText/IntNfa.h"
|
|
#include "Algebras/TemporalUnit/TemporalUnitAlgebra.h"
|
|
#include "GenericTC.h"
|
|
#include "Algebras/OrderedRelation/OrderedRelationAlgebra.h"
|
|
#include "Tools.h"
|
|
#include <string>
|
|
#include <set>
|
|
#include <stack>
|
|
#include <vector>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#include "BasicTypes.h"
|
|
|
|
#define YYDEBUG 1
|
|
#define YYERROR_VERBOSE 1
|
|
|
|
|
|
int parsePatternRegEx(const char* argument, IntNfa** T);
|
|
|
|
union Word;
|
|
|
|
namespace stj {
|
|
|
|
class Pattern;
|
|
class PatElem;
|
|
class Assign;
|
|
class ClassifyLI;
|
|
class IndexLI;
|
|
struct IndexMatchInfo;
|
|
struct IndexMatchInfo2;
|
|
|
|
Pattern* parseString(const char* input, bool classify, Tuple *t,ListExpr ttype);
|
|
void patternFlushBuffer();
|
|
|
|
enum ExtBool {ST_FALSE, ST_TRUE, ST_UNDEF};
|
|
enum Wildcard {NO, STAR, PLUS};
|
|
enum IndexType {TRIE, BTREE, RTREE1, RTREE2, NONE};
|
|
|
|
class ExprList {
|
|
public:
|
|
std::vector<std::string> exprs;
|
|
|
|
ExprList() {}
|
|
~ExprList() {}
|
|
|
|
std::string toString();
|
|
};
|
|
|
|
class Condition {
|
|
private:
|
|
std::string text;
|
|
std::vector<std::pair<std::string, int> > varKeys;
|
|
std::pair<QueryProcessor*, OpTree> opTree;
|
|
std::vector<Attribute*> pointers; // for each expression like X.card
|
|
std::set<std::string> instantVars; // used for operator indextmatches2
|
|
bool treeOk;
|
|
|
|
public:
|
|
Condition() : treeOk(false) {}
|
|
~Condition() {}
|
|
|
|
std::string toString() const;
|
|
int convertVarKey(const char *varKey, Tuple *t = 0, ListExpr tupleType = 0);
|
|
void clear();
|
|
static std::string getType(const int t, const std::string& var,
|
|
Tuple *tuple = 0, ListExpr ttype = 0);
|
|
template<class Moving, class Intime, class Constant>
|
|
static void getConstValue(Attribute *src, const Instant& inst,
|
|
Attribute*& result);
|
|
static void getConstValue(Attribute *src, const std::string& type,
|
|
const Instant& inst, Attribute*& result);
|
|
bool initOpTree(Tuple *tuple = 0, ListExpr ttype = 0);
|
|
void deleteOpTree();
|
|
|
|
std::string getText() const {return text;}
|
|
void setText(std::string newText) {text = newText;}
|
|
int getVarKeysSize() const {return varKeys.size();}
|
|
std::string getVar(unsigned int pos) {
|
|
std::string s;
|
|
return (pos < varKeys.size() ?
|
|
varKeys[pos].first : s);}
|
|
int getKey(unsigned int pos) const {return (pos < varKeys.size() ?
|
|
varKeys[pos].second : -1);}
|
|
// int getPId(unsigned int pos) {return (pos < pIds.size() ?
|
|
// pIds[pos] : -1);}
|
|
void getAllVars(std::set<std::string>& result) const {
|
|
for (unsigned int i = 0; i < varKeys.size(); i++) {
|
|
result.insert(varKeys[i].first);}}
|
|
void collectInstantVars(std::map<std::string, int>& varToElem) {
|
|
for (std::map<std::string, int>::iterator it = varToElem.begin();
|
|
it != varToElem.end(); it++) {
|
|
if (it->second >= 0) {
|
|
instantVars.insert(it->first);
|
|
}
|
|
}
|
|
}
|
|
void clearVectors() {varKeys.clear();}
|
|
// string getVar(unsigned int pos) {return (pos < vars.size() ?
|
|
// vars[pos] : "");}
|
|
void setOpTree(std::pair<QueryProcessor*, OpTree> qp_op) {opTree = qp_op;}
|
|
void setPointers(std::vector<Attribute*> ptrs) {pointers = ptrs;}
|
|
void setValuePtr(unsigned int pos, std::string& value);
|
|
void setValuePtr(unsigned int pos, std::pair<std::string,
|
|
unsigned int>& value);
|
|
void clearTimePtr(unsigned int pos);
|
|
void mergeAddTimePtr(unsigned int pos,
|
|
temporalalgebra::Interval<Instant>& value);
|
|
void setTimePtr(unsigned int pos, const temporalalgebra::Periods& per);
|
|
void setStartEndPtr(unsigned int pos, Instant& value);
|
|
void setCardPtr(unsigned int pos, int value);
|
|
void cleanLabelsPtr(unsigned int pos);
|
|
void appendToLabelsPtr(unsigned int pos, std::string& value);
|
|
void appendToLabelsPtr(unsigned int pos, std::set<std::string>& values);
|
|
void cleanPlacesPtr(unsigned int pos);
|
|
void appendToPlacesPtr(unsigned int pos,
|
|
std::pair<std::string,unsigned int>& value);
|
|
void appendToPlacesPtr(unsigned int pos,
|
|
std::set<std::pair<std::string, unsigned int> >& values);
|
|
void setLeftRightclosedPtr(unsigned int pos, bool value);
|
|
QueryProcessor* getQP() {return opTree.first;}
|
|
OpTree getOpTree() {return opTree.second;}
|
|
int getPointersSize() {return pointers.size();}
|
|
bool isTreeOk() {return treeOk;}
|
|
void setTreeOk(bool value) {treeOk = value;}
|
|
template<class M>
|
|
void restrictPtr(const int pos, M *traj, const int from, const int to,
|
|
Tuple *tuple, ListExpr ttype, const int key);
|
|
template<class M>
|
|
void setPointerToValue(const int pos, M *traj, const int from,
|
|
const int to);
|
|
template<class M>
|
|
void setPointerToEmptyValue(const int pos, M *traj, Tuple *t = 0,
|
|
ListExpr ttype = 0);
|
|
template<class M>
|
|
bool evaluate(const IndexMatchInfo &imi, M *traj,
|
|
std::map<std::string, int> &varToElem,
|
|
Tuple *tuple = 0, ListExpr ttype = 0);
|
|
bool evaluateInstant(const ListExpr tt, Tuple *t, IndexMatchInfo2& imi);
|
|
bool evaluatePeriods(const ListExpr tt, Tuple *t,
|
|
temporalalgebra::Periods *per);
|
|
bool copyPtrFromAttr(const int pos, Attribute *attr);
|
|
void copyAndRestrictPtr(const int pos, Tuple *tuple, const ListExpr ttype,
|
|
const int key, const temporalalgebra::Periods& per);
|
|
void setPtrToTimeValue(const int pos, const temporalalgebra::Periods& per);
|
|
};
|
|
|
|
/*
|
|
\section{Class ~PatElem~}
|
|
|
|
*/
|
|
class PatElem {
|
|
friend class TMatch;
|
|
friend class TMatchIndexLI;
|
|
private:
|
|
std::string var;
|
|
std::set<std::string> ivs;
|
|
std::set<std::string> lbs;
|
|
std::vector<std::pair<Word, SetRel> > values;
|
|
std::vector<std::string> types;
|
|
Wildcard wc;
|
|
SetRel setRel;
|
|
bool ok;
|
|
|
|
public:
|
|
PatElem() : var(""), ivs(), lbs(), values(), types(), wc(NO),
|
|
setRel(STANDARD), ok(true) {}
|
|
PatElem(const char* contents, Tuple *tuple);
|
|
PatElem(const PatElem& elem) : var(elem.var), ivs(elem.ivs), lbs(elem.lbs),
|
|
values(elem.values), types(elem.types), wc(elem.wc),
|
|
setRel(elem.setRel), ok(elem.ok) {}
|
|
~PatElem() {}
|
|
|
|
void stringToSet(const std::string& input, const bool isTime);
|
|
void setVar(const std::string& v) {var = v;}
|
|
PatElem& operator=(const PatElem& elem) {
|
|
var = elem.var;
|
|
ivs = elem.ivs;
|
|
lbs = elem.lbs;
|
|
values = elem.values;
|
|
types = elem.types;
|
|
wc = elem.wc;
|
|
setRel = elem.setRel;
|
|
ok = elem.ok;
|
|
return *this;
|
|
}
|
|
|
|
void getV(std::string& result) const {result = var;}
|
|
void getL(std::set<std::string>& result) const {result = lbs;}
|
|
SetRel getSetRel() const {return setRel;}
|
|
void getI(std::set<std::string>& result) const {result = ivs;}
|
|
Wildcard getW() const {return wc;}
|
|
bool isOk() const {return ok;}
|
|
void clearL() {lbs.clear();}
|
|
void insertL(const std::string& lb) {lbs.insert(lb);}
|
|
void clearI() {ivs.clear();}
|
|
void insertI(std::string& iv) {ivs.insert(iv);}
|
|
void clearW() {wc = NO;}
|
|
bool hasLabel() const {return lbs.size() > 0;}
|
|
bool hasInterval() const {return ivs.size() > 0;}
|
|
bool hasRealInterval() const;
|
|
bool hasIndexableContents() const {return (hasLabel() ||
|
|
hasRealInterval());}
|
|
int getNoValues() const {return values.size();}
|
|
bool hasValuesWithContent() const;
|
|
bool isRelevantForTupleIndex() const;
|
|
bool extractValues(std::string &input, Tuple *tuple);
|
|
void getInterval(temporalalgebra::SecInterval& result) const;
|
|
std::vector<std::pair<Word, SetRel> > getValues() const {return values;}
|
|
void deleteValues(std::vector<std::pair<int, std::string> > &relevantAttrs);
|
|
};
|
|
|
|
/*
|
|
\section{Class ~Assign~}
|
|
|
|
*/
|
|
class Assign {
|
|
private:
|
|
int resultPos;
|
|
bool occurrence; // ~true~ if and only if ~var~ occurs in the pattern
|
|
std::string text[10]; // one for each possible attribute
|
|
std::string var; // the assigned variable
|
|
std::vector<std::pair<std::string, int> > right[11];
|
|
// list of vars and keys for every type
|
|
std::pair<QueryProcessor*, OpTree> opTree[10];
|
|
std::vector<Attribute*> pointers[10]; // for each expression like X.card
|
|
bool treesOk;
|
|
|
|
public:
|
|
Assign() {treesOk = false;}
|
|
~Assign() {}
|
|
|
|
bool convertVarKey(const char* vk, Tuple *tuple = 0, ListExpr tupleType = 0);
|
|
bool prepareRewrite(int key, const std::vector<size_t> &assSeq,
|
|
std::map<std::string, int> &varPosInSeq,
|
|
stj::MLabel const &ml);
|
|
bool hasValue() {return (!text[0].empty() || !text[1].empty() ||
|
|
!text[8].empty() || !text[9].empty());}
|
|
bool hasTime() {return (!text[2].empty() ||
|
|
(!text[3].empty() && !text[4].empty()));}
|
|
bool initOpTrees();
|
|
void clear();
|
|
void deleteOpTrees();
|
|
void setLabelPtr(unsigned int pos, const std::string& value);
|
|
void setPlacePtr(unsigned int pos, const std::pair<std::string,
|
|
unsigned int>& value);
|
|
void setTimePtr(unsigned int pos, const temporalalgebra::SecInterval& value);
|
|
void setStartPtr(unsigned int pos, const Instant& value);
|
|
void setEndPtr(unsigned int pos, const Instant& value);
|
|
void setLeftclosedPtr(unsigned int pos, bool value);
|
|
void setRightclosedPtr(unsigned int pos, bool value);
|
|
void cleanLabelsPtr(unsigned int pos);
|
|
void appendToLabelsPtr(unsigned int pos, const std::string& value);
|
|
void appendToLabelsPtr(unsigned int pos, const std::set<std::string>& value);
|
|
void cleanPlacesPtr(unsigned int pos);
|
|
void appendToPlacesPtr(unsigned int pos,
|
|
const std::pair<std::string,unsigned int>& value);
|
|
void appendToPlacesPtr(unsigned int pos,
|
|
const std::set<std::pair<std::string,unsigned int> >& value);
|
|
|
|
void init(std::string v, int pp) {clear(); var = v;
|
|
occurrence = (pp > -1);}
|
|
int getResultPos() const {return resultPos;}
|
|
void setResultPos(int p) {resultPos = p;}
|
|
bool occurs() const {return occurrence;}
|
|
void setOccurrence(int p) {occurrence = (p > -1);}
|
|
std::string getText(int key) const {return text[key];}
|
|
void setText(int key, std::string newText) {if (!text[key].empty()) {
|
|
right[key].clear();}
|
|
text[key] = newText;}
|
|
int getRightSize(int key) const {return right[key].size();}
|
|
std::string getV() const {return var;}
|
|
int getRightKey(int lkey, int j) const {return right[lkey][j].second;}
|
|
std::pair<std::string, int> getVarKey(int key, int i) const {
|
|
return right[key][i];
|
|
}
|
|
std::pair<std::string, int> getVarKey(int key) const {
|
|
return right[key].back();
|
|
}
|
|
std::string getRightVar(int lkey, int j) const {return right[lkey][j].first;}
|
|
void addRight(int key,
|
|
std::pair<std::string, int> newRight) {
|
|
right[key].push_back(newRight);
|
|
}
|
|
void removeUnordered() {if (!right[10].empty()) {
|
|
right[10].pop_back();
|
|
}}
|
|
QueryProcessor* getQP(unsigned int key) {if (key < 10) {
|
|
return opTree[key].first;}
|
|
else return 0;}
|
|
OpTree getOpTree(unsigned int key) {if (key < 10) {
|
|
return opTree[key].second;}
|
|
else return 0;}
|
|
bool areTreesOk() {return treesOk;}
|
|
void setTreesOk(bool value) {treesOk = value;}
|
|
};
|
|
|
|
/*
|
|
\section{Class ~Pattern~}
|
|
|
|
*/
|
|
class Pattern {
|
|
friend class TMatch;
|
|
public:
|
|
Pattern() {}
|
|
|
|
Pattern(int i) {}
|
|
|
|
~Pattern() {
|
|
deleteEasyCondOpTrees();
|
|
deleteCondOpTrees();
|
|
deleteAssignOpTrees();
|
|
}
|
|
|
|
std::string GetText() const;
|
|
bool isValid(const std::string& type) const;
|
|
bool isCompatible(TupleType *ttype, const int majorAttrNo,
|
|
std::vector<std::pair<int, std::string> >& relevantAttrs,
|
|
int& majorValueNo);
|
|
static Pattern* getPattern(std::string input, bool classify, Tuple *tuple = 0,
|
|
ListExpr ttype = 0);
|
|
template<class M>
|
|
ExtBool matches(M *m);
|
|
ExtBool tmatches(Tuple *tuple, const int attrno, ListExpr ttype);
|
|
int getResultPos(const std::string v);
|
|
void collectAssVars();
|
|
void addVarPos(const std::string var, const int pos, const bool between);
|
|
void addAtomicPos();
|
|
int getPatternPos(const std::string v);
|
|
bool checkAssignTypes();
|
|
static std::pair<std::string, Attribute*> getPointer(const int key,
|
|
const bool isInterval = true, Tuple *tuple = 0);
|
|
bool initAssignOpTrees();
|
|
void deleteAssignOpTrees(bool conds);
|
|
bool parseNFA();
|
|
void simplifyNFA(std::vector<std::map<int, int> >& result);
|
|
void findNFApaths(std::vector<std::map<int, int> >& simpleNFA,
|
|
std::set<std::pair<std::set<int>, int> >& result);
|
|
void getCrucialElems(const std::set<std::pair<std::set<int>,int> >& paths,
|
|
std::set<int>& result);
|
|
bool containsFinalState(std::set<int> &states);
|
|
bool initCondOpTrees(Tuple *tuple = 0, ListExpr ttype = 0,
|
|
const bool mainAttr = true);
|
|
bool initEasyCondOpTrees(const bool mainAttr, Tuple *tuple = 0,
|
|
ListExpr ttype = 0);
|
|
void deleteCondOpTrees();
|
|
void deleteEasyCondOpTrees();
|
|
void deleteAtomValues(std::vector<std::pair<int, std::string> > &attrs);
|
|
bool startsWithAsterisk() const;
|
|
bool startsWithPlus() const;
|
|
bool nfaHasLoop(const int state) const;
|
|
|
|
std::vector<PatElem> getElems() {return elems;}
|
|
std::vector<Condition>* getConds() {return &conds;}
|
|
bool hasConds() {return conds.size() > 0;}
|
|
bool hasEasyConds() {return easyConds.size() > 0;}
|
|
std::vector<Condition> getEasyConds() {return easyConds;}
|
|
std::vector<Assign>& getAssigns() {return assigns;}
|
|
void getElem(int pos, PatElem& elem) const {elem = elems[pos];}
|
|
Condition getCond(int pos) const {return conds[pos];}
|
|
Condition getEasyCond(int pos) const {return easyConds[pos];}
|
|
Assign getAssign(int pos) const {return assigns[pos];}
|
|
std::set<int> getFinalStates() const {return finalStates;}
|
|
bool hasAssigns() {return !assigns.empty();}
|
|
void addPatElem(PatElem pElem) {elems.push_back(pElem);}
|
|
void addRegExSymbol(const char* s) {regEx += s;}
|
|
void addCond(Condition cond) {conds.push_back(cond);}
|
|
void addEasyCond(int pos, Condition cond) {
|
|
easyCondPos[pos].insert(easyConds.size());
|
|
easyConds.push_back(cond);
|
|
}
|
|
void addAssign(Assign ass) {assigns.push_back(ass);}
|
|
void setText(std::string newText) {text = newText;}
|
|
std::pair<int, int> getVarPos(std::string var) {return varPos[var];}
|
|
int getSize() const {return elems.size();}
|
|
int getNoElems() const {return elemToVar.size();}
|
|
std::map<std::string, std::pair<int, int> > getVarPos() {return varPos;}
|
|
std::map<int, std::set<int> > getEasyCondPos() {return easyCondPos;}
|
|
std::set<int> getEasyCondPos(const int e) {return easyCondPos[e];}
|
|
void insertAssVar(std::string v) {assignedVars.insert(v);}
|
|
std::set<std::string> getAssVars() {return assignedVars;}
|
|
void setAssign(int posR, int posP, int key, std::string arg) {
|
|
assigns[posR].setText(key, arg); assigns[posR].setOccurrence(posP);}
|
|
void addAssignRight(int pos, int key, std::pair<std::string, int> varKey)
|
|
{assigns[pos].addRight(key, varKey);}
|
|
void getNFA(std::vector<std::map<int, int> >& result) {
|
|
result = nfa;
|
|
}
|
|
int getNFAsize() const {return nfa.size();}
|
|
bool isNFAempty() const {return (nfa.size() == 0);}
|
|
std::map<int, int> getTransitions(int pos) {assert(pos >= 0);
|
|
assert(pos < (int)nfa.size()); return nfa[pos];}
|
|
bool isFinalState(int state) {return finalStates.find(state)
|
|
!= finalStates.end();}
|
|
void setNFA(std::vector<std::map<int, int> > &_nfa,
|
|
std::set<int> &fs) {
|
|
nfa = _nfa; finalStates = fs;
|
|
}
|
|
void eraseTransition(int state, int pE) {nfa[state].erase(pE);}
|
|
void setDescr(std::string desc) {description = desc;}
|
|
std::string getDescr() {return description;}
|
|
void deleteAssignOpTrees() {for (unsigned int i = 0;i < assigns.size();i++){
|
|
assigns[i].deleteOpTrees();}}
|
|
std::string getRegEx() {return regEx;}
|
|
bool containsRegEx() {return
|
|
regEx.find_first_of("()|") != std::string::npos;}
|
|
void addRelevantVar(std::string var) {relevantVars.insert(var);}
|
|
bool isRelevant(std::string var) {return relevantVars.count(var);}
|
|
std::string getVarFromElem(int elem){
|
|
if (elemToVar.find(elem) != elemToVar.end()) {
|
|
return elemToVar[elem];
|
|
}
|
|
else {
|
|
return "";
|
|
}}
|
|
std::map<std::string, int> getVarToElem() {return varToElem;}
|
|
void setVarToElem(std::map<std::string, int> &vte)
|
|
{varToElem = vte;}
|
|
int getElemFromVar(std::string var) {
|
|
if (varToElem.find(var) == varToElem.end()) {
|
|
return INT_MIN;
|
|
}
|
|
return varToElem[var];}
|
|
int getElemFromAtom(int atom) {return atomicToElem[atom];}
|
|
int get1stAtomFromElem(int elem) {
|
|
for (std::map<int, int>::iterator it = atomicToElem.begin();
|
|
it != atomicToElem.end(); it++) {
|
|
if (it->second == elem) {
|
|
return it->first;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
std::vector<PatElem> elems;
|
|
std::vector<Assign> assigns;
|
|
std::vector<Condition> easyConds; // evaluated during matching
|
|
std::vector<Condition> conds; // evaluated after matching
|
|
std::string text, description, regEx;
|
|
std::map<std::string, std::pair<int, int> > varPos;
|
|
std::map<int, int> atomicToElem;
|
|
std::map<int, std::string> elemToVar;
|
|
std::map<std::string, int> varToElem;
|
|
std::map<int, std::set<int> > easyCondPos;
|
|
std::set<std::string> assignedVars;
|
|
// variables on the right side of an assignment
|
|
std::set<std::string> relevantVars;
|
|
// variables that occur in conds, results, assigns
|
|
std::vector<std::map<int, int> > nfa;
|
|
std::set<int> finalStates;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~PatPersistent~}
|
|
|
|
*/
|
|
class PatPersistent : public Label {
|
|
public:
|
|
PatPersistent() {}
|
|
PatPersistent(int i) : Label(i > 0) {}
|
|
PatPersistent(PatPersistent& src) : Label(src.toText()) {}
|
|
|
|
~PatPersistent() {}
|
|
|
|
std::string toText() const {
|
|
std::string value;
|
|
Label::GetValue(value);
|
|
return value;
|
|
}
|
|
template<class M>
|
|
ExtBool matches(M *traj) {
|
|
Pattern *p = Pattern::getPattern(toText(), false);
|
|
if (p) {
|
|
ExtBool result = p->matches(traj);
|
|
delete p;
|
|
return result;
|
|
}
|
|
else {
|
|
return ST_UNDEF;
|
|
}
|
|
}
|
|
|
|
static const std::string BasicType() {return "pattern";}
|
|
static const bool checkType(const ListExpr type) {
|
|
return listutils::isSymbol(type, BasicType());
|
|
}
|
|
};
|
|
|
|
extern TypeConstructor classifierTC;
|
|
|
|
/*
|
|
\section{Class ~Classifier~}
|
|
|
|
*/
|
|
class Classifier : public Attribute {
|
|
friend class ClassifyLI;
|
|
public:
|
|
Classifier() {}
|
|
Classifier(int i) : Attribute(true), charpos(0), chars(0), delta(0),
|
|
s2p(0), defined(true) {}
|
|
Classifier(const Classifier& src);
|
|
|
|
~Classifier() {
|
|
charpos.Destroy();
|
|
chars.Destroy();
|
|
delta.Destroy();
|
|
s2p.Destroy();
|
|
}
|
|
|
|
static const std::string BasicType() {return "classifier";}
|
|
int getCharPosSize() const {return charpos.Size();}
|
|
int getNumOfP() const {return charpos.Size() / 2;}
|
|
int getCharSize() const {return chars.Size();}
|
|
void appendCharPos(int pos) {charpos.Append(pos);}
|
|
void appendChar(char ch) {chars.Append(ch);}
|
|
void SetDefined(const bool def) {defined = def;}
|
|
bool IsDefined() const {return defined;}
|
|
bool IsEmpty() const {return (chars.Size() == 0);}
|
|
std::string getDesc(int pos);
|
|
std::string getPatText(int pos);
|
|
void buildMultiNFA(std::vector<Pattern*> patterns,
|
|
std::vector<std::map<int, int> > &nfa,
|
|
std::set<int> &finalStates, std::map<int, int> &state2Pat);
|
|
void setPersistentNFA(std::vector<std::map<int, int> > &nfa,
|
|
std::set<int> &finalSt,
|
|
std::map<int, int> &state2Pat) {
|
|
delta.clean();
|
|
s2p.clean();
|
|
Tools::makeNFApersistent(nfa, finalSt, delta, s2p, state2Pat);
|
|
}
|
|
DbArray<NFAtransition> *getDelta() {return δ}
|
|
int getNumOfState2Pat() {return s2p.Size();}
|
|
void getStartStates(std::set<int> &startStates);
|
|
|
|
// algebra support functions
|
|
static Word In(const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct);
|
|
static ListExpr Out(ListExpr typeInfo, Word value);
|
|
static Word Create(const ListExpr typeInfo);
|
|
static void Delete(const ListExpr typeInfo, Word& w);
|
|
static void Close(const ListExpr typeInfo, Word& w);
|
|
static Word Clone(const ListExpr typeInfo, const Word& w);
|
|
static bool Open(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value);
|
|
static bool Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value);
|
|
static bool KindCheck(ListExpr type, ListExpr& errorInfo);
|
|
static int SizeOfObj();
|
|
static void* Cast(void* addr);
|
|
int Compare(const Attribute* arg) const;
|
|
size_t HashValue() const;
|
|
bool Adjacent(const Attribute* arg) const;
|
|
Classifier* Clone() const;
|
|
void CopyFrom(const Attribute* right);
|
|
size_t Sizeof() const;
|
|
static ListExpr Property();
|
|
static bool checkType(ListExpr t) {
|
|
return listutils::isSymbol(t, BasicType());
|
|
}
|
|
|
|
private:
|
|
std::vector<std::map<int, int> > nfa; // multiNFA (not persistent)
|
|
DbArray<int> charpos;
|
|
DbArray<char> chars;
|
|
DbArray<NFAtransition> delta; // multiNFA (persistent)
|
|
DbArray<int> s2p; // neg: start; pos: final; INT_MAX: default
|
|
bool defined;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~TMatch~}
|
|
|
|
*/
|
|
class TMatch {
|
|
private:
|
|
Pattern *p;
|
|
Tuple *t;
|
|
ListExpr ttype;
|
|
std::set<int>** matching;
|
|
int attrno, valueno;
|
|
DataType type;
|
|
std::vector<std::pair<int, std::string> > relevantAttrs;
|
|
std::set<unsigned int>** pathMatrix; // stores the whole matching process
|
|
|
|
public:
|
|
TMatch(Pattern *pat, Tuple *tuple, ListExpr tt, const int _attrno,
|
|
std::vector<std::pair<int, std::string> >& _relevantAttrs,
|
|
const int _valueno);
|
|
|
|
~TMatch() {}
|
|
|
|
ExtBool matches();
|
|
int GetNoMainComponents() const;
|
|
void GetInterval(const int u, temporalalgebra::SecInterval& iv) const;
|
|
bool labelsMatch(const std::set<std::string>& tlabels,
|
|
const int atom, const int pos);
|
|
bool placesMatch(
|
|
const std::set<std::pair<std::string, unsigned int> >& tlabels,
|
|
const int atom, const int pos);
|
|
bool mainValuesMatch(const int u, const int atom);
|
|
bool otherValuesMatch(const int pos,
|
|
const temporalalgebra::SecInterval& iv, const int atom);
|
|
bool valuesMatch(const int u, const int atom, const bool checkMain);
|
|
bool easyCondsMatch(const int u, const int atom);
|
|
bool performTransitions(const int u, std::set<int>& states);
|
|
bool performTransitionsWithMatrix(const int u, std::set<int>& states);
|
|
bool findMatchingBinding(const int startState);
|
|
bool conditionsMatch(const IndexMatchInfo& imi);
|
|
bool findBinding(const int u, const int atom, IndexMatchInfo& imi);
|
|
};
|
|
|
|
extern TypeConstructor tupleindexTC;
|
|
extern TypeConstructor tupleindex2TC;
|
|
|
|
/*
|
|
\section{Class ~TupleIndex~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
class TupleIndex {
|
|
typedef R_Tree<1, NewPair<TupleId, PosType> > RTree1TI;
|
|
typedef R_Tree<2, NewPair<TupleId, PosType> > RTree2TI;
|
|
typedef BTree_t<NewPair<TupleId, PosType> > BTreeTI;
|
|
typedef InvertedFileT<PosType, PosType2> TrieTI;
|
|
|
|
friend class TMatchIndexLI;
|
|
public:
|
|
TupleIndex() {}
|
|
TupleIndex(std::vector<TrieTI*> t, std::vector<BTreeTI*> b,
|
|
std::vector<RTree1TI*> r1, std::vector<RTree2TI*> r2,
|
|
RTree1TI *tI, std::map<int, std::pair<IndexType, int> > aI,
|
|
std::map<std::pair<IndexType, int>, int> iA, int mA, int64_t *fE);
|
|
TupleIndex(bool dummy) { timeIndex = 0;}
|
|
TupleIndex(TupleIndex &src);
|
|
~TupleIndex() {deleteIndexes();}
|
|
|
|
static const std::string BasicType() {
|
|
if (PosType::BasicType() == "newinterval") {
|
|
return "tupleindex2";
|
|
}
|
|
return "tupleindex";
|
|
}
|
|
static bool checkType(const ListExpr list);
|
|
static ListExpr Property();
|
|
static ListExpr Property2();
|
|
static Word In(const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct);
|
|
static ListExpr Out(ListExpr typeInfo, Word value);
|
|
static Word Create(const ListExpr typeInfo);
|
|
static void Delete(const ListExpr typeInfo, Word& w);
|
|
static bool Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value);
|
|
static bool Open(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value);
|
|
static void Close(const ListExpr typeInfo, Word& w);
|
|
static Word Clone(const ListExpr typeInfo, const Word& w);
|
|
static int SizeOfObj();
|
|
static bool TypeCheck(ListExpr type, ListExpr& errorInfo);
|
|
|
|
void initialize(TupleType *ttype, int _mainAttr);
|
|
bool addTuple(Tuple *tuple);
|
|
static void insertIntoTrie(InvertedFileT<PosType, PosType2> *inv, TupleId tid,
|
|
Attribute *traj, DataType type, appendcache::RecordAppendCache* cache,
|
|
TrieNodeCacheType* trieCache, int64_t& inst);
|
|
static bool fillTimeIndex(RTree1TI* rt, TupleId tid, Attribute *traj,
|
|
DataType type);
|
|
static void insertIntoBTree(BTreeTI *bt, TupleId tid,
|
|
temporalalgebra::MInt *mint, int64_t& inst);
|
|
static bool insertIntoRTree1(RTree1TI *rt, TupleId tid, Attribute *m,
|
|
int64_t& inst);
|
|
static bool insertIntoRTree2(RTree2TI *rt, TupleId tid, Attribute *m,
|
|
std::string type, int64_t& inst);
|
|
void deleteIndexes();
|
|
void setTimeLimits(const Instant& leftLimit, const Instant& rightLimit,
|
|
const TupleId id);
|
|
void processTimeIntervals(Relation *rel, const int attr,
|
|
const std::string &typeName);
|
|
void processRTree2(Relation *rel, const int attrNo,
|
|
const std::string &typeName);
|
|
void processRTree1(Relation *rel, const int attr);
|
|
void processBTree(Relation *rel, const int attr);
|
|
void processTrie(Relation *rel, const int attr, const std::string &typeName,
|
|
const size_t memSize);
|
|
void collectSortInsert(Relation *rel, const int attrPos,
|
|
const std::string &typeName, const size_t memSize);
|
|
|
|
private:
|
|
std::vector<TrieTI*> tries;
|
|
std::vector<BTreeTI*> btrees;
|
|
std::vector<RTree1TI*> rtrees1;
|
|
std::vector<RTree2TI*> rtrees2;
|
|
RTree1TI *timeIndex;
|
|
std::map<int, std::pair<IndexType, int> > attrToIndex;
|
|
std::map<std::pair<IndexType, int>, int> indexToAttr;
|
|
int mainAttr;
|
|
NewPair<int64_t, int64_t> timeLimits; // first and last instant of dataset
|
|
std::vector<int64_t> firstEnd; // vector of instants, one entry for each tuple
|
|
};
|
|
|
|
/*
|
|
\section{Struct ~UnitSet~}
|
|
|
|
*/
|
|
struct UnitSet {
|
|
UnitSet() {}
|
|
UnitSet(std::set<int>& u) : units(u) {}
|
|
UnitSet(int unit) {units.insert(unit);}
|
|
|
|
std::set<int> units;
|
|
};
|
|
|
|
/*
|
|
\section{Struct ~IndexRetrieval~}
|
|
|
|
*/
|
|
struct IndexRetrieval : public UnitSet {
|
|
IndexRetrieval() : pred(0), succ(0) {}
|
|
IndexRetrieval(unsigned int p, unsigned int s = 0) : pred(p), succ(s) {}
|
|
IndexRetrieval(unsigned int p, unsigned int s, std::set<int>& u) :
|
|
UnitSet(u), pred(p), succ(s) {}
|
|
IndexRetrieval(unsigned int p, unsigned int s, std::vector<int>& u) :
|
|
pred(p), succ(s) {units.insert(u.begin(), u.end());}
|
|
|
|
unsigned int pred, succ;
|
|
};
|
|
|
|
/*
|
|
\section{Struct ~IndexRetrieval2~}
|
|
|
|
*/
|
|
struct IndexRetrieval2 {
|
|
IndexRetrieval2() : pred(0), succ(0), per(0) {}
|
|
IndexRetrieval2(const unsigned int p, const unsigned int s = 0) :
|
|
pred(p), succ(s), per(0) {}
|
|
IndexRetrieval2(const unsigned int p, const unsigned int s,
|
|
const temporalalgebra::SecInterval& iv) : pred(p), succ(s) {
|
|
per = new temporalalgebra::Periods(1);
|
|
per->Add(iv);
|
|
}
|
|
IndexRetrieval2(const unsigned int p, const unsigned int s,
|
|
temporalalgebra::Periods *_per) :
|
|
pred(p), succ(s) {
|
|
if (!_per->IsValid()) {
|
|
_per->EndBulkLoad(true);
|
|
}
|
|
per = (temporalalgebra::Periods*)_per->compress();
|
|
_per->DeleteIfAllowed();
|
|
}
|
|
|
|
~IndexRetrieval2() {
|
|
if (per != 0) {
|
|
per->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
unsigned int pred, succ;
|
|
temporalalgebra::Periods* per;
|
|
};
|
|
|
|
/*
|
|
\section{Struct ~IndexMatchInfo~}
|
|
|
|
*/
|
|
struct IndexMatchInfo {
|
|
|
|
IndexMatchInfo(std::vector<int> &b) : binding(b) {}
|
|
|
|
IndexMatchInfo(bool r=false, int n = 0) :
|
|
range(r), next(n), prevElem(-1) , binding(){binding.clear();}
|
|
|
|
IndexMatchInfo(bool r, int n, const std::vector<int> b, const int e) :
|
|
range(r), next(n), prevElem(e) {if (b.size() > 0) {binding = b;}}
|
|
|
|
IndexMatchInfo(const int elem, const int u) : range(false), next(-1),
|
|
prevElem(-1) {
|
|
for (int i = 0; i < elem - 1; i++) {
|
|
binding.push_back(-1);
|
|
}
|
|
if (u > 0) {
|
|
binding.push_back(u - 1);
|
|
}
|
|
binding.push_back(u);
|
|
}
|
|
|
|
void print(const bool printBinding);
|
|
bool finished(const int size) const {return range || (next >= size);}
|
|
bool exhausted(const int size) const {return next >= size;}
|
|
bool matches(const int unit) const {return (range ? next<=unit : next==unit);}
|
|
|
|
void set(const int elem, const int to) {
|
|
if (elem >= 0 && (int)binding.size() > elem) {
|
|
binding[elem] = to;
|
|
}
|
|
else if (elem >= 0) {
|
|
while ((int)binding.size() < elem) {
|
|
binding.push_back(-1);
|
|
}
|
|
binding.push_back(to);
|
|
}
|
|
}
|
|
|
|
int getTo(const int elem) const {
|
|
if ((int)binding.size() > elem) {
|
|
return binding[elem];
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int getFrom(const int elem) const {
|
|
if (elem >= -1 && (int)binding.size() > elem) {
|
|
if (binding[elem] == -1) {
|
|
return -1;
|
|
}
|
|
for (int i = elem - 1; i >= 0; i--) {
|
|
if (binding[i] != -1) {
|
|
return binding[i] + 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
bool extendOrInsert(const int elem, const int u) {
|
|
if ((int)binding.size() > elem) {
|
|
binding[elem]++;
|
|
return false;
|
|
}
|
|
else {
|
|
for (int i = binding.size(); i < elem; i++) {
|
|
binding.push_back(-1);
|
|
}
|
|
binding.push_back(u);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void reduceOrErase(const int elem, const bool inserted) {
|
|
if (inserted) {
|
|
binding.pop_back();
|
|
}
|
|
else {
|
|
binding[elem]--;
|
|
}
|
|
}
|
|
|
|
void reset(const int oldEnd) {
|
|
if (prevElem >= 0 && (int)binding.size() > prevElem) {
|
|
binding[prevElem] = oldEnd;
|
|
}
|
|
}
|
|
|
|
bool range;
|
|
int next, prevElem;
|
|
std::vector<int> binding; //holds right ends of bindings for each pattern elem
|
|
};
|
|
|
|
struct cmp {
|
|
bool operator()(const IndexMatchInfo& imi1, const IndexMatchInfo& imi2)const {
|
|
return imi1.binding < imi2.binding;
|
|
}
|
|
};
|
|
|
|
/*
|
|
\section{Struct ~IndexMatchSlot~}
|
|
|
|
*/
|
|
struct IndexMatchSlot {
|
|
IndexMatchSlot() : pred(0), succ(0) {}
|
|
IndexMatchSlot(IndexMatchInfo &imi) : pred(0), succ(0) {imis.push_back(imi);}
|
|
IndexMatchSlot(IndexMatchSlot *src) : pred(src->pred), succ(src->succ),
|
|
imis(src->imis) {}
|
|
|
|
unsigned int pred, succ;
|
|
std::vector<IndexMatchInfo> imis;
|
|
};
|
|
|
|
/*
|
|
\section{Struct ~IndexMatchInfo2~}
|
|
|
|
*/
|
|
struct IndexMatchInfo2 {
|
|
IndexMatchInfo2() : inst(datetime::instanttype) {inst.ToMinimum();}
|
|
IndexMatchInfo2(IndexMatchInfo2 *imi) :
|
|
inst(imi->inst), binding(imi->binding) {}
|
|
IndexMatchInfo2(IndexMatchInfo2 *imi, temporalalgebra::Periods *per) :
|
|
inst(datetime::instanttype), binding(imi->binding) {
|
|
per->Minimum(inst);
|
|
inst = std::max(imi->inst, inst);
|
|
}
|
|
IndexMatchInfo2(const Instant& ins) : inst(ins) {}
|
|
IndexMatchInfo2(const Instant& ins, const int elem,
|
|
const temporalalgebra::Periods *per) : inst(ins) {
|
|
binding.insert(std::make_pair(elem, *per));
|
|
}
|
|
|
|
~IndexMatchInfo2() {}
|
|
|
|
void setInstant(const Instant& ins) {inst = ins;}
|
|
|
|
void extend(const Instant& ins, const int elem,
|
|
const temporalalgebra::Periods *per) {
|
|
inst = ins;
|
|
binding.insert(std::make_pair(elem, *per));
|
|
}
|
|
|
|
Instant getInstant() {return inst;}
|
|
|
|
void getPeriods(const int elem, temporalalgebra::Periods& result) {
|
|
if (binding.find(elem) == binding.end()) { // elem not found
|
|
result.SetDefined(false);
|
|
}
|
|
else {
|
|
result = binding[elem];
|
|
}
|
|
}
|
|
|
|
bool checkPeriods(temporalalgebra::Periods *per) {
|
|
if (!per->IsDefined()) {
|
|
return false;
|
|
}
|
|
if (per->IsEmpty()) {
|
|
return false;
|
|
}
|
|
if (!per->IsOrdered()) {
|
|
per->EndBulkLoad();
|
|
}
|
|
return !per->Before(inst); // match has to occur at or after inst
|
|
}
|
|
|
|
bool exhausted(const int64_t end) {
|
|
return inst.millisecondsToNull() > end;
|
|
}
|
|
|
|
void print() {
|
|
cout << "inst: " << inst << " | binding: ";
|
|
bool hasSucc = true;
|
|
int pos = 0;
|
|
std::map<int, temporalalgebra::Periods>::iterator it;
|
|
while (hasSucc) {
|
|
it = binding.find(-1 * pos - 1);
|
|
if (it != binding.end()) {
|
|
cout << it->first << " ---> " << it->second << " | ";
|
|
}
|
|
it = binding.find(pos);
|
|
if (it != binding.end()) {
|
|
cout << it->first << " ---> " << it->second << " | ";
|
|
}
|
|
else {
|
|
hasSucc = false;
|
|
}
|
|
pos++;
|
|
}
|
|
it = binding.find(pos);
|
|
if (it != binding.end()) {
|
|
cout << it->first << " ---> " << it->second << " | ";
|
|
}
|
|
}
|
|
|
|
bool getBinding(const int elem, temporalalgebra::Periods& result) const {
|
|
if (binding.find(elem) == binding.end()) { // not found
|
|
result.SetDefined(false);
|
|
return false;
|
|
}
|
|
result.SetDefined(true);
|
|
result = binding.at(elem);
|
|
return true;
|
|
}
|
|
|
|
Instant inst;
|
|
std::map<int, temporalalgebra::Periods> binding; // patelem --> interval
|
|
};
|
|
|
|
/*
|
|
\section{Struct ~IndexMatchSlot2~}
|
|
|
|
*/
|
|
struct IndexMatchSlot2 {
|
|
IndexMatchSlot2() : pred(0), succ(0) {}
|
|
IndexMatchSlot2(const IndexMatchInfo2 &imi) : pred(0), succ(0) {
|
|
imis.push_back(imi);
|
|
}
|
|
IndexMatchSlot2(IndexMatchSlot2 *src) : pred(src->pred), succ(src->succ),
|
|
imis(src->imis) {}
|
|
|
|
unsigned int pred, succ;
|
|
std::vector<IndexMatchInfo2> imis;
|
|
};
|
|
|
|
/*
|
|
\section{struct ~DoubleUnitSet~}
|
|
|
|
*/
|
|
struct DoubleUnitSet {
|
|
DoubleUnitSet() {}
|
|
|
|
DoubleUnitSet(std::set<int>& u, bool m = true) {
|
|
if (m) {
|
|
match = u;
|
|
}
|
|
else {
|
|
mismatch = u;
|
|
}
|
|
}
|
|
|
|
DoubleUnitSet(int u, bool m = true) {
|
|
if (m) {
|
|
match.insert(u);
|
|
}
|
|
else {
|
|
mismatch.insert(u);
|
|
}
|
|
}
|
|
|
|
ExtBool getMatchRecord(int u) {
|
|
if (match.find(u) != match.end()) {
|
|
return ST_TRUE;
|
|
}
|
|
if (mismatch.find(u) != mismatch.end()) {
|
|
return ST_FALSE;
|
|
}
|
|
return ST_UNDEF;
|
|
}
|
|
|
|
void addMatchRecord(int u, bool m = true) {
|
|
if (m) {
|
|
match.insert(u);
|
|
}
|
|
else {
|
|
mismatch.insert(u);
|
|
}
|
|
}
|
|
|
|
std::set<int> match;
|
|
std::set<int> mismatch;
|
|
};
|
|
|
|
/*
|
|
\section{struct ~DoubleBindingSet~}
|
|
|
|
*/
|
|
struct DoubleBindingSet {
|
|
DoubleBindingSet() {}
|
|
|
|
DoubleBindingSet(IndexMatchInfo& imi, bool m = true) {
|
|
if (m) {
|
|
match.insert(imi.binding);
|
|
}
|
|
else {
|
|
mismatch.insert(imi.binding);
|
|
}
|
|
}
|
|
|
|
ExtBool getCondRecord(IndexMatchInfo &imi) {
|
|
if (match.find(imi.binding) != match.end()) {
|
|
return ST_TRUE;
|
|
}
|
|
if (mismatch.find(imi.binding) != mismatch.end()) {
|
|
return ST_FALSE;
|
|
}
|
|
return ST_UNDEF;
|
|
}
|
|
|
|
void addCondRecord(IndexMatchInfo &imi, bool m = true) {
|
|
if (m) {
|
|
match.insert(imi.binding);
|
|
}
|
|
else {
|
|
mismatch.insert(imi.binding);
|
|
}
|
|
}
|
|
|
|
std::set<std::vector<int> > match;
|
|
std::set<std::vector<int> > mismatch;
|
|
};
|
|
|
|
/*
|
|
\section{class ~IndexMatchSuper~}
|
|
|
|
*/
|
|
class IndexMatchSuper {
|
|
public:
|
|
IndexMatchSuper(Relation *r, Pattern *_p, int a, DataType t) :
|
|
rel(r), p(_p), attrNo(a), mtype(t), matchRecord(0), condRecord(0),
|
|
trajSize(0), activeTuples(0), unitCtr(0), indexResult(0), indexResult2(0),
|
|
matchInfo(0), newMatchInfo(0), matchInfo2(0), newMatchInfo2(0) {}
|
|
IndexMatchSuper(Relation *r, Pattern *_p) : rel(r), p(_p), attrNo(-1),
|
|
mtype(MLABEL), matchRecord(0), condRecord(0), trajSize(0), activeTuples(0),
|
|
unitCtr(0), indexResult(0), indexResult2(0), matchInfo(0), newMatchInfo(0),
|
|
matchInfo2(0), newMatchInfo2(0) {}
|
|
|
|
~IndexMatchSuper();
|
|
|
|
int getTrajSize(const TupleId tId, const DataType type);
|
|
void getInterval(const TupleId tId, const int pos,
|
|
temporalalgebra::SecInterval& iv);
|
|
void periodsToUnits(const temporalalgebra::Periods *per,
|
|
const TupleId tId, std::set<int> &units);
|
|
template<class M>
|
|
void periodsToUnits(const temporalalgebra::Periods *per,
|
|
const TupleId tId, std::set<int> &units);
|
|
void remove(std::vector<TupleId> &toRemove, const bool mainAttr);
|
|
void removeIdFromIndexResult(const TupleId id, const bool mainAttr);
|
|
void removeIdFromMatchInfo(const TupleId id, const bool mainAttr);
|
|
bool canBeDeactivated(const TupleId id, const int state, const int atom,
|
|
const bool checkRange = false) const;
|
|
void clearMatchInfo();
|
|
void clearMatchInfo2();
|
|
bool hasIdIMIs(const TupleId id, const bool mainAttr, const int state = -1);
|
|
void extendBinding(IndexMatchInfo& imi, const int atom, const bool wc,
|
|
const TupleId id = 0);
|
|
void deletePattern();
|
|
|
|
Relation *rel;
|
|
Pattern *p;
|
|
int attrNo;
|
|
std::vector<std::pair<int, std::string> > relevantAttrs;
|
|
DataType mtype;
|
|
std::vector<TupleId> matches;
|
|
std::vector<NewPair<TupleId, IndexMatchInfo> > matchesR; // rewrite
|
|
DoubleUnitSet ***matchRecord; // state x tuple id
|
|
DoubleBindingSet **condRecord; // tuple id
|
|
bool *active;
|
|
int *trajSize;
|
|
int activeTuples, unitCtr;
|
|
std::set<int> loopStates, crucialAtoms;
|
|
IndexRetrieval ***indexResult;
|
|
IndexRetrieval2 ***indexResult2;
|
|
IndexMatchSlot ***matchInfo, ***newMatchInfo;
|
|
IndexMatchSlot2 ***matchInfo2, ***newMatchInfo2;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~TMatchIndexLI~}
|
|
|
|
*/
|
|
class TMatchIndexLI : public IndexMatchSuper {
|
|
public:
|
|
TMatchIndexLI(Relation *r, ListExpr tt, TupleIndex<UnitPos, UnitPos> *t,
|
|
int a, Pattern *pat, int majorValueNo, DataType type);
|
|
TMatchIndexLI(Relation *r, ListExpr tt, TupleIndex<NewInterval, UnitPos> *t,
|
|
Pattern *p);
|
|
|
|
~TMatchIndexLI();
|
|
|
|
bool tiCompatibleToRel();
|
|
template<class ResultType>
|
|
bool getSingleIndexResult(
|
|
std::pair<int, std::pair<IndexType, int> > indexInfo,
|
|
std::pair<Word, SetRel> values, std::string type,
|
|
int valueNo, std::vector<ResultType> &result);
|
|
int getNoComponents(const TupleId tId, const int attrNo);
|
|
Instant getFirstEnd(const TupleId id);
|
|
void unitsToPeriods(const std::set<int> &units, const TupleId tId,
|
|
const int attr, temporalalgebra::Periods *per);
|
|
template<class M, class U>
|
|
void unitsToPeriods(Attribute *traj, const std::set<int> &units,
|
|
temporalalgebra::Periods *per);
|
|
void getResultForAtomPart(std::pair<int, std::pair<IndexType,int> > indexInfo,
|
|
std::pair<Word, SetRel> values, std::string type,
|
|
std::vector<temporalalgebra::Periods*> &prev,
|
|
std::vector<temporalalgebra::Periods*> &result,
|
|
const int prevCrucial, const bool mainAttr,
|
|
bool checkPrev = false);
|
|
bool getResultForAtomTime(const int atomNo, const int prevCrucial,
|
|
std::vector<temporalalgebra::Periods*> &result);
|
|
void storeIndexResult(const int atomNo, const int prevCrucial,
|
|
const bool mainAttr, int &noResults);
|
|
void initMatchInfo(const bool mainAttr);
|
|
bool atomMatch(int state, std::pair<int, int> trans,
|
|
const bool rewrite = false);
|
|
void extendBinding2(temporalalgebra::Periods *per, const int elem,
|
|
const bool totalMatch, IndexMatchInfo2& imi);
|
|
bool canBeDeactivated2(const TupleId id, const int state, const int atom);
|
|
bool geoMatch(const int atomNo, Tuple *t, temporalalgebra::Periods *per);
|
|
bool condsMatch(Tuple *t, const IndexMatchInfo2& imi);
|
|
bool easyCondsMatch(const int atomNo,Tuple *t, temporalalgebra::Periods *per);
|
|
bool atomMatch2(const int state, std::pair<int, int> trans);
|
|
void applyNFA(const bool mainAttr, const bool rewrite = false);
|
|
bool initialize(const bool mainAttr, const bool rewrite = false);
|
|
Tuple* nextTuple();
|
|
|
|
private:
|
|
ListExpr ttList;
|
|
TupleIndex<UnitPos, UnitPos> *ti; // Unit (, Ref)
|
|
TupleIndex<NewInterval, UnitPos> *ti2; // Interval (, Ref)
|
|
int valueNo; // only relevant for indextmatches
|
|
std::vector<int64_t> *firstEnd; //earliest end of time-dep. attrs per tuple
|
|
};
|
|
|
|
/*
|
|
\section{Class ~IndexRewriteLI~}
|
|
|
|
*/
|
|
template<class M>
|
|
class IndexRewriteLI : public TMatchIndexLI {
|
|
public:
|
|
IndexRewriteLI(Relation *r, ListExpr tt, TupleIndex<UnitPos, UnitPos> *t,
|
|
int a, Pattern *pat, int majorValueNo, DataType type) :
|
|
TMatchIndexLI(r, tt, t, a, pat, majorValueNo, type) {}
|
|
|
|
M* nextResult();
|
|
private:
|
|
|
|
};
|
|
|
|
/*
|
|
\section{Class ~Match~}
|
|
|
|
*/
|
|
template<class M>
|
|
class Match {
|
|
public:
|
|
Pattern *p;
|
|
M *m; // mlabel, mplace, mlabels, mplaces
|
|
std::set<unsigned int>** matching; // stores the whole matching process
|
|
DataType type; // enum
|
|
|
|
Match(Pattern *pat, M *traj) {
|
|
p = pat;
|
|
m = traj;
|
|
matching = 0;
|
|
type = getMType();
|
|
}
|
|
|
|
~Match() {}
|
|
|
|
DataType getMType();
|
|
ExtBool matches();
|
|
bool valuesMatch(int i, const PatElem& elem);
|
|
bool updateStates(int i, std::vector<std::map<int, int> > &nfa,
|
|
std::vector<PatElem> &elems,
|
|
std::set<int> &finalStates, std::set<int> &states,
|
|
std::vector<Condition> &easyConds,
|
|
std::map<int, std::set<int> > &easyCondPos,
|
|
std::map<int, int> &atomicToElem, bool store = false);
|
|
bool easyCondsMatch(int ulId, PatElem const &elem,
|
|
std::vector<Condition> &easyConds, std::set<int> pos);
|
|
std::string states2Str(int ulId, std::set<int> &states);
|
|
std::string matchings2Str(unsigned int dim1, unsigned int dim2);
|
|
bool findMatchingBinding(std::vector<std::map<int, int> > &nfa,
|
|
int startState,
|
|
std::vector<PatElem> &elems, std::vector<Condition> &conds,
|
|
std::map<int, int> &atomicToElem,
|
|
std::map<int, std::string> &elemToVar);
|
|
bool findBinding(unsigned int ulId,
|
|
unsigned int pId, std::vector<PatElem> &elems,
|
|
std::vector<Condition> &conds,
|
|
std::map<int, std::string> &elemToVar, IndexMatchInfo &imi);
|
|
void cleanPaths(std::map<int, int> &atomicToElem);
|
|
bool cleanPath(unsigned int ulId, unsigned int pId);
|
|
bool conditionsMatch(std::vector<Condition> &conds,const IndexMatchInfo &imi);
|
|
bool evaluateEmptyM();
|
|
bool isSensiblyBound(const std::map<std::string, std::pair<int, int> > &b,
|
|
std::string& var);
|
|
void deletePattern() {if (p) {delete p; p = 0;}}
|
|
bool initEasyCondOpTrees() {return p->initEasyCondOpTrees(true);}
|
|
bool initCondOpTrees() {return p->initCondOpTrees();}
|
|
bool initAssignOpTrees() {return p->initAssignOpTrees();}
|
|
void deleteSetMatrix() {if (matching) {
|
|
Tools::deleteSetMatrix(matching, m->GetNoComponents());}}
|
|
void createSetMatrix(unsigned int dim1, unsigned int dim2) {
|
|
matching = Tools::createSetMatrix(dim1, dim2);}
|
|
void setM(M *newM) {m = newM;}
|
|
std::vector<int> applyConditions(ClassifyLI* c);
|
|
|
|
|
|
void setNFA(std::vector<std::map<int, int> > &nfa, std::set<int> &fs) {
|
|
p->setNFA(nfa, fs);
|
|
}
|
|
void setNFAfromDbArrays(DbArray<NFAtransition> &trans, DbArray<int> &fs) {
|
|
std::vector<std::map<int, int> > nfa;
|
|
std::set<int> finalStates;
|
|
Tools::createNFAfromPersistent(trans, fs, nfa, finalStates);
|
|
p->setNFA(nfa, finalStates);
|
|
}
|
|
void setPattern(Pattern *pat) {p = pat;}
|
|
Pattern* getPattern() {return p;}
|
|
M* getM() {return m;}
|
|
std::pair<std::string, Attribute*> getPointer(int key);
|
|
static std::pair<QueryProcessor*, OpTree> processQueryStr(
|
|
std::string query, int type);
|
|
};
|
|
|
|
/*
|
|
\section{Struct ~BindingStackElem~}
|
|
|
|
*/
|
|
struct BindingStackElem {
|
|
BindingStackElem(unsigned int ul, unsigned int pe) : ulId(ul), peId(pe) {}
|
|
|
|
unsigned int ulId, peId;
|
|
// map<string, std::pair<int, int> > binding;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~RewriteLI~}
|
|
|
|
*/
|
|
template<class M>
|
|
class RewriteLI {
|
|
public:
|
|
RewriteLI(M *src, Pattern *pat);
|
|
RewriteLI(int i) : match(0) {}
|
|
|
|
~RewriteLI() {clearMatch(true);}
|
|
|
|
void clearMatch(const bool deletePattern);
|
|
M* getNextResult();
|
|
M* rewrite(M *src, IndexMatchInfo &imi, std::vector<Assign> &assigns);
|
|
void resetBinding(int limit);
|
|
bool findNextBinding(unsigned int ulId, unsigned int pId, Pattern *p,
|
|
int offset);
|
|
|
|
protected:
|
|
std::stack<BindingStackElem> bindingStack;
|
|
Match<M> *match;
|
|
IndexMatchInfo imi;
|
|
std::set<IndexMatchInfo, cmp> rewBindings;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~ClassifyLI~}
|
|
|
|
*/
|
|
class ClassifyLI {
|
|
|
|
friend class Match<MLabel>;
|
|
friend class Match<MLabels>;
|
|
friend class Match<MPlace>;
|
|
friend class Match<MPlaces>;
|
|
|
|
public:
|
|
template<class M>
|
|
ClassifyLI(M *traj, Word _classifier);
|
|
ClassifyLI(int i) : classifyTT(0) {}
|
|
|
|
~ClassifyLI();
|
|
|
|
static TupleType* getTupleType();
|
|
FText* nextResultText();
|
|
void printMatches();
|
|
|
|
protected:
|
|
std::vector<Pattern*> pats;
|
|
TupleType* classifyTT;
|
|
std::set<int> matchingPats;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~MultiRewriteLI~}
|
|
|
|
*/
|
|
template<class M>
|
|
class MultiRewriteLI : public ClassifyLI, public RewriteLI<M> {
|
|
public:
|
|
MultiRewriteLI(Word _mlstream, Word _pstream, int _pos);
|
|
|
|
~MultiRewriteLI();
|
|
|
|
M* nextResult();
|
|
void getStartStates(std::set<int> &states);
|
|
void initStack(std::set<int> &startStates);
|
|
|
|
private:
|
|
Stream<Tuple> tStream;
|
|
int attrpos;
|
|
bool streamOpen;
|
|
M* traj;
|
|
Classifier* c;
|
|
std::map<int, int> state2Pat;
|
|
std::set<int> finalStates, states, matchCands;
|
|
std::vector<std::map<int, int> > nfa;
|
|
std::vector<PatElem> patElems;
|
|
std::vector<Condition> easyConds;
|
|
std::map<int, std::set<int> > easyCondPos;
|
|
std::map<int, std::pair<int, int> > patOffset;
|
|
// elem no |-> (pat no, first pat elem)
|
|
std::map<int, int> atomicToElem;
|
|
std::map<int, std::string> elemToVar;
|
|
std::map<std::string, int> varToElem;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~FilterMatchesLI~}
|
|
|
|
*/
|
|
template<class M>
|
|
class FilterMatchesLI {
|
|
public:
|
|
FilterMatchesLI(Word _stream, int _attrIndex, std::string& pText);
|
|
|
|
~FilterMatchesLI();
|
|
|
|
Tuple* getNextResult();
|
|
|
|
private:
|
|
Stream<Tuple> stream;
|
|
int attrIndex;
|
|
Match<M>* match;
|
|
bool streamOpen, deleteP;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~IndexMatchesLI~}
|
|
|
|
*/
|
|
class IndexMatchesLI : public IndexMatchSuper {
|
|
public:
|
|
IndexMatchesLI(Relation *_rel, InvertedFile *inv,
|
|
R_Tree<1, NewPair<TupleId, UnitPos> > *rt, int _attrNr, Pattern *_p,
|
|
DataType type);
|
|
|
|
~IndexMatchesLI();
|
|
|
|
Tuple* nextTuple();
|
|
void retrieveValue(std::vector<std::set<int> >& part,
|
|
std::vector<std::set<int> >& part2,
|
|
SetRel rel, bool first, const std::string& label,
|
|
unsigned int ref = UINT_MAX);
|
|
void retrieveTime(std::vector<std::set<int> >& oldPart,
|
|
std::vector<std::set<int> >& newPart,
|
|
const std::string& ivstr);
|
|
void removeIdFromMatchInfo(const TupleId id);
|
|
void storeIndexResult(const int e);
|
|
void initMatchInfo(const std::set<int>& cruElems);
|
|
void initialize();
|
|
void applyNFA();
|
|
template<class M>
|
|
bool imiMatch(Match<M>& match, const int e, const TupleId id,
|
|
IndexMatchInfo& imi, const int unit, const int newState);
|
|
bool valuesMatch(const int e, const TupleId id, IndexMatchInfo& imi,
|
|
const int newState, const int unit);
|
|
void applySetRel(const SetRel setRel,
|
|
std::vector<std::set<std::pair<TupleId, int> > >& valuePosVec,
|
|
std::set<std::pair<TupleId, int> >*& result);
|
|
bool simpleMatch(const int e, const int state, const int newState);
|
|
bool wildcardMatch(const int state, std::pair<int, int> trans);
|
|
bool timesMatch(const TupleId id,const unsigned int unit,const PatElem& elem);
|
|
bool checkConditions(const TupleId id, IndexMatchInfo& imi);
|
|
|
|
protected:
|
|
std::set<int> indexMismatch;
|
|
InvertedFile* invFile;
|
|
R_Tree<1, NewPair<TupleId, UnitPos> > *rtree;
|
|
size_t maxMLsize;
|
|
std::vector<bool> deactivated;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~IndexClassifyLI~}
|
|
|
|
*/
|
|
class IndexClassifyLI : public IndexMatchesLI {
|
|
public:
|
|
IndexClassifyLI(Relation *rel, InvertedFile *inv,
|
|
R_Tree<1, NewPair<TupleId, UnitPos> > *rt, Word _classifier, int _attrNr,
|
|
DataType type);
|
|
|
|
~IndexClassifyLI();
|
|
|
|
template<class M>
|
|
Tuple* nextResultTuple();
|
|
|
|
protected:
|
|
TupleType* classifyTT;
|
|
Classifier *c;
|
|
std::queue<std::pair<std::string, TupleId> > results;
|
|
int currentPat;
|
|
};
|
|
|
|
/*
|
|
\section{Class ~DeriveGroupsLI~}
|
|
|
|
*/
|
|
template<class M>
|
|
class DeriveGroupsLI {
|
|
public:
|
|
DeriveGroupsLI(Word _stream, double threshold, int attrNo);
|
|
|
|
~DeriveGroupsLI() {}
|
|
|
|
Tuple *getNextTuple();
|
|
|
|
private:
|
|
std::vector<std::pair<TupleId, unsigned int> > result;
|
|
};
|
|
|
|
/*
|
|
\subsection{Function ~restrict~}
|
|
|
|
*/
|
|
template<class M>
|
|
void Condition::restrictPtr(const int pos, M *traj, const int from,
|
|
const int to, Tuple *tuple, ListExpr ttype, const int key) {
|
|
temporalalgebra::Periods per(true);
|
|
if (from > -1 && to > -1 && to >= from) {
|
|
temporalalgebra::SecInterval iv(true), ivtemp(true);
|
|
traj->GetInterval(from, iv);
|
|
traj->GetInterval(to, ivtemp);
|
|
iv.end = ivtemp.end;
|
|
iv.rc = ivtemp.rc;
|
|
per.Add(iv);
|
|
}
|
|
copyAndRestrictPtr(pos, tuple, ttype, key, per);
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~setPointerToValue~}
|
|
|
|
*/
|
|
template<class M>
|
|
void Condition::setPointerToValue(const int pos, M *traj, const int from,
|
|
const int to) {
|
|
temporalalgebra::SecInterval iv(true);
|
|
switch (getKey(pos)) {
|
|
case 0: { // label
|
|
std::string value;
|
|
((MLabel*)traj)->GetValue(from, value);
|
|
setValuePtr(pos, value);
|
|
break;
|
|
}
|
|
case 1: { // place
|
|
std::pair<std::string, unsigned int> value;
|
|
((MPlace*)traj)->GetValue(from, value);
|
|
setValuePtr(pos, value);
|
|
break;
|
|
}
|
|
case 2: { // time
|
|
clearTimePtr(pos);
|
|
for (int j = from; j <= to; j++) {
|
|
traj->GetInterval(j, iv);
|
|
mergeAddTimePtr(pos, iv);
|
|
}
|
|
break;
|
|
}
|
|
case 3: { // start
|
|
traj->GetInterval(from, iv);
|
|
setStartEndPtr(pos, iv.start);
|
|
break;
|
|
}
|
|
case 4: { // end
|
|
traj->GetInterval(to, iv);
|
|
setStartEndPtr(pos, iv.end);
|
|
break;
|
|
}
|
|
case 5: { // leftclosed
|
|
traj->GetInterval(from, iv);
|
|
setLeftRightclosedPtr(pos, iv.lc);
|
|
break;
|
|
}
|
|
case 6: { // rightclosed
|
|
traj->GetInterval(to, iv);
|
|
setLeftRightclosedPtr(pos, iv.rc);
|
|
break;
|
|
}
|
|
case 7: { // card
|
|
setCardPtr(pos, to - from + 1);
|
|
break;
|
|
}
|
|
case 8: { // labels
|
|
cleanLabelsPtr(pos);
|
|
if (M::BasicType() == MLabel::BasicType()) {
|
|
for (int j = from; j <= to; j++) {
|
|
std::string value;
|
|
((MLabel*)traj)->GetValue(j, value);
|
|
appendToLabelsPtr(pos, value);
|
|
}
|
|
}
|
|
else {
|
|
for (int j = from; j <= to; j++) {
|
|
std::set<std::string> values;
|
|
((MLabels*)traj)->GetValues(j, values);
|
|
appendToLabelsPtr(pos, values);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: { // places
|
|
cleanPlacesPtr(pos);
|
|
if (M::BasicType() == MPlace::BasicType()) {
|
|
for (int j = from; j <= to; j++) {
|
|
std::pair<std::string, unsigned int> value;
|
|
((MPlace*)traj)->GetValue(j, value);
|
|
appendToPlacesPtr(pos, value);
|
|
}
|
|
}
|
|
else {
|
|
for (int j = from; j <= to; j++) {
|
|
std::set<std::pair<std::string, unsigned int> > values;
|
|
((MPlaces*)traj)->GetValues(j, values);
|
|
appendToPlacesPtr(pos, values);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~setPointerToEmptyValue~}
|
|
|
|
*/
|
|
template<class M>
|
|
void Condition::setPointerToEmptyValue(const int pos, M *traj,
|
|
Tuple *t /* = 0 */, ListExpr ttype /* = 0 */) {
|
|
temporalalgebra::SecInterval iv(true);
|
|
switch (getKey(pos)) {
|
|
case 0: { // label
|
|
std::string value("");
|
|
setValuePtr(pos, value);
|
|
break;
|
|
}
|
|
case 1: { // place
|
|
std::pair<std::string, unsigned int> value;
|
|
setValuePtr(pos, value);
|
|
break;
|
|
}
|
|
case 2: {
|
|
clearTimePtr(pos);
|
|
traj->GetInterval(traj->GetNoComponents() - 1, iv);
|
|
iv.SetStart(iv.end, false);
|
|
mergeAddTimePtr(pos, iv);
|
|
break;
|
|
}
|
|
case 3: // start
|
|
case 4: { // end
|
|
traj->GetInterval(traj->GetNoComponents() - 1, iv);
|
|
setStartEndPtr(pos, iv.end);
|
|
break;
|
|
}
|
|
case 5: // leftclosed
|
|
case 6: { // rightclosed
|
|
traj->GetInterval(traj->GetNoComponents() - 1, iv);
|
|
setLeftRightclosedPtr(pos, iv.rc);
|
|
break;
|
|
}
|
|
case 7: {
|
|
setCardPtr(pos, 0);
|
|
break;
|
|
}
|
|
case 8: {
|
|
cleanLabelsPtr(pos);
|
|
break;
|
|
}
|
|
case 9: {
|
|
cleanPlacesPtr(pos);
|
|
break;
|
|
}
|
|
default: {
|
|
restrictPtr(pos, traj, -1, -1, t, ttype, getKey(pos) - 99);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~evaluate~}
|
|
|
|
This function is invoked by ~conditionsMatch~ (and others) and checks whether a
|
|
binding matches a certain condition.
|
|
|
|
*/
|
|
template<class M>
|
|
bool Condition::evaluate(const IndexMatchInfo& imi, M *traj,
|
|
std::map<std::string, int> &varToElem,
|
|
Tuple *tuple /* = 0 */, ListExpr ttype /* = 0 */) {
|
|
// cout << "EVAL \'" << text << "\'; " << getVarKeysSize() << endl;
|
|
Word qResult;
|
|
int from, to;
|
|
for (int i = 0; i < getVarKeysSize(); i++) {
|
|
int elem = varToElem[getVar(i)];
|
|
from = imi.getFrom(elem);
|
|
to = imi.getTo(elem);
|
|
if (elem != -1 && from != -1 && to != -1 && from <= to) {
|
|
int key = getKey(i);
|
|
if (key > 99) { // reference to attribute of tuple
|
|
if (!tuple || !ttype) {
|
|
return false;
|
|
}
|
|
if (Tools::isMovingAttr(ttype, key - 99)) {
|
|
// cout << "restrict: " << getVar(i) << " " << from << " " << to
|
|
// << " " << key-99 << endl;
|
|
restrictPtr(i, traj, from, to, tuple, ttype, key - 99);
|
|
}
|
|
else {
|
|
pointers[i]->CopyFrom(tuple->GetAttribute(key - 100));
|
|
}
|
|
}
|
|
else {
|
|
setPointerToValue<M>(i, traj, from, to);
|
|
}
|
|
}
|
|
else { // variable bound to empty sequence
|
|
setPointerToEmptyValue<M>(i, traj, tuple, ttype);
|
|
}
|
|
}
|
|
getQP()->EvalS(getOpTree(), qResult, OPEN);
|
|
// if (!((CcBool*)qResult.addr)->GetValue()) {
|
|
// cout << "FALSE result: FROM " << from << " TO " << to << "; result for |"
|
|
// << text
|
|
// << "| is " << (((CcBool*)qResult.addr)->GetValue() ? "TRUE":"FALSE")
|
|
// << endl;
|
|
// }
|
|
return ((CcBool*)qResult.addr)->GetValue();
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~matches~}
|
|
|
|
Checks the pattern and the condition and (if no problem occurs) invokes the NFA
|
|
construction and the matching procedure.
|
|
|
|
*/
|
|
template<class M>
|
|
ExtBool Pattern::matches(M *m) {
|
|
ExtBool result = ST_UNDEF;
|
|
if (!isValid(M::BasicType())) {
|
|
cout << "pattern is not suitable for type " << M::BasicType() << endl;
|
|
return result;
|
|
}
|
|
Match<M> *match = new Match<M>(this, m);
|
|
if (initEasyCondOpTrees(true)) {
|
|
result = match->matches();
|
|
}
|
|
delete match;
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~getType~}
|
|
|
|
*/
|
|
template<class M>
|
|
DataType Match<M>::getMType() {
|
|
if (M::BasicType() == "mlabels") {
|
|
return MLABELS;
|
|
}
|
|
if (M::BasicType() == "mplace") {
|
|
return MPLACE;
|
|
}
|
|
if (M::BasicType() == "mplaces") {
|
|
return MPLACES;
|
|
}
|
|
return MLABEL;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~match~}
|
|
|
|
Loops through the MLabel calling updateStates() for every ULabel. True is
|
|
returned if and only if the final state is an element of currentStates after
|
|
the loop.
|
|
|
|
*/
|
|
template<class M>
|
|
ExtBool Match<M>::matches() {
|
|
if (p->isNFAempty()) {
|
|
cout << "empty nfa" << endl;
|
|
return ST_UNDEF;
|
|
}
|
|
if (!p->initEasyCondOpTrees(true)) {
|
|
cout << "Error: EasyCondOpTrees not initialized" << endl;
|
|
return ST_UNDEF;
|
|
}
|
|
std::set<int> states;
|
|
states.insert(0);
|
|
if (!p->hasConds() && !p->hasAssigns()) {
|
|
for (int i = 0; i < m->GetNoComponents(); i++) {
|
|
if (!updateStates(i, p->nfa, p->elems, p->finalStates, states,
|
|
p->easyConds, p->easyCondPos, p->atomicToElem)) {
|
|
// cout << "mismatch at unit " << i << endl;
|
|
return ST_FALSE;
|
|
}
|
|
}
|
|
if (!p->containsFinalState(states)) {
|
|
// cout << "no final state is active" << endl;
|
|
return ST_FALSE;
|
|
}
|
|
}
|
|
else {
|
|
createSetMatrix(m->GetNoComponents(), p->elemToVar.size());
|
|
for (int i = 0; i < m->GetNoComponents(); i++) {
|
|
if (!updateStates(i, p->nfa, p->elems, p->finalStates, states,
|
|
p->easyConds, p->easyCondPos, p->atomicToElem, true)){
|
|
// cout << "mismatch at unit " << i << endl;
|
|
Tools::deleteSetMatrix(matching, m->GetNoComponents());
|
|
return ST_FALSE;
|
|
}
|
|
}
|
|
if (!p->containsFinalState(states)) {
|
|
// cout << "no final state is active" << endl;
|
|
Tools::deleteSetMatrix(matching, m->GetNoComponents());
|
|
matching = 0;
|
|
return ST_FALSE;
|
|
}
|
|
if (!p->initCondOpTrees()) {
|
|
Tools::deleteSetMatrix(matching, m->GetNoComponents());
|
|
matching = 0;
|
|
return ST_UNDEF;
|
|
}
|
|
if (!p->hasAssigns()) {
|
|
bool result = findMatchingBinding(p->nfa, 0, p->elems, p->conds,
|
|
p->atomicToElem, p->elemToVar);
|
|
Tools::deleteSetMatrix(matching, m->GetNoComponents());
|
|
matching = 0;
|
|
return (result ? ST_TRUE : ST_FALSE);
|
|
}
|
|
return ST_TRUE; // happens iff rewrite is called
|
|
}
|
|
return ST_TRUE;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~states2Str~}
|
|
|
|
Writes the set of currently active states into a string.
|
|
|
|
*/
|
|
template<class M>
|
|
std::string Match<M>::states2Str(int ulId, std::set<int> &states) {
|
|
std::stringstream result;
|
|
if (!states.empty()) {
|
|
std::set<int>::iterator it = states.begin();
|
|
result << "after unit # " << ulId << ", active states are {" << *it;
|
|
it++;
|
|
while (it != states.end()) {
|
|
result << ", " << *it;
|
|
it++;
|
|
}
|
|
result << "}" << endl;
|
|
}
|
|
else {
|
|
result << "after unit # " << ulId << ", there is no active state" << endl;
|
|
}
|
|
return result.str();
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~matchings2Str~}
|
|
|
|
Writes the matching table into a string.
|
|
|
|
*/
|
|
template<class M>
|
|
std::string Match<M>::matchings2Str(unsigned int dim1, unsigned int dim2) {
|
|
std::stringstream result;
|
|
for (unsigned int i = 0; i < dim1; i++) {
|
|
for (unsigned int j = 0; j < dim2; j++) {
|
|
if (matching[i][j].empty()) {
|
|
result << " ";
|
|
}
|
|
else {
|
|
std::string cell;
|
|
std::set<unsigned int>::iterator it, it2;
|
|
for (it = matching[i][j].begin(); it != matching[i][j].end(); it++) {
|
|
it2 = it;
|
|
it2++;
|
|
cell += int2Str(*it) + (it2 != matching[i][j].end() ? "," : "");
|
|
}
|
|
result << cell;
|
|
for (unsigned int k = 20; k > cell.size(); k--) {
|
|
result << " ";
|
|
}
|
|
}
|
|
}
|
|
result << endl;
|
|
}
|
|
return result.str();
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~valuesMatch~}
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::valuesMatch(int i, const PatElem& elem) {
|
|
std::set<std::pair<std::string, unsigned int> > mpls;
|
|
std::set<std::string> lbs, mlbs;
|
|
elem.getL(lbs);
|
|
if (lbs.empty() && (elem.getSetRel() < SUPERSET)) {
|
|
return true; // easiest case
|
|
}
|
|
switch (type) {
|
|
case MLABEL: {
|
|
std::string mlb;
|
|
((MLabel*)m)->GetValue(i, mlb);
|
|
if (elem.getSetRel() == STANDARD) {
|
|
return lbs.find(mlb) != lbs.end();
|
|
}
|
|
mlbs.insert(mlb);
|
|
return Tools::relationHolds(mlbs, lbs, elem.getSetRel());
|
|
}
|
|
case MLABELS: {
|
|
((MLabels*)m)->GetValues(i, mlbs);
|
|
return Tools::relationHolds(mlbs, lbs, elem.getSetRel());
|
|
}
|
|
case MPLACE: {
|
|
std::pair<std::string, unsigned int> mpl;
|
|
((MPlace*)m)->GetValue(i, mpl);
|
|
mpls.insert(mpl);
|
|
return Tools::relationHolds(mpls, lbs, elem.getSetRel());
|
|
}
|
|
case MPLACES: {
|
|
((MPlaces*)m)->GetValues(i, mpls);
|
|
return Tools::relationHolds(mpls, lbs, elem.getSetRel());
|
|
}
|
|
default: { // cannot occur
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~updateStates~}
|
|
|
|
Applies the NFA. Each valid transaction is processed. If ~store~ is true,
|
|
each matching is stored.
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::updateStates(int ulId, std::vector<std::map<int, int> > &nfa,
|
|
std::vector<PatElem> &elems,
|
|
std::set<int> &finalStates, std::set<int> &states,
|
|
std::vector<Condition> &easyConds,
|
|
std::map<int, std::set<int> > &easyCondPos,
|
|
std::map<int, int> &atomicToElem, bool store /* = false */) {
|
|
std::set<int>::iterator its;
|
|
std::set<unsigned int>::iterator itu;
|
|
std::map<int, int> transitions;
|
|
for (its = states.begin(); its != states.end(); its++) { // collect possible
|
|
std::map<int, int> trans = nfa[*its]; // transitions
|
|
transitions.insert(trans.begin(), trans.end());
|
|
}
|
|
if (transitions.empty()) {
|
|
return false;
|
|
}
|
|
states.clear();
|
|
std::map<int, int>::iterator itm, itn;
|
|
temporalalgebra::SecInterval iv;
|
|
m->GetInterval(ulId, iv);
|
|
std::set<std::string> ivs;
|
|
if (store) {
|
|
if (ulId < m->GetNoComponents() - 1) { // usual case
|
|
for (itm = transitions.begin(); itm != transitions.end(); itm++) {
|
|
elems[itm->first].getI(ivs);
|
|
if (valuesMatch(ulId, elems[itm->first]) && Tools::timesMatch(iv, ivs)
|
|
&& easyCondsMatch(ulId, elems[itm->first], easyConds,
|
|
easyCondPos[itm->first])) {
|
|
states.insert(states.end(), itm->second);
|
|
std::map<int, int> nextTrans = nfa[itm->second];
|
|
for (itn = nextTrans.begin(); itn != nextTrans.end(); itn++) {
|
|
itu = matching[ulId][atomicToElem[itm->first]].end();
|
|
matching[ulId][atomicToElem[itm->first]].insert
|
|
(itu, atomicToElem[itn->first]);// store matching
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else { // last row; mark final states with -1
|
|
for (itm = transitions.begin(); itm != transitions.end(); itm++) {
|
|
elems[itm->first].getI(ivs);
|
|
if (valuesMatch(ulId, elems[itm->first]) && Tools::timesMatch(iv, ivs)
|
|
&& easyCondsMatch(ulId, elems[itm->first], easyConds,
|
|
easyCondPos[itm->first])) {
|
|
states.insert(states.end(), itm->second);
|
|
if (finalStates.count(itm->second)) { // store last matching
|
|
matching[ulId][atomicToElem[itm->first]].insert(UINT_MAX);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (itm = transitions.begin(); itm != transitions.end(); itm++) {
|
|
elems[itm->first].getI(ivs);
|
|
if (valuesMatch(ulId, elems[itm->first]) && Tools::timesMatch(iv, ivs)
|
|
&& easyCondsMatch(ulId, elems[itm->first], easyConds,
|
|
easyCondPos[itm->first])) {
|
|
states.insert(states.end(), itm->second);
|
|
}
|
|
}
|
|
}
|
|
return !states.empty();
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~cleanPaths~}
|
|
|
|
Deletes all paths inside ~matching~ which do not end at a final state.
|
|
|
|
*/
|
|
template<class M>
|
|
void Match<M>::cleanPaths(std::map<int, int> &atomicToElem) {
|
|
std::map<int, int> transitions = p->getTransitions(0);
|
|
std::map<int, int>::reverse_iterator itm;
|
|
for (itm = transitions.rbegin(); itm != transitions.rend(); itm++) {
|
|
cleanPath(0, atomicToElem[itm->first]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~findMatchingBinding~}
|
|
|
|
Searches for a binding which fulfills every condition.
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::findMatchingBinding(std::vector<std::map<int, int> > &nfa,
|
|
int startState,
|
|
std::vector<PatElem> &elems,
|
|
std::vector<Condition> &conds,
|
|
std::map<int, int> &atomicToElem,
|
|
std::map<int, std::string> &elemToVar) {
|
|
if ((startState < 0) || (startState > (int)nfa.size() - 1)) {
|
|
return false; // illegal start state
|
|
}
|
|
if (conds.empty()) {
|
|
return true;
|
|
}
|
|
std::map<int, int> transitions = nfa[startState];
|
|
IndexMatchInfo imi;
|
|
std::map<int, int>::reverse_iterator itm;
|
|
for (itm = transitions.rbegin(); itm != transitions.rend(); itm++) {
|
|
if (findBinding(0, atomicToElem[itm->first], elems, conds, elemToVar, imi)){
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~findBinding~}
|
|
|
|
Recursively finds all bindings in the matching set matrix and checks whether
|
|
they fulfill every condition, stopping immediately after the first success.
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::findBinding(unsigned int ulId, unsigned int pId,
|
|
std::vector<PatElem> &elems, std::vector<Condition> &conds,
|
|
std::map<int, std::string> &elemToVar, IndexMatchInfo &imi) {
|
|
std::string var = elemToVar[pId];
|
|
bool inserted = imi.extendOrInsert(pId, ulId);
|
|
if (*(matching[ulId][pId].begin()) == UINT_MAX) { // complete match
|
|
if (conditionsMatch(conds, imi)) {
|
|
return true;
|
|
}
|
|
}
|
|
else {
|
|
for (std::set<unsigned int>::reverse_iterator
|
|
it = matching[ulId][pId].rbegin();
|
|
it != matching[ulId][pId].rend(); it++) {
|
|
if (findBinding(ulId + 1, *it, elems, conds, elemToVar, imi)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
imi.reduceOrErase(pId, inserted);
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~cleanPath~}
|
|
|
|
Recursively deletes all paths starting from (ulId, pId) that do not end at a
|
|
final state.
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::cleanPath(unsigned int ulId, unsigned int pId) {
|
|
// cout << "cleanPaths called, ul " << ulId << ", pE " << pId << endl;
|
|
if (matching[ulId][pId].empty()) {
|
|
return false;
|
|
}
|
|
if (*(matching[ulId][pId].begin()) == UINT_MAX) {
|
|
return true;
|
|
}
|
|
bool result = false;
|
|
std::set<unsigned int>::iterator it;
|
|
std::vector<unsigned int> toDelete;
|
|
for (it = matching[ulId][pId].begin(); it != matching[ulId][pId].end(); it++){
|
|
if (cleanPath(ulId + 1, *it)) {
|
|
result = true;
|
|
}
|
|
else {
|
|
toDelete.push_back(*it);
|
|
}
|
|
}
|
|
for (unsigned int i = 0; i < toDelete.size(); i++) {
|
|
matching[ulId][pId].erase(toDelete[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~easyCondsMatch~}
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::easyCondsMatch(int ulId, PatElem const &elem,
|
|
std::vector<Condition> &easyConds,
|
|
std::set<int> pos) {
|
|
if (elem.getW() || pos.empty() || easyConds.empty()) {
|
|
return true;
|
|
}
|
|
std::vector<int> binding;
|
|
IndexMatchInfo imi(binding);
|
|
std::string var;
|
|
elem.getV(var);
|
|
int elemPos = p->getElemFromVar(var);
|
|
imi.set(elemPos - 1, ulId - 1);
|
|
imi.set(elemPos, ulId);
|
|
std::map<std::string, int> varToElem = p->getVarToElem();
|
|
for (std::set<int>::iterator it = pos.begin(); it != pos.end(); it++) {
|
|
if (!easyConds[*it].evaluate<M>(imi, m, varToElem)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~conditionsMatch~}
|
|
|
|
Checks whether the specified conditions are fulfilled. The result is true if
|
|
and only if there is (at least) one binding that matches every condition.
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::conditionsMatch(std::vector<Condition> &conds,
|
|
const IndexMatchInfo &imi) {
|
|
if (!m->GetNoComponents()) { // empty MLabel
|
|
return evaluateEmptyM();
|
|
}
|
|
std::map<std::string, int> varToElem = p->getVarToElem();
|
|
for (unsigned int i = 0; i < conds.size(); i++) {
|
|
if (!conds[i].evaluate<M>(imi, m, varToElem)) {
|
|
// cout << conds[i].getText() << " | ";
|
|
// Tools::printBinding(binding);
|
|
return false;
|
|
}
|
|
}
|
|
// cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!! MATCH" << endl;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~evaluateEmptyML~}
|
|
|
|
This function is invoked in case of an empty moving label (i.e., with 0
|
|
components). A match is possible for a pattern like 'X [*] Y [*]' and conditions
|
|
X.card = 0, X.card = Y.card [*] 7. Time or label constraints are invalid.
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::evaluateEmptyM() {
|
|
Word res;
|
|
for (unsigned int i = 0; i < p->conds.size(); i++) {
|
|
for (int j = 0; j < p->conds[i].getVarKeysSize(); j++) {
|
|
if (p->conds[i].getKey(j) != 4) { // only card conditions possible
|
|
cout << "Error: Only cardinality conditions allowed" << endl;
|
|
return false;
|
|
}
|
|
p->conds[i].setCardPtr(j, 0);
|
|
}
|
|
p->conds[i].getQP()->EvalS(p->conds[i].getOpTree(), res, OPEN);
|
|
if (!((CcBool*)res.addr)->IsDefined() || !((CcBool*)res.addr)->GetValue()) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~isSensiblyBound~}
|
|
|
|
This function checks whether a variable is bound in a sensible and valid way.
|
|
|
|
*/
|
|
template<class M>
|
|
bool Match<M>::isSensiblyBound(const std::map<std::string,
|
|
std::pair<int, int> > &b,
|
|
std::string& var) {
|
|
int first = b.find(var)->second.first;
|
|
int second = b.find(var)->second.second;
|
|
return (first >= 0 && first < m->GetNoComponents() &&
|
|
second >= 0 && second < m->GetNoComponents() && first <= second);
|
|
}
|
|
|
|
/*
|
|
\subsection{Constructors for class ~FilterMatchesLI~}
|
|
|
|
*/
|
|
template<class M>
|
|
FilterMatchesLI<M>::FilterMatchesLI(Word _stream, int _attrIndex,
|
|
std::string& pText)
|
|
: stream(_stream), attrIndex(_attrIndex), match(0),
|
|
streamOpen(false), deleteP(true) {
|
|
Pattern *p = Pattern::getPattern(pText, false);
|
|
if (p) {
|
|
if (p->isValid(M::BasicType())) {
|
|
match = new Match<M>(p, 0);
|
|
stream.open();
|
|
streamOpen = true;
|
|
}
|
|
else {
|
|
cout << "pattern is not suitable for type " << M::BasicType() << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Destructor for class ~FilterMatchesLI~}
|
|
|
|
*/
|
|
template<class M>
|
|
FilterMatchesLI<M>::~FilterMatchesLI() {
|
|
if (match) {
|
|
if (deleteP) {
|
|
match->deletePattern();
|
|
}
|
|
delete match;
|
|
match = 0;
|
|
}
|
|
if (streamOpen) {
|
|
stream.close();
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~getNextResult~}
|
|
|
|
*/
|
|
template<class M>
|
|
Tuple* FilterMatchesLI<M>::getNextResult() {
|
|
if (!match) {
|
|
return 0;
|
|
}
|
|
Tuple* cand = stream.request();
|
|
while (cand) {
|
|
match->setM((M*)cand->GetAttribute(attrIndex));
|
|
if (match->matches() == ST_TRUE) {
|
|
return cand;
|
|
}
|
|
cand->DeleteIfAllowed();
|
|
cand = stream.request();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template<class M>
|
|
RewriteLI<M>::RewriteLI(M *src, Pattern *pat) {
|
|
if (pat->isValid(M::BasicType())) {
|
|
match = new Match<M>(pat, src);
|
|
if (match->matches()) {
|
|
if (match->initCondOpTrees() && match->initAssignOpTrees()) {
|
|
if (!src->GetNoComponents()) {
|
|
BindingStackElem dummy(0, 0);
|
|
bindingStack.push(dummy);
|
|
}
|
|
else {
|
|
std::map<int, int> transitions = pat->getTransitions(0);
|
|
for (std::map<int, int>::iterator itm = transitions.begin();
|
|
itm != transitions.end(); itm++) {
|
|
BindingStackElem bE(0, itm->first); // init stack
|
|
bindingStack.push(bE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
cout << "pattern is not suitable for type " << MLabel::BasicType() << endl;
|
|
match = 0;
|
|
}
|
|
}
|
|
|
|
template<class M>
|
|
void RewriteLI<M>::clearMatch(const bool removePattern) {
|
|
if (match) {
|
|
if (removePattern) {
|
|
match->deletePattern();
|
|
}
|
|
match->deleteSetMatrix();
|
|
delete match;
|
|
match = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~rewrite~}
|
|
|
|
*/
|
|
template<class M>
|
|
M* RewriteLI<M>::rewrite(M *src, IndexMatchInfo &imi,
|
|
std::vector<Assign> &assigns) {
|
|
Pattern *p = match->getPattern();
|
|
M *result = new M(true);
|
|
Word qResult;
|
|
Instant start(datetime::instanttype), end(datetime::instanttype);
|
|
temporalalgebra::SecInterval iv(true), iv2(true);
|
|
bool lc(false), rc(false);
|
|
int elem = -1;
|
|
std::pair<unsigned int, unsigned int> segment;
|
|
assert(src->IsValid());
|
|
for (unsigned int i = 0; i < assigns.size(); i++) {
|
|
for (int j = 0; j <= 9; j++) {
|
|
if (!assigns[i].getText(j).empty()) {
|
|
for (int k = 0; k < assigns[i].getRightSize(j); k++) {
|
|
elem = p->getElemFromVar(assigns[i].getRightVar(j, k));
|
|
if (imi.getTo(elem) > -1) {
|
|
segment.first = imi.getFrom(elem);
|
|
segment.second = imi.getTo(elem);
|
|
switch (assigns[i].getRightKey(j, k)) {
|
|
case 0: { // label
|
|
std::string lvalue;
|
|
((MLabel*)src)->GetValue(segment.first, lvalue);
|
|
assigns[i].setLabelPtr(k, lvalue);
|
|
break;
|
|
}
|
|
case 1: { // place
|
|
std::pair<std::string, unsigned int> pvalue;
|
|
((MPlace*)src)->GetValue(segment.first, pvalue);
|
|
assigns[i].setPlacePtr(k, pvalue);
|
|
break;
|
|
}
|
|
case 2: { // time
|
|
src->GetInterval(segment.first, iv);
|
|
src->GetInterval(segment.second, iv2);
|
|
iv.end = iv2.end;
|
|
iv.rc = iv2.rc;
|
|
assigns[i].setTimePtr(k, iv);
|
|
break;
|
|
}
|
|
case 3: { // start
|
|
src->GetInterval(segment.first, iv);
|
|
if (j == 3) {
|
|
assigns[i].setStartPtr(k, iv.start);
|
|
}
|
|
else {
|
|
assigns[i].setEndPtr(k, iv.start);
|
|
}
|
|
break;
|
|
}
|
|
case 4: { // end
|
|
src->GetInterval(segment.second, iv);
|
|
if (j == 3) {
|
|
assigns[i].setStartPtr(k, iv.end);
|
|
}
|
|
else {
|
|
assigns[i].setEndPtr(k, iv.end);
|
|
}
|
|
break;
|
|
}
|
|
case 5: { // leftclosed
|
|
src->GetInterval(segment.first, iv);
|
|
if (j == 5) {
|
|
assigns[i].setLeftclosedPtr(k, iv.lc);
|
|
}
|
|
else {
|
|
assigns[i].setRightclosedPtr(k, iv.lc);
|
|
}
|
|
break;
|
|
}
|
|
case 6: { // rightclosed
|
|
src->GetInterval(segment.second, iv);
|
|
if (j == 5) {
|
|
assigns[i].setLeftclosedPtr(k, iv.rc);
|
|
}
|
|
else {
|
|
assigns[i].setRightclosedPtr(k, iv.rc);
|
|
}
|
|
break;
|
|
}
|
|
case 8: { // labels
|
|
std::set<Labels::base> lvalues;
|
|
for (unsigned int m = segment.first; m <= segment.second; m++) {
|
|
((MLabels*)src)->GetValues(m, lvalues);
|
|
assigns[i].appendToLabelsPtr(k, lvalues);
|
|
}
|
|
break;
|
|
}
|
|
case 9: { // places
|
|
std::set<Places::base> pvalues;
|
|
for (unsigned int m = segment.first; m <= segment.second; m++) {
|
|
((MPlaces*)src)->GetValues(m, pvalues);
|
|
assigns[i].appendToPlacesPtr(k, pvalues);
|
|
}
|
|
break;
|
|
}
|
|
default: { // cannot occur
|
|
cout << "Error: assigns[" << i << "].getRightKey(" << j << ", "
|
|
<< k << ") = " << assigns[i].getRightKey(j, k) << endl;
|
|
result->SetDefined(false);
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
else { // variable from right size unbound
|
|
result->SetDefined(false);
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
} // all pointers are set now
|
|
Label lb(true);
|
|
if (!assigns[i].getText(0).empty()) {
|
|
assigns[i].getQP(0)->EvalS(assigns[i].getOpTree(0), qResult, OPEN);
|
|
lb = *((Label*)qResult.addr);
|
|
}
|
|
Place pl(true);
|
|
if (!assigns[i].getText(1).empty()) {
|
|
assigns[i].getQP(1)->EvalS(assigns[i].getOpTree(1), qResult, OPEN);
|
|
pl = *((Place*)qResult.addr);
|
|
}
|
|
if (!assigns[i].getText(2).empty()) {
|
|
assigns[i].getQP(2)->EvalS(assigns[i].getOpTree(2), qResult, OPEN);
|
|
iv2 = *((temporalalgebra::SecInterval*)qResult.addr);
|
|
}
|
|
if (!assigns[i].getText(3).empty()) {
|
|
assigns[i].getQP(3)->EvalS(assigns[i].getOpTree(3), qResult, OPEN);
|
|
start = *((Instant*)qResult.addr);
|
|
}
|
|
if (!assigns[i].getText(3).empty()) {
|
|
assigns[i].getQP(4)->EvalS(assigns[i].getOpTree(4), qResult, OPEN);
|
|
end = *((Instant*)qResult.addr);
|
|
}
|
|
if (!assigns[i].getText(5).empty()) {
|
|
assigns[i].getQP(5)->EvalS(assigns[i].getOpTree(5), qResult, OPEN);
|
|
lc = ((CcBool*)qResult.addr)->GetValue();
|
|
}
|
|
if (!assigns[i].getText(6).empty()) {
|
|
assigns[i].getQP(6)->EvalS(assigns[i].getOpTree(6), qResult, OPEN);
|
|
rc = ((CcBool*)qResult.addr)->GetValue();
|
|
}
|
|
Labels lbs(true);
|
|
if (!assigns[i].getText(8).empty()) {
|
|
assigns[i].getQP(8)->EvalS(assigns[i].getOpTree(8), qResult, OPEN);
|
|
lbs = *((Labels*)qResult.addr);
|
|
}
|
|
Places pls(true);
|
|
if (!assigns[i].getText(9).empty()) {
|
|
assigns[i].getQP(9)->EvalS(assigns[i].getOpTree(9), qResult, OPEN);
|
|
pls = *((Places*)qResult.addr);
|
|
}
|
|
// information from assignment i collected
|
|
elem = p->getElemFromVar(assigns[i].getV());
|
|
if (imi.getTo(elem) > -1) { // var occurs
|
|
segment.first = imi.getFrom(elem);
|
|
segment.second = imi.getTo(elem);
|
|
if (segment.second == segment.first) { // 1 source ul
|
|
src->GetInterval(segment.first, iv);
|
|
if (!assigns[i].getText(2).empty()) {
|
|
iv = iv2;
|
|
}
|
|
if (!assigns[i].getText(3).empty()) {
|
|
iv.start = start;
|
|
}
|
|
if (!assigns[i].getText(4).empty()) {
|
|
iv.end = end;
|
|
}
|
|
if (!assigns[i].getText(5).empty()) {
|
|
iv.lc = lc;
|
|
}
|
|
if (!assigns[i].getText(6).empty()) {
|
|
iv.rc = rc;
|
|
}
|
|
if (!iv.IsValid()) {
|
|
iv.Print(cout);
|
|
cout << " is an invalid interval" << endl;
|
|
result->SetDefined(false);
|
|
return result;
|
|
}
|
|
if (M::BasicType() == MLabel::BasicType()) {
|
|
if (!assigns[i].getQP(0)) {
|
|
std::string lvalue;
|
|
((MLabel*)src)->GetValue(segment.first, lvalue);
|
|
((MLabel*)result)->Add(iv, lvalue);
|
|
}
|
|
else {
|
|
((MLabel*)result)->Add(iv, lb);
|
|
}
|
|
}
|
|
else if (M::BasicType() == MPlace::BasicType()) {
|
|
if (!assigns[i].getQP(1)) {
|
|
std::pair<std::string, unsigned int> pvalue;
|
|
((MPlace*)src)->GetValue(segment.first, pvalue);
|
|
((MPlace*)result)->Add(iv, pvalue);
|
|
}
|
|
else {
|
|
((MPlace*)result)->Add(iv, pl);
|
|
}
|
|
}
|
|
else if (M::BasicType() == MLabels::BasicType()) {
|
|
if (!assigns[i].getQP(8)) {
|
|
((MLabels*)src)->GetBasics(segment.first, lbs);
|
|
}
|
|
((MLabels*)result)->Add(iv, lbs);
|
|
}
|
|
else if (M::BasicType() == MPlaces::BasicType()) {
|
|
if (!assigns[i].getQP(9)) {
|
|
((MPlaces*)src)->GetBasics(segment.first, pls);
|
|
}
|
|
((MPlaces*)result)->Add(iv, pls);
|
|
}
|
|
}
|
|
else { // arbitrary many source uls
|
|
for (unsigned int m = segment.first; m <= segment.second; m++) {
|
|
src->GetInterval(m, iv);
|
|
if ((m == segment.first) && // first unit label
|
|
(!assigns[i].getText(2).empty() || !assigns[i].getText(3).empty())){
|
|
iv.start = start;
|
|
}
|
|
if ((m == segment.second) && // last unit label
|
|
(!assigns[i].getText(2).empty() || !assigns[i].getText(4).empty())){
|
|
iv.end = end;
|
|
}
|
|
if ((m == segment.first) && !assigns[i].getText(5).empty()) {
|
|
iv.lc = lc;
|
|
}
|
|
if ((m == segment.second) && !assigns[i].getText(6).empty()) {
|
|
iv.rc = rc;
|
|
}
|
|
if (!iv.IsValid()) {
|
|
iv.Print(cout);
|
|
cout << " is an invalid interval" << endl;
|
|
result->SetDefined(false);
|
|
return result;
|
|
}
|
|
if (M::BasicType() == "mlabel") {
|
|
Label lb(true);
|
|
((MLabel*)src)->GetBasic(m, lb);
|
|
((MLabel*)result)->Add(iv, lb);
|
|
}
|
|
else if (M::BasicType() == "mplace") {
|
|
Place pl(true);
|
|
((MPlace*)src)->GetBasic(m, pl);
|
|
((MPlace*)result)->Add(iv, pl);
|
|
}
|
|
if (!assigns[i].getText(8).empty()) {
|
|
((MLabels*)result)->Add(iv, lbs);
|
|
}
|
|
if (!assigns[i].getText(9).empty()) {
|
|
((MPlaces*)result)->Add(iv, pls);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else { // variable does not occur in binding
|
|
if (!assigns[i].occurs()) { // and not in pattern
|
|
if (!assigns[i].getText(2).empty()) {
|
|
iv = iv2;
|
|
}
|
|
else {
|
|
iv.start = start;
|
|
iv.end = end;
|
|
}
|
|
if (!assigns[i].getText(5).empty()) {
|
|
iv.lc = lc;
|
|
}
|
|
if (!assigns[i].getText(6).empty()) {
|
|
iv.rc = rc;
|
|
}
|
|
if (!assigns[i].getText(0).empty()) {
|
|
((MLabel*)result)->Add(iv, lb);
|
|
}
|
|
if (!assigns[i].getText(1).empty()) {
|
|
((MPlace*)result)->Add(iv, pl);
|
|
}
|
|
if (!assigns[i].getText(8).empty()) {
|
|
((MLabels*)result)->Add(iv, lbs);
|
|
}
|
|
if (!assigns[i].getText(9).empty()) {
|
|
((MPlaces*)result)->Add(iv, pls);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// assert(result->IsValid());
|
|
if (!result->IsValid()) {
|
|
result->SetDefined(false);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template<class M>
|
|
M* RewriteLI<M>::getNextResult() {
|
|
if (!match) {
|
|
return 0;
|
|
}
|
|
if (bindingStack.empty()) {
|
|
return 0;
|
|
}
|
|
M* result = 0;
|
|
if (!match->m->GetNoComponents()) { // empty mlabel
|
|
bindingStack.pop();
|
|
std::vector<Condition> *conds = match->p->getConds();
|
|
if (match->conditionsMatch(*conds, imi)) {
|
|
M *source = match->m;
|
|
result = rewrite(source, imi, match->p->getAssigns());
|
|
}
|
|
}
|
|
else { // non-empty mlabel
|
|
BindingStackElem bE(0, 0);
|
|
while (!bindingStack.empty()) {
|
|
bE = bindingStack.top();
|
|
bindingStack.pop();
|
|
resetBinding(bE.ulId);
|
|
if (findNextBinding(bE.ulId, bE.peId, match->p, 0)) {
|
|
if (rewBindings.find(imi) == rewBindings.end()) {
|
|
// cout << "FOUND and INSERTED: ";
|
|
// imi.print(true);
|
|
rewBindings.insert(imi);
|
|
M *source = match->m;
|
|
result = rewrite(source, imi, match->p->getAssigns());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
match->deleteSetMatrix();
|
|
return result;
|
|
}
|
|
|
|
template<class M>
|
|
void RewriteLI<M>::resetBinding(int limit) {
|
|
if (limit == 0) {
|
|
imi.binding.clear();
|
|
return;
|
|
}
|
|
bool found = false;
|
|
unsigned int pos = 0;
|
|
while (pos < imi.binding.size() && !found) {
|
|
if (imi.getTo(pos) >= limit) {
|
|
imi.set(pos, limit - 1);
|
|
found = true;
|
|
for (unsigned int j = pos + 1; j < imi.binding.size(); pos++) {
|
|
imi.binding.pop_back();
|
|
}
|
|
}
|
|
pos++;
|
|
}
|
|
}
|
|
|
|
template<class M>
|
|
bool RewriteLI<M>::findNextBinding(unsigned int ulId, unsigned int peId,
|
|
Pattern *p, int offset) {
|
|
// std::string var = p->getVarFromElem(peId - offset);
|
|
imi.set(peId - offset, ulId);
|
|
if (*(match->matching[ulId][peId].begin()) == UINT_MAX) { // complete match
|
|
std::vector<Condition> *conds = p->getConds();
|
|
match->p = p;
|
|
PatElem atom;
|
|
p->getElem(p->get1stAtomFromElem(peId), atom);
|
|
return match->easyCondsMatch(ulId, atom, p->easyConds,
|
|
p->getEasyCondPos(p->get1stAtomFromElem(peId))) &&
|
|
match->conditionsMatch(*conds, imi);
|
|
}
|
|
if (match->matching[ulId][peId].empty()) {
|
|
return false;
|
|
}
|
|
else { // push all elements except the first one to stack; process first elem
|
|
std::set<unsigned int>::reverse_iterator it, it2;
|
|
it2 = match->matching[ulId][peId].rbegin();
|
|
it2++;
|
|
for (it = match->matching[ulId][peId].rbegin();
|
|
it2 != match->matching[ulId][peId].rend(); it++) {
|
|
it2++;
|
|
BindingStackElem bE(ulId + 1, *it);
|
|
bindingStack.push(bE);
|
|
}
|
|
return findNextBinding(ulId + 1, *(match->matching[ulId][peId].begin()), p,
|
|
offset);
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Constructor for class ~ClassifyLI~}
|
|
|
|
This constructor is used for the operator ~classify~.
|
|
|
|
*/
|
|
template<class M>
|
|
ClassifyLI::ClassifyLI(M *traj, Word _classifier) : classifyTT(0) {
|
|
Classifier *c = static_cast<Classifier*>(_classifier.addr);
|
|
int startState(0), pat(0);
|
|
std::set<unsigned int> emptyset;
|
|
std::set<int> states, finalStates, matchCands;
|
|
std::set<int>::iterator it;
|
|
Pattern *p = 0;
|
|
PatElem elem;
|
|
std::vector<PatElem> patElems;
|
|
std::vector<Condition> easyConds;
|
|
std::vector<int> startStates;
|
|
std::map<int, std::set<int> > easyCondPos;
|
|
std::map<int, int> atomicToElem; // TODO: use this sensibly
|
|
std::map<int, std::string> elemToVar; // TODO: use this sensibly
|
|
bool condsOccur = false;
|
|
for (int i = 0; i < c->getCharPosSize() / 2; i++) {
|
|
states.insert(states.end(), startState);
|
|
startStates.push_back(startState);
|
|
p = Pattern::getPattern(c->getPatText(i), true); // single NFA are not built
|
|
if (p) {
|
|
p->setDescr(c->getDesc(i));
|
|
if (p->hasConds()) {
|
|
condsOccur = true;
|
|
}
|
|
pats.push_back(p);
|
|
std::map<int, std::set<int> > easyOld = p->getEasyCondPos();
|
|
for (std::map<int, std::set<int> >::iterator im = easyOld.begin();
|
|
im != easyOld.end(); im++) {
|
|
for (it = im->second.begin(); it != im->second.end(); it++) {
|
|
easyCondPos[im->first+patElems.size()].insert(*it + easyConds.size());
|
|
}
|
|
}
|
|
for (unsigned int j = 0; j < p->getEasyConds().size(); j++) {
|
|
easyConds.push_back(p->getEasyCond(j));
|
|
easyConds.back().initOpTree();
|
|
}
|
|
for (int j = 0; j < p->getSize(); j++) {
|
|
p->getElem(j, elem);
|
|
patElems.push_back(elem);
|
|
}
|
|
do { // get start state
|
|
startState++;
|
|
c->s2p.Get(startState, pat);
|
|
} while ((i < c->getCharPosSize() / 2 - 1) && (pat >= 0));
|
|
}
|
|
else {
|
|
cout << "pattern could not be parsed" << endl;
|
|
}
|
|
}
|
|
if (!pats.size()) {
|
|
cout << "no classification data specified" << endl;
|
|
return;
|
|
}
|
|
std::vector<std::map<int, int> > nfa;
|
|
Tools::createNFAfromPersistent(c->delta, c->s2p, nfa, finalStates);
|
|
Match<M> *match = new Match<M>(0, traj);
|
|
if (condsOccur) {
|
|
match->createSetMatrix(traj->GetNoComponents(), patElems.size());
|
|
}
|
|
for (int i = 0; i < traj->GetNoComponents(); i++) {
|
|
if (!match->updateStates(i, nfa, patElems, finalStates, states, easyConds,
|
|
easyCondPos, atomicToElem, condsOccur)){
|
|
for (unsigned int j = 0; j < easyConds.size(); j++) {
|
|
easyConds[j].deleteOpTree();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
for (unsigned int j = 0; j < easyConds.size(); j++) {
|
|
easyConds[j].deleteOpTree();
|
|
}
|
|
for (it = states.begin(); it != states.end(); it++) { // active states final?
|
|
c->s2p.Get(*it, pat);
|
|
if ((*it > 0) && (pat != INT_MAX) && (pat >= 0)) {
|
|
matchCands.insert(matchCands.end(), pat);
|
|
// cout << "pattern " << pat << " matches" << endl;
|
|
}
|
|
}
|
|
for (it = matchCands.begin(); it != matchCands.end(); it++) { // check conds
|
|
pats[*it]->initCondOpTrees();
|
|
std::vector<Condition>* conds = pats[*it]->getConds();
|
|
// cout << "call fMB(nfa, " << startStates[*it] << ", " << patElems.size()
|
|
// << ", " << conds->size() << ")" << endl;
|
|
if (match->findMatchingBinding(nfa, startStates[*it], patElems, *conds,
|
|
atomicToElem, elemToVar)) {
|
|
matchingPats.insert(*it);
|
|
// cout << "p " << *it << " matches after condition check" << endl;
|
|
}
|
|
else {
|
|
// cout << "p " << *it << " has non-matching conditions" << endl;
|
|
}
|
|
pats[*it]->deleteCondOpTrees();
|
|
}
|
|
match->deleteSetMatrix();
|
|
delete match;
|
|
}
|
|
|
|
/*
|
|
\subsection{Constructor for class ~MultiRewriteLI~}
|
|
|
|
This constructor is used for the operator ~rewrite~.
|
|
|
|
*/
|
|
template<class M>
|
|
MultiRewriteLI<M>::MultiRewriteLI(Word _tstream, Word _pstream, int _pos) :
|
|
ClassifyLI(0), RewriteLI<M>(0), tStream(_tstream), attrpos(_pos),
|
|
streamOpen(false), traj(0), c(0) {
|
|
Stream<FText> pStream(_pstream);
|
|
pStream.open();
|
|
FText* inputText = pStream.request();
|
|
Pattern *p = 0;
|
|
PatElem elem;
|
|
std::set<int>::iterator it;
|
|
std::map<int, std::set<int> >::iterator im;
|
|
int elemCount(0);
|
|
std::string var;
|
|
while (inputText) {
|
|
if (!inputText->IsDefined()) {
|
|
cout << "undefined input is ignored" << endl;
|
|
}
|
|
else {
|
|
p = Pattern::getPattern(inputText->GetValue(), true); // no single NFA
|
|
if (p) {
|
|
if (!p->hasAssigns()) {
|
|
cout << "pattern without rewrite part ignored" << endl;
|
|
}
|
|
else {
|
|
if (p->initCondOpTrees()) {
|
|
p->initAssignOpTrees();
|
|
pats.push_back(p);
|
|
for (int i = 0; i < p->getSize(); i++) {
|
|
atomicToElem[patElems.size()] = elemCount + p->getElemFromAtom(i);
|
|
p->getElem(i, elem);
|
|
elem.getV(var);
|
|
elemToVar[elemCount+p->getElemFromAtom(i)] = var;
|
|
varToElem[var] = elemCount+p->getElemFromAtom(i);
|
|
patElems.push_back(elem);
|
|
patOffset[elemCount + p->getElemFromAtom(i)] =
|
|
std::make_pair(pats.size() - 1, elemCount);
|
|
}
|
|
elemCount += p->getElemFromAtom(p->getSize() - 1) + 1;
|
|
std::map<int, std::set<int> > easyOld = p->getEasyCondPos();
|
|
for (im = easyOld.begin(); im != easyOld.end(); im++) {
|
|
for (it = im->second.begin(); it != im->second.end(); it++) {
|
|
easyCondPos[im->first + patElems.size()].insert
|
|
(*it + easyConds.size());
|
|
}
|
|
}
|
|
for (unsigned int j = 0; j < p->getEasyConds().size(); j++) {
|
|
easyConds.push_back(p->getEasyCond(j));
|
|
easyConds.back().initOpTree();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
inputText->DeleteIfAllowed();
|
|
inputText = pStream.request();
|
|
}
|
|
pStream.close();
|
|
if (!pats.size()) {
|
|
cout << "no classification data specified" << endl;
|
|
}
|
|
else {
|
|
tStream.open();
|
|
streamOpen = true;
|
|
Classifier *c = new Classifier(0);
|
|
c->buildMultiNFA(pats, nfa, finalStates, state2Pat);
|
|
c->getStartStates(states);
|
|
this->match = new Match<M>(0, traj);
|
|
c->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
\subsection{Function ~nextResult~}
|
|
|
|
This function is used for the operator ~multirewrite~.
|
|
|
|
*/
|
|
template<class M>
|
|
M* MultiRewriteLI<M>::nextResult() {
|
|
if (!pats.size()) {
|
|
return 0;
|
|
}
|
|
std::set<int> startStates;
|
|
std::set<int>::iterator it;
|
|
while (!this->bindingStack.empty()) {
|
|
BindingStackElem bE(0, 0);
|
|
bE = this->bindingStack.top();
|
|
// cout << "take (" << bE.ulId << ", " << bE.pId << ") from stack" << endl;
|
|
this->bindingStack.pop();
|
|
this->resetBinding(bE.ulId);
|
|
std::pair<int, int> patNo = patOffset[bE.peId];
|
|
if (this->findNextBinding(bE.ulId, bE.peId, pats[patNo.first],
|
|
patNo.second)) {
|
|
return RewriteLI<M>::rewrite(traj, this->imi,
|
|
pats[patNo.first]->getAssigns());
|
|
}
|
|
}
|
|
Tuple *tuple = 0;
|
|
while (this->bindingStack.empty()) { // new ML from stream necessary
|
|
this->match->deleteSetMatrix();
|
|
delete this->match;
|
|
this->match = 0;
|
|
deleteIfAllowed(traj);
|
|
tuple = tStream.request();
|
|
if (!tuple) {
|
|
return 0;
|
|
}
|
|
traj = (M*)(tuple->GetAttribute(attrpos))->Copy();
|
|
this->match = new Match<M>(0, traj);
|
|
this->match->createSetMatrix(traj->GetNoComponents(), patElems.size());
|
|
getStartStates(startStates);
|
|
states = startStates;
|
|
matchCands.clear();
|
|
int i = 0;
|
|
while (!states.empty() && (i < traj->GetNoComponents())) { // loop over traj
|
|
this->match->updateStates(i, nfa, patElems, finalStates, states,
|
|
easyConds, easyCondPos, atomicToElem, true);
|
|
i++;
|
|
}
|
|
for (it = states.begin(); it != states.end(); it++) { //active states final?
|
|
if (finalStates.count(*it)) {
|
|
matchCands.insert(matchCands.end(), state2Pat[*it]);
|
|
}
|
|
}
|
|
initStack(startStates);
|
|
tuple->DeleteIfAllowed();
|
|
tuple = 0;
|
|
while (!this->bindingStack.empty()) {
|
|
BindingStackElem bE(0, 0);
|
|
bE = this->bindingStack.top();
|
|
// cout << "take (" << bE.ulId << ", " << bE.pId << ") from stack" << endl;
|
|
this->bindingStack.pop();
|
|
this->resetBinding(bE.ulId);
|
|
std::pair<int, int> patNo = patOffset[bE.peId];
|
|
pats[patNo.first]->setVarToElem(varToElem);
|
|
if (this->findNextBinding(bE.ulId, bE.peId, pats[patNo.first],
|
|
patNo.second)) {
|
|
return RewriteLI<M>::rewrite(traj, this->imi,
|
|
pats[patNo.first]->getAssigns());
|
|
}
|
|
}
|
|
}
|
|
cout << "SHOULD NOT OCCUR" << endl;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~initStack~}
|
|
|
|
Determines the start states of the match candidate patterns and pushes the
|
|
corresponding initial transitions onto the stack.
|
|
|
|
*/
|
|
template<class M>
|
|
void MultiRewriteLI<M>::initStack(std::set<int> &startStates) {
|
|
std::set<int>::iterator it;
|
|
std::map<int, int>::iterator itm;
|
|
for (it = startStates.begin(); it != startStates.end(); it++) {
|
|
if (matchCands.count(-state2Pat[*it])) {
|
|
std::map<int, int> transitions = nfa[*it];
|
|
for (itm = transitions.begin(); itm != transitions.end(); itm++) {
|
|
BindingStackElem bE(0, atomicToElem[itm->first]);
|
|
this->bindingStack.push(bE);
|
|
// cout << "(0, " << itm->first << ") pushed onto stack" << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~getStartStates~}
|
|
|
|
*/
|
|
template<class M>
|
|
void MultiRewriteLI<M>::getStartStates(std::set<int> &states) {
|
|
states.clear();
|
|
states.insert(0);
|
|
std::map<int, int>::iterator it;
|
|
for (it = state2Pat.begin(); it != state2Pat.end(); it++) {
|
|
if (it->second < 0) {
|
|
states.insert(it->first);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Destructor for class ~MultiRewriteLI~}
|
|
|
|
*/
|
|
template<class M>
|
|
MultiRewriteLI<M>::~MultiRewriteLI() {
|
|
for (unsigned int i = 0; i < pats.size(); i++) {
|
|
if (pats[i]) {
|
|
pats[i]->deleteCondOpTrees();
|
|
delete pats[i];
|
|
pats[i] = 0;
|
|
}
|
|
}
|
|
if (this->match) {
|
|
this->match->deleteSetMatrix();
|
|
delete this->match;
|
|
}
|
|
this->match = 0;
|
|
if (traj) {
|
|
deleteIfAllowed(traj);
|
|
}
|
|
traj = 0;
|
|
if (streamOpen) {
|
|
tStream.close();
|
|
}
|
|
for (unsigned int i = 0; i < easyConds.size(); i++) {
|
|
easyConds[i].deleteOpTree();
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~nextResultTuple~}
|
|
|
|
*/
|
|
template<class M>
|
|
Tuple* IndexClassifyLI::nextResultTuple() {
|
|
if (c == 0) {
|
|
return 0;
|
|
}
|
|
while (results.empty()) {
|
|
if (currentPat >= c->getNumOfP()) {
|
|
return 0;
|
|
}
|
|
cout << "results empty, fill now. currentPat=" << currentPat << ", "
|
|
<< c->getPatText(currentPat) << endl;
|
|
Pattern *pat = Pattern::getPattern(c->getPatText(currentPat), false);
|
|
p = pat;
|
|
delete pat;
|
|
initialize();
|
|
applyNFA();
|
|
for (unsigned int i = 0; i < matches.size(); i++) {
|
|
results.push(std::make_pair(c->getDesc(currentPat), matches[i]));
|
|
}
|
|
p->deleteCondOpTrees();
|
|
cout << "desc for " << currentPat << " is " << c->getDesc(currentPat)<<endl;
|
|
currentPat++;
|
|
}
|
|
std::pair<std::string, TupleId> resultPair = results.front();
|
|
results.pop();
|
|
cout << "tuple id " << resultPair.second << " popped, " << results.size()
|
|
<< " left" << endl;
|
|
|
|
Tuple* tuple = rel->GetTuple(resultPair.second, false);
|
|
int noValues = ((MLabels*)(tuple->GetAttribute(attrNo)))->GetNoValues();
|
|
cout << "Trajectory has "
|
|
<< ((MLabels*)(tuple->GetAttribute(attrNo)))->GetNoComponents()
|
|
<< " units and " << noValues << " labels" << endl;
|
|
|
|
((MLabels*)(tuple->GetAttribute(attrNo)))->Print(cout);
|
|
Attribute* traj = (tuple->GetAttribute(attrNo))->Copy();
|
|
Tuple *result = new Tuple(classifyTT);
|
|
result->PutAttribute(0, new FText(true, resultPair.first));
|
|
result->PutAttribute(1, traj);
|
|
deleteIfAllowed(tuple);
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~imiMatch~}
|
|
|
|
*/
|
|
template<class M>
|
|
bool IndexMatchesLI::imiMatch(Match<M>& match, const int e, const TupleId id,
|
|
IndexMatchInfo& imi, const int unit, const int newState) {
|
|
PatElem elem;
|
|
p->getElem(e, elem);
|
|
if (unit >= 0) { // exact position from index
|
|
// cout << " unit=" << unit << ", imi: next=" << imi.next << ", range="
|
|
// << (imi.range ? "TRUE" : "FALSE") << endl;
|
|
if (imi.matches(unit) && match.valuesMatch(unit, elem) &&
|
|
timesMatch(id, unit, elem) &&
|
|
match.easyCondsMatch(unit, elem, p->easyConds, p->getEasyCondPos(e))) {
|
|
if (unit + 1 >= unitCtr) {
|
|
IndexMatchInfo newIMI(false, unit + 1, imi.binding, imi.prevElem);
|
|
extendBinding(newIMI, e, false);
|
|
// if (newIMI.finished(trajSize[id])) {
|
|
// newIMI.print(true); cout << " ";
|
|
// }
|
|
if (p->isFinalState(newState) && newIMI.finished(trajSize[id]) &&
|
|
checkConditions(id, newIMI)) { // complete match
|
|
removeIdFromIndexResult(id, true);
|
|
removeIdFromMatchInfo(id);
|
|
// cout << id << " removed (index match) " << activeTuples
|
|
// << " active tuples" << endl;
|
|
matches.push_back(id);
|
|
return true;
|
|
}
|
|
else if (!newIMI.exhausted(trajSize[id])) { // continue
|
|
newMatchInfo[newState][id]->imis.push_back(newIMI);
|
|
// cout << " IMI pushed back for new state " << newState
|
|
// << " and id " << id << endl;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
if (imi.range) {
|
|
bool result = false;
|
|
int numOfNewIMIs = 0;
|
|
for (int i = imi.next; i < trajSize[id]; i++) {
|
|
if (match.valuesMatch(i, elem) && timesMatch(id, i, elem) &&
|
|
match.easyCondsMatch(i, elem, p->easyConds, p->getEasyCondPos(e))) {
|
|
if (i + 1 >= unitCtr) {
|
|
IndexMatchInfo newIMI(false, i + 1, imi.binding, imi.prevElem);
|
|
extendBinding(newIMI, e, false);
|
|
if (p->isFinalState(newState) && imi.finished(trajSize[id]) &&
|
|
checkConditions(id, newIMI)) { // complete match
|
|
removeIdFromMatchInfo(id);
|
|
// cout << id << " removed (range match) " << activeTuples
|
|
// << " active tuples" << endl;
|
|
removeIdFromIndexResult(id, true);
|
|
matches.push_back(id);
|
|
return true;
|
|
}
|
|
else if (!newIMI.exhausted(trajSize[id])) { // continue
|
|
if (newMatchInfo[newState] == 0) {
|
|
newMatchInfo[newState] = new IndexMatchSlot*[rel->GetNoTuples()];
|
|
memset(newMatchInfo[newState], 0,
|
|
rel->GetNoTuples() * sizeof(void*));
|
|
}
|
|
newMatchInfo[newState][id]->imis.push_back(newIMI);
|
|
numOfNewIMIs++;
|
|
result = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
else {
|
|
if (match.valuesMatch(imi.next, elem) && timesMatch(id, imi.next, elem) &&
|
|
match.easyCondsMatch(imi.next, elem, p->easyConds, p->getEasyCondPos(e))) {
|
|
if (imi.next + 1 >= unitCtr) {
|
|
IndexMatchInfo newIMI(false, imi.next + 1, imi.binding, imi.prevElem);
|
|
extendBinding(newIMI, e, false);
|
|
if (p->isFinalState(newState) && imi.finished(trajSize[id]) &&
|
|
checkConditions(id, newIMI)) { // complete match
|
|
removeIdFromMatchInfo(id);
|
|
// cout << id << " removed (match) " << activeTuples
|
|
// << " active tuples" << endl;
|
|
matches.push_back(id);
|
|
return true;
|
|
}
|
|
else if (!newIMI.exhausted(trajSize[id])) { // continue
|
|
if (newMatchInfo[newState] == 0) {
|
|
newMatchInfo[newState] = new IndexMatchSlot*[rel->GetNoTuples()];
|
|
memset(newMatchInfo[newState], 0,
|
|
rel->GetNoTuples() * sizeof(void*));
|
|
}
|
|
newMatchInfo[newState][id]->imis.push_back(newIMI);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~periodsToUnits~}
|
|
|
|
*/
|
|
template<class M>
|
|
void IndexMatchSuper::periodsToUnits(const temporalalgebra::Periods *per,
|
|
const TupleId tId,
|
|
std::set<int> &units) {
|
|
int start, end;
|
|
temporalalgebra::Interval<Instant> iv;
|
|
Tuple *t = rel->GetTuple(tId, false);
|
|
M *traj = (M*)t->GetAttribute(attrNo);
|
|
for (int i = 0; i < per->GetNoComponents(); i++) {
|
|
per->Get(i, iv);
|
|
start = traj->Position(iv.start);
|
|
end = traj->Position(iv.end);
|
|
if (end > start && !iv.rc) {
|
|
temporalalgebra::SecInterval trajIv;
|
|
traj->GetInterval(end, trajIv);
|
|
if (!trajIv.rc) {
|
|
end--;
|
|
}
|
|
}
|
|
if (start == -1) {
|
|
start = traj->FirstPosFrom(iv.start);
|
|
}
|
|
if (end == -1) {
|
|
end = traj->LastPosUntil(iv.end);
|
|
}
|
|
if (end == start - 1) {
|
|
end++;
|
|
}
|
|
if (start > -1 && end > -1) {
|
|
if (start == -1 && end >= 0) {
|
|
start = 0;
|
|
}
|
|
else if (end == -1 && start >= 0) {
|
|
end = getTrajSize(tId, mtype) - 1;
|
|
}
|
|
for (int j = start; j <= end; j++) {
|
|
units.insert(units.end(), j);
|
|
}
|
|
}
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~getSingleIndexResult~}
|
|
|
|
*/
|
|
template<class ResultType>
|
|
bool TMatchIndexLI::getSingleIndexResult(
|
|
std::pair<int, std::pair<IndexType, int> > indexInfo,
|
|
std::pair<Word, SetRel> values, std::string type, int valueNo,
|
|
std::vector<ResultType> &result) {
|
|
std::string attrType = nl->ToString(nl->Second(nl->Nth(indexInfo.first + 1,
|
|
nl->Second(ttList))));
|
|
switch (indexInfo.second.first) {
|
|
case TRIE: {
|
|
if (values.first.addr == 0) {
|
|
return false; // no content
|
|
}
|
|
if (attrType.substr(0,6) == "mlabel" || attrType.substr(0,6) == "mplace"){
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
if (attrType.substr(0, 6) == "mplace" && sc->IsObjectName("Places") &&
|
|
(type != Labels::BasicType())) {
|
|
Rectangle<2> rect(true);
|
|
if (type == Rectangle<2>::BasicType()) {
|
|
rect.CopyFrom((Rectangle<2>*)(values.first.addr));
|
|
cout << "rect retrieved: ";
|
|
((Rectangle<2>*)(values.first.addr))->Print(cout);
|
|
rect.Print(cout);
|
|
}
|
|
else {
|
|
rect = ((Region*)(values.first.addr))->BoundingBox();
|
|
cout << "bbox of region retrieved: ";
|
|
}
|
|
rect.Print(cout);
|
|
if (ti != 0) {
|
|
Tools::queryRtree2(ti->rtrees2[indexInfo.second.second], rect,
|
|
result);
|
|
}
|
|
else {
|
|
Tools::queryRtree2(ti2->rtrees2[indexInfo.second.second], rect,
|
|
result);
|
|
}
|
|
cout << "rtree queried" << endl;
|
|
return false;
|
|
}
|
|
std::set<std::string> lbs;
|
|
((Labels*)(values.first.addr))->GetValues(lbs);
|
|
if (valueNo == 0 && lbs.empty()) {
|
|
return false; // first access unsuccessful
|
|
}
|
|
std::set<std::string>::iterator it = lbs.begin();
|
|
for (int i = 0; i < valueNo; i++) {
|
|
it++;
|
|
}
|
|
if (ti != 0) {
|
|
Tools::queryTrie(ti->tries[indexInfo.second.second], *it, result);
|
|
}
|
|
else {
|
|
Tools::queryTrie(ti2->tries[indexInfo.second.second], *it, result);
|
|
}
|
|
return (int)(lbs.size()) > valueNo + 1; // TRUE iff there is a successor
|
|
}
|
|
break;
|
|
}
|
|
case BTREE: {
|
|
// cout << "BTREE, type " << type << ", pos " << indexInfo.second.second
|
|
// << endl;
|
|
if (values.first.addr == 0) {
|
|
return false; // no content
|
|
}
|
|
temporalalgebra::Range<CcReal> *range
|
|
= (temporalalgebra::Range<CcReal>*)(values.first.addr);
|
|
temporalalgebra::Interval<CcReal> iv;
|
|
if (valueNo == 0 && range->IsEmpty()) {
|
|
return false; // first access unsuccessful
|
|
}
|
|
range->Get(valueNo, iv);
|
|
if (ti != 0) {
|
|
Tools::queryBtree(ti->btrees[indexInfo.second.second], iv, result);
|
|
}
|
|
else {
|
|
Tools::queryBtree(ti2->btrees[indexInfo.second.second], iv, result);
|
|
}
|
|
// for (unsigned int i = 0; i < result.size(); i++) {
|
|
// cout << "|" << i << ": " << result[i].size() << " ";
|
|
// }
|
|
// cout << endl;
|
|
return range->GetNoComponents() > valueNo + 1;
|
|
}
|
|
case RTREE1: {
|
|
// cout << "RTREE1, type " << type << ", pos " << indexInfo.second.second
|
|
// << endl;
|
|
if (values.first.addr == 0) {
|
|
return false; // no content
|
|
}
|
|
temporalalgebra::Range<CcReal> *range
|
|
= (temporalalgebra::Range<CcReal>*)(values.first.addr);
|
|
temporalalgebra::Interval<CcReal> iv;
|
|
if (valueNo == 0 && range->IsEmpty()) {
|
|
return false; // first access unsuccessful
|
|
}
|
|
range->Get(valueNo, iv);
|
|
if (ti != 0) {
|
|
Tools::queryRtree1(ti->rtrees1[indexInfo.second.second], iv, result);
|
|
}
|
|
else {
|
|
Tools::queryRtree1(ti2->rtrees1[indexInfo.second.second], iv, result);
|
|
}
|
|
// for (unsigned int i = 0; i < result.size(); i++) {
|
|
// cout << "|" << i << ": " << result[i].size() << " ";
|
|
// }
|
|
// cout << endl;
|
|
return range->GetNoComponents() > valueNo + 1;
|
|
}
|
|
case RTREE2: {
|
|
if (values.first.addr == 0) {
|
|
return false; // no content
|
|
}
|
|
Rectangle<2> rect = ((Region*)(values.first.addr))->BoundingBox();
|
|
if (rect.IsEmpty()) {
|
|
return false; // first access unsuccessful
|
|
}
|
|
if (ti != 0) {
|
|
Tools::queryRtree2(ti->rtrees2[indexInfo.second.second], rect, result);
|
|
}
|
|
else {
|
|
Tools::queryRtree2(ti2->rtrees2[indexInfo.second.second], rect, result);
|
|
}
|
|
// for (unsigned int i = 0; i < result.size(); i++) {
|
|
// cout << "|" << i << ": " << result[i].size() << " ";
|
|
// }
|
|
// cout << endl;
|
|
return false;
|
|
}
|
|
default: { // case NONE
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
\subsection{Function ~unitsToPeriods~}
|
|
|
|
*/
|
|
template<class M, class U>
|
|
void TMatchIndexLI::unitsToPeriods(Attribute *traj, const std::set<int> &units,
|
|
temporalalgebra::Periods *per) {
|
|
M *m = (M*)traj;
|
|
temporalalgebra::SecInterval iv(true);
|
|
for (std::set<int>::iterator it = units.begin(); it != units.end(); it++) {
|
|
m->GetInterval(*it, iv);
|
|
per->MergeAdd(iv);
|
|
// cout << "time interval " << u.timeInterval << " added" << endl;
|
|
}
|
|
}
|
|
|
|
/*
|
|
\section{Functions for class ~IndexRewriteLI~}
|
|
|
|
\subsection{Function ~nextResult~}
|
|
|
|
*/
|
|
template<class M>
|
|
M* IndexRewriteLI<M>::nextResult() {
|
|
if (matchesR[0].first == 0 || matchesR[0].first >= matchesR.size() ||
|
|
matchesR.size() <= 1) {
|
|
return 0;
|
|
}
|
|
NewPair<TupleId, IndexMatchInfo> match = matchesR[matchesR[0].first];
|
|
Tuple *srcTuple = rel->GetTuple(match.first, false);
|
|
M *src = (M*)(srcTuple->GetAttribute(attrNo));
|
|
RewriteLI<M> rew(src, p);
|
|
M *result = rew.rewrite(src, match.second, p->getAssigns());
|
|
matchesR[0].first++;
|
|
rew.clearMatch(false);
|
|
srcTuple->DeleteIfAllowed();
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
\section{Implementation of Class ~DeriveGroupsLI~}
|
|
|
|
\subsection{Constructor}
|
|
|
|
*/
|
|
template<class M>
|
|
DeriveGroupsLI<M>::DeriveGroupsLI(Word _stream, double threshold, int attrNo) {
|
|
Stream<Tuple> stream(_stream);
|
|
std::vector<M*> trajStore;
|
|
stream.open();
|
|
Tuple *src = stream.request();
|
|
int noTuples = 0;
|
|
while (src != 0) {
|
|
trajStore.push_back((M*)(src->GetAttribute(attrNo)->Clone()));
|
|
src = stream.request();
|
|
noTuples++;
|
|
}
|
|
stream.close();
|
|
// std::vector<double> dist[noTuples];
|
|
// for (int i = 0; i < noTuples; i++) {
|
|
// for (int j = 0; j < i; j++) {
|
|
// double distance = 0;
|
|
// //double distance = trajStore[i]->Distance(*trajStore[j]);
|
|
// if (distance <= threshold) {
|
|
// dist[i].push_back(j);
|
|
// cout << "pair (" << i << ", " << j << ") found" << endl;
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~getNextTuple~}
|
|
|
|
*/
|
|
template<class M>
|
|
Tuple* DeriveGroupsLI<M>::getNextTuple() {
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
\section{Functions for class ~TupleIndex~}
|
|
|
|
\subsection{auxiliary Functions for Secondo support}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
TupleIndex<PosType, PosType2>::TupleIndex(std::vector<TrieTI*> t,
|
|
std::vector<BTreeTI*> b, std::vector<RTree1TI*> r1, std::vector<RTree2TI*> r2,
|
|
RTree1TI *tI, std::map<int, std::pair<IndexType, int> > aI,
|
|
std::map<std::pair<IndexType, int>, int> iA, int mA, int64_t *fE) {
|
|
tries = t;
|
|
btrees = b;
|
|
rtrees1 = r1;
|
|
rtrees2 = r2;
|
|
timeIndex = tI;
|
|
attrToIndex = aI;
|
|
indexToAttr = iA;
|
|
mainAttr = mA;
|
|
firstEnd = fE;
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
TupleIndex<PosType, PosType2>::TupleIndex(TupleIndex &src) {
|
|
assert(false);
|
|
tries = src.tries;
|
|
btrees = src.btrees;
|
|
rtrees1 = src.rtrees1;
|
|
rtrees2 = src.rtrees2;
|
|
timeIndex = src.timeIndex;
|
|
attrToIndex = src.attrToIndex;
|
|
indexToAttr = src.indexToAttr;
|
|
mainAttr = src.mainAttr;
|
|
firstEnd = src.firstEnd;
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
bool TupleIndex<PosType, PosType2>::checkType(const ListExpr list) {
|
|
return listutils::isSymbol(list, BasicType());
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
ListExpr TupleIndex<PosType, PosType2>::Property() {
|
|
return (nl->TwoElemList(
|
|
nl->FourElemList(
|
|
nl->StringAtom("Signature"), nl->StringAtom("Example Type List"),
|
|
nl->StringAtom("List Rep"), nl->StringAtom("Example List")),
|
|
nl->FourElemList (
|
|
nl->StringAtom("-> SIMPLE"),
|
|
nl->StringAtom(TupleIndex<PosType, PosType2>::BasicType()),
|
|
nl->StringAtom("no list representation"),
|
|
nl->StringAtom(""))));
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
Word TupleIndex<PosType, PosType2>::In(const ListExpr typeInfo,
|
|
const ListExpr instance, const int errorPos,
|
|
ListExpr& errorInfo, bool& correct) {
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
ListExpr TupleIndex<PosType, PosType2>::Out(ListExpr typeInfo, Word value) {
|
|
ListExpr overviewlist, rtree1list, rtree2list, last1, last2;
|
|
overviewlist = rtree1list = rtree2list = last1 = last2 = nl->TheEmptyList();
|
|
TupleIndex<PosType, PosType2> *ti = (TupleIndex<PosType,PosType2>*)value.addr;
|
|
std::stringstream overview;
|
|
Word val;
|
|
overview << ti->tries.size() << " Tries," << endl << ti->btrees.size()
|
|
<< " BTrees," << endl << ti->rtrees1.size() << " 1-dim RTrees,"
|
|
<< endl << ti->rtrees2.size() << " 2-dim RTrees. More:" << endl;
|
|
overviewlist = nl->TextAtom(overview.str());
|
|
cout << overview.str() << endl;
|
|
if (ti->rtrees1.size() > 0) {
|
|
val.addr = ti->rtrees1[0];
|
|
rtree1list = nl->OneElemList(OutRTree<1>(nl->FourElemList(nl->Empty(),
|
|
nl->Empty(), nl->Empty(), nl->BoolAtom(true)), val));
|
|
last1 = rtree1list;
|
|
}
|
|
for (unsigned int i = 1; i < ti->rtrees1.size(); i++) {
|
|
val.addr = ti->rtrees1[i];
|
|
last1 = nl->Append(last1, OutRTree<1>(nl->FourElemList(nl->Empty(),
|
|
nl->Empty(), nl->Empty(), nl->BoolAtom(true)), val));
|
|
}
|
|
if (ti->rtrees2.size() > 0) {
|
|
val.addr = ti->rtrees2[0];
|
|
rtree2list = nl->OneElemList(OutRTree<2>(nl->FourElemList(nl->Empty(),
|
|
nl->Empty(), nl->Empty(), nl->BoolAtom(true)), val));
|
|
last2 = rtree2list;
|
|
}
|
|
for (unsigned int i = 1; i < ti->rtrees2.size(); i++) {
|
|
val.addr = ti->rtrees2[i];
|
|
last2 = nl->Append(last2, OutRTree<2>(nl->FourElemList(nl->Empty(),
|
|
nl->Empty(), nl->Empty(), nl->BoolAtom(true)), val));
|
|
}
|
|
return nl->ThreeElemList(overviewlist, rtree1list, rtree2list);
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
Word TupleIndex<PosType, PosType2>::Create(const ListExpr typeInfo) {
|
|
Word w;
|
|
w.addr = (new TupleIndex<PosType, PosType2>(true));
|
|
return w;
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::Delete(const ListExpr typeInfo, Word& w) {
|
|
TupleIndex<PosType, PosType2> *ti = (TupleIndex<PosType, PosType2>*)w.addr;
|
|
delete ti;
|
|
w.addr = 0;
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
bool TupleIndex<PosType, PosType2>::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value) {
|
|
SecondoCatalog *sc = SecondoSystem::GetCatalog();
|
|
TupleIndex<PosType, PosType2> *ti
|
|
= static_cast<TupleIndex<PosType, PosType2>*>(value.addr);
|
|
unsigned int noComponents = ti->tries.size();
|
|
if (!valueRecord.Write(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
Word val;
|
|
ListExpr tList = sc->NumericType(nl->SymbolAtom(TrieTI::BasicType()));
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
val.addr = ti->tries[i];
|
|
cout << "save trie # " << i + 1 << " of " << noComponents << endl;
|
|
if (!triealg::SaveInvfile<PosType, PosType2>(valueRecord, offset, tList,
|
|
val)) {
|
|
cout << "error saving trie " << i << endl;
|
|
return false;
|
|
}
|
|
}
|
|
noComponents = ti->btrees.size();
|
|
if (!valueRecord.Write(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
tList = sc->NumericType(nl->SymbolAtom(BTreeTI::BasicType()));
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
cout << "save btree # " << i + 1 << " of " << noComponents << endl;
|
|
if (!ti->btrees[i]->Save(valueRecord, offset, tList)) {
|
|
cout << "error saving btree " << i << endl;
|
|
return false;
|
|
}
|
|
}
|
|
noComponents = ti->rtrees1.size();
|
|
if (!valueRecord.Write(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
// tList = nl->FourElemList(nl->Empty(), nl->Empty(), nl->Empty(),
|
|
// nl->BoolAtom(true));
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
// val.addr = ti->rtrees1[i];
|
|
cout << "save rtree1 # " << i + 1 << " of " << noComponents << endl;
|
|
SmiFileId fileId = ti->rtrees1[i]->FileId();
|
|
if (!valueRecord.Write(&fileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
// if (!SaveRTree<1>(valueRecord, offset, tList, val)) {
|
|
// cout << "error saving rtree1 " << i << endl;
|
|
// return false;
|
|
// }
|
|
}
|
|
noComponents = ti->rtrees2.size();
|
|
if (!valueRecord.Write(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
// val.addr = ti->rtrees2[i];
|
|
cout << "save rtree2 # " << i + 1 << " of " << noComponents << endl;
|
|
SmiFileId fileId = ti->rtrees2[i]->FileId();
|
|
if (!valueRecord.Write(&fileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
// if (!SaveRTree<2>(valueRecord, offset, tList, val)) {
|
|
// cout << "error saving rtree2 " << i << endl;
|
|
// return false;
|
|
// }
|
|
}
|
|
// val.addr = ti->timeIndex;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
cout << "save time index" << endl;
|
|
SmiFileId fileId = ti->timeIndex->FileId();
|
|
if (!valueRecord.Write(&fileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
}
|
|
// if (!SaveRTree<1>(valueRecord, offset, tList, val)) {
|
|
// cout << "error saving timeIndex" << endl;
|
|
// return false;
|
|
// }
|
|
noComponents = ti->attrToIndex.size();
|
|
if (!valueRecord.Write(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
std::map<int, std::pair<IndexType, int> >::iterator it1
|
|
= ti->attrToIndex.begin();
|
|
while (it1 != ti->attrToIndex.end()) {
|
|
if (!valueRecord.Write(&it1->first, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Write(&it1->second.first, sizeof(IndexType), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(IndexType);
|
|
if (!valueRecord.Write(&it1->second.second, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
it1++;
|
|
}
|
|
cout << "attrToIndex saved" << endl;
|
|
noComponents = ti->indexToAttr.size();
|
|
if (!valueRecord.Write(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
std::map<std::pair<IndexType, int>, int>::iterator it2
|
|
= ti->indexToAttr.begin();
|
|
while (it2 != ti->indexToAttr.end()) {
|
|
if (!valueRecord.Write(&it2->first.first, sizeof(IndexType), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(IndexType);
|
|
if (!valueRecord.Write(&it2->first.second, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Write(&it2->second, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
it2++;
|
|
}
|
|
cout << "indexToAttr saved" << endl;
|
|
if (!valueRecord.Write(&(ti->mainAttr), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
cout << "mainAttr = " << ti->mainAttr << " saved" << endl;
|
|
offset += sizeof(int);
|
|
noComponents = ti->firstEnd.size();
|
|
if (!valueRecord.Write(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
if (!valueRecord.Write(&(ti->firstEnd[i]), sizeof(int64_t), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int64_t);
|
|
}
|
|
if (noComponents > 0) {
|
|
cout << "first ends for " << noComponents - 1 << " tuples saved" << endl;
|
|
}
|
|
if (!valueRecord.Write(&ti->timeLimits.first, sizeof(int64_t), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int64_t);
|
|
if (!valueRecord.Write(&ti->timeLimits.second, sizeof(int64_t), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int64_t);
|
|
return true;
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
bool TupleIndex<PosType, PosType2>::Open(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value) {
|
|
SecondoCatalog *sc = SecondoSystem::GetCatalog();
|
|
TupleIndex *ti = new TupleIndex();
|
|
Word val;
|
|
SmiFileId fileId;
|
|
ListExpr tList = sc->NumericType(nl->SymbolAtom(TrieTI::BasicType()));
|
|
unsigned int noComponents;
|
|
if (!valueRecord.Read(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
// cout << "There are " << noComponents << " tries, ";
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
if (!triealg::OpenInvfile<PosType, PosType2>(valueRecord, offset, tList,
|
|
val)) {
|
|
cout << "error opening trie" << endl;
|
|
return false;
|
|
}
|
|
ti->tries.push_back((TrieTI*)val.addr);
|
|
}
|
|
if (!valueRecord.Read(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
// cout << "There are " << noComponents << " btrees, ";
|
|
tList = nl->ThreeElemList(nl->SymbolAtom(BTreeTI::BasicType()), nl->Empty(),
|
|
sc->NumericType(nl->SymbolAtom(CcInt::BasicType())));
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
BTreeTI *bt = BTreeTI::Open(valueRecord, offset, tList);
|
|
if (!bt) {
|
|
cout << "error opening btree" << endl;
|
|
return false;
|
|
}
|
|
ti->btrees.push_back(bt);
|
|
}
|
|
if (!valueRecord.Read(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
// cout << "There are " << noComponents << " rtree1s, ";
|
|
// tList = nl->FourElemList(nl->Empty(), nl->Empty(), nl->Empty(),
|
|
// nl->BoolAtom(true));
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
// if (!OpenRTree<1>(valueRecord, offset, tList, val)) {
|
|
// cout << "error opening rtree1" << endl;
|
|
// return false;
|
|
// }
|
|
if (!valueRecord.Read(&fileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
val.addr = new RTree1TI(fileId, false);
|
|
ti->rtrees1.push_back((RTree1TI*)val.addr);
|
|
}
|
|
if (!valueRecord.Read(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
// cout << "There are " << noComponents << " rtree2s, ";
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
// if (!OpenRTree<2>(valueRecord, offset, tList, val)) {
|
|
// cout << "error opening rtree2" << endl;
|
|
// return false;
|
|
// }
|
|
if (!valueRecord.Read(&fileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
val.addr = new RTree2TI(fileId,false);
|
|
ti->rtrees2.push_back((RTree2TI*)val.addr);
|
|
}
|
|
// if (!OpenRTree<1>(valueRecord, offset, tList, val)) {
|
|
// cout << "error opening time index" << endl;
|
|
// return false;
|
|
// }
|
|
if (PosType::BasicType() == "unitpos") {
|
|
if (!valueRecord.Read(&fileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
val.addr = new RTree1TI(fileId, false);
|
|
ti->timeIndex = (RTree1TI*)val.addr;
|
|
// cout << "Time index opened, ";
|
|
}
|
|
else {
|
|
ti->timeIndex = 0;
|
|
}
|
|
if (!valueRecord.Read(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
int attr;
|
|
std::pair<IndexType, int> indexPos;
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
if (!valueRecord.Read(&attr, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&indexPos.first, sizeof(IndexType), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(IndexType);
|
|
if (!valueRecord.Read(&indexPos.second, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
ti->attrToIndex[attr] = indexPos;
|
|
}
|
|
if (!valueRecord.Read(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
if (!valueRecord.Read(&(indexPos.first), sizeof(IndexType), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(IndexType);
|
|
if (!valueRecord.Read(&(indexPos.second), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&attr, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
ti->indexToAttr[indexPos] = attr;
|
|
}
|
|
if (!valueRecord.Read(&(ti->mainAttr), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
value = SetWord(ti);
|
|
if (!valueRecord.Read(&noComponents, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
ti->firstEnd.resize(noComponents);
|
|
for (unsigned int i = 0; i < noComponents; i++) {
|
|
if (!valueRecord.Read(&(ti->firstEnd[i]), sizeof(int64_t), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int64_t);
|
|
}
|
|
if (!valueRecord.Read(&ti->timeLimits.first, sizeof(int64_t), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int64_t);
|
|
if (!valueRecord.Read(&ti->timeLimits.second, sizeof(int64_t), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int64_t);
|
|
// cout << "TupleIndex opened succesfully" << endl;
|
|
return true;
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::Close(const ListExpr typeInfo, Word& w) {
|
|
TupleIndex<PosType, PosType2> *ti = (TupleIndex<PosType, PosType2>*)w.addr;
|
|
delete ti;
|
|
w.addr = 0;
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
Word TupleIndex<PosType, PosType2>::Clone(const ListExpr typeInfo,
|
|
const Word& w) {
|
|
TupleIndex<PosType, PosType2> *ti = (TupleIndex<PosType, PosType2>*)w.addr;
|
|
Word res;
|
|
res.addr = new TupleIndex<PosType, PosType2>(*ti);
|
|
return res;
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
int TupleIndex<PosType, PosType2>::SizeOfObj() {
|
|
return sizeof(TupleIndex<PosType, PosType2>);
|
|
}
|
|
|
|
template<class PosType, class PosType2>
|
|
bool TupleIndex<PosType, PosType2>::TypeCheck(ListExpr type,
|
|
ListExpr& errorInfo) {
|
|
return nl->IsEqual(type, BasicType());
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~initialize~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::initialize(TupleType *ttype, int _mainAttr){
|
|
std::vector<int> placeAttrs;
|
|
mainAttr = _mainAttr;
|
|
Instant limit(datetime::instanttype);
|
|
limit.ToMinimum();
|
|
timeLimits.second = limit.millisecondsToNull();
|
|
limit.ToMaximum();
|
|
timeLimits.first = limit.millisecondsToNull();//init limits to extreme values
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
// ListExpr typeInfo = nl->FourElemList(nl->Empty(), nl->Empty(),
|
|
// nl->Empty(), nl->BoolAtom(true));
|
|
// RTree1TLLI* rtbla = (RTree1TLLI*)((CreateRTree<1>(typeInfo)).addr);
|
|
if (PosType::BasicType() == "newinterval") { // version for tupleindex2
|
|
timeIndex = 0;
|
|
}
|
|
else { // version for tupleindex with main attribute
|
|
timeIndex = new R_Tree<1, NewPair<TupleId, PosType> >(4000, false);
|
|
cout << "RTree1 for time intervals created" << endl;
|
|
}
|
|
for (int i = 0; i < ttype->GetNoAttributes(); i++) {
|
|
AttributeType atype = ttype->GetAttributeType(i);
|
|
std::string name = sc->GetTypeName(atype.algId, atype.typeId);
|
|
if (name == "mlabel" || name == "mlabels" || name == "mplace" ||
|
|
name == "mplaces") {
|
|
attrToIndex[i] = std::make_pair(TRIE, (int)tries.size());
|
|
indexToAttr[std::make_pair(TRIE, (int)tries.size())] = i;
|
|
// InvertedFile *inv = new InvertedFile();
|
|
TrieTI *inv = new TrieTI();
|
|
inv->setParams(false, 1, "");
|
|
tries.push_back(inv);
|
|
cout << "Trie for attr " << i << " created and appended" << endl;
|
|
if (name == "mplace" || name == "mplaces") {
|
|
placeAttrs.push_back(i);
|
|
}
|
|
}
|
|
else if (name == "mint") {
|
|
attrToIndex[i] = std::make_pair(BTREE, (int)btrees.size());
|
|
indexToAttr[std::make_pair(BTREE, (int)btrees.size())] = i;
|
|
BTreeTI *btree = new BTreeTI(SmiKey::Integer);
|
|
btrees.push_back(btree);
|
|
cout << "BTree for attr " << i << " created and appended" << endl;
|
|
}
|
|
else if (name == "mreal") {
|
|
attrToIndex[i] = std::make_pair(RTREE1, (int)rtrees1.size());
|
|
indexToAttr[std::make_pair(RTREE1, (int)rtrees1.size())] = i;
|
|
// R_Tree<1, NewPair<TupleId, int> > *rtree1 =
|
|
// new R_Tree<1, NewPair<TupleId, int> >(4096);
|
|
RTree1TI *rtree1 = new R_Tree<1, NewPair<TupleId, PosType> >(4000, false);
|
|
rtrees1.push_back(rtree1);
|
|
cout << "RTree1 for attr " << i << " created and appended" << endl;
|
|
}
|
|
else if (name == "mpoint" || name == "mregion") {
|
|
attrToIndex[i] = std::make_pair(RTREE2, (int)rtrees2.size());
|
|
indexToAttr[std::make_pair(RTREE2, (int)rtrees2.size())] = i;
|
|
// R_Tree<2, NewPair<TupleId, int> > *rtree2 =
|
|
// new R_Tree<2, NewPair<TupleId, int> >(4096);
|
|
RTree2TI *rtree2 = new R_Tree<2, NewPair<TupleId, PosType> >(4000, false);
|
|
rtrees2.push_back(rtree2);
|
|
cout << "RTree2 for attr " << i << " created and appended" << endl;
|
|
}
|
|
else {
|
|
attrToIndex[i] = std::make_pair(NONE, -1);
|
|
}
|
|
}
|
|
// now insert rtree2 for mplace(s) attributes
|
|
for (unsigned int j = 0; j < placeAttrs.size(); j++) {
|
|
indexToAttr[std::make_pair(RTREE2, (int)rtrees2.size())] = placeAttrs[j];
|
|
RTree2TI *rtree2 = new R_Tree<2, NewPair<TupleId, PosType> >(4000, false);
|
|
rtrees2.push_back(rtree2);
|
|
cout << "RTree2 # " << rtrees2.size() << " for attr " << placeAttrs[j]
|
|
<< " created and appended" << endl;
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~insertIntoTrie~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::insertIntoTrie(TrieTI *inv, TupleId tid,
|
|
Attribute *traj, DataType type, appendcache::RecordAppendCache* cache,
|
|
TrieNodeCacheType* trieCache, int64_t& inst) {
|
|
Instant rightLimit(datetime::instanttype);
|
|
switch (type) {
|
|
case MLABEL: {
|
|
std::string value;
|
|
for (int j = 0; j < ((MLabel*)traj)->GetNoComponents(); j++) {
|
|
((MLabel*)traj)->GetValue(j, value);
|
|
inv->insertString(tid, value, j, 0, cache, trieCache);
|
|
// cout << "inserted " << tid << " " << value << " " << j << endl;
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
((MLabel*)traj)->FinalInstant(rightLimit);
|
|
}
|
|
break;
|
|
}
|
|
case MPLACE: {
|
|
std::pair<std::string, uint32_t> value;
|
|
for (int j = 0; j < ((MPlace*)traj)->GetNoComponents(); j++) {
|
|
((MPlace*)traj)->GetValue(j, value);
|
|
inv->insertString(tid, value.first, j, value.second, cache, trieCache);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
((MPlace*)traj)->FinalInstant(rightLimit);
|
|
}
|
|
break;
|
|
}
|
|
case MLABELS: {
|
|
std::set<std::string> values;
|
|
for (int j = 0; j < ((MLabels*)traj)->GetNoComponents(); j++) {
|
|
((MLabels*)traj)->GetValues(j, values);
|
|
for (std::set<std::string>::iterator it
|
|
= values.begin(); it != values.end(); it++) {
|
|
inv->insertString(tid, *it, j, 0, cache, trieCache);
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
((MLabels*)traj)->FinalInstant(rightLimit);
|
|
}
|
|
break;
|
|
}
|
|
default: { // mplaces
|
|
std::set<std::pair<std::string, uint32_t> > values;
|
|
for (int j = 0; j < ((MPlaces*)traj)->GetNoComponents(); j++) {
|
|
((MPlaces*)traj)->GetValues(j, values);
|
|
for (std::set<std::pair<std::string, uint32_t> >::iterator it
|
|
= values.begin(); it != values.end(); it++) {
|
|
inv->insertString(tid, it->first, j, it->second, cache, trieCache);
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
((MPlaces*)traj)->FinalInstant(rightLimit);
|
|
}
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
if (rightLimit.millisecondsToNull() < inst) {
|
|
inst = rightLimit.millisecondsToNull();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~fillTimeIndex~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
bool TupleIndex<PosType, PosType2>::fillTimeIndex(RTree1TI* rt, TupleId tid,
|
|
Attribute *traj, DataType type) {
|
|
temporalalgebra::SecInterval iv(true);
|
|
double start[1], end[1];
|
|
int noComponents = -1;
|
|
switch (type) {
|
|
case MLABEL: {
|
|
noComponents = ((MLabel*)traj)->GetNoComponents();
|
|
break;
|
|
}
|
|
case MLABELS: {
|
|
noComponents = ((MLabels*)traj)->GetNoComponents();
|
|
break;
|
|
}
|
|
case MPLACE: {
|
|
noComponents = ((MPlace*)traj)->GetNoComponents();
|
|
break;
|
|
}
|
|
default: { // MPLACES
|
|
noComponents = ((MPlaces*)traj)->GetNoComponents();
|
|
break;
|
|
}
|
|
}
|
|
for (int i = 0; i < noComponents; i++) {
|
|
switch (type) {
|
|
case MLABEL: {
|
|
((MLabel*)traj)->GetInterval(i, iv);
|
|
break;
|
|
}
|
|
case MLABELS: {
|
|
((MLabels*)traj)->GetInterval(i, iv);
|
|
break;
|
|
}
|
|
case MPLACE: {
|
|
((MPlace*)traj)->GetInterval(i, iv);
|
|
break;
|
|
}
|
|
default: { // MPLACES
|
|
((MPlaces*)traj)->GetInterval(i, iv);
|
|
break;
|
|
}
|
|
}
|
|
start[0] = iv.start.ToDouble();
|
|
end[0] = iv.end.ToDouble();
|
|
Rectangle<1> doubleIv(true, start, end);
|
|
if (doubleIv.IsDefined()) {
|
|
NewPair<TupleId, PosType> position(tid, i);
|
|
R_TreeLeafEntry<1, NewPair<TupleId, PosType> > entry(doubleIv, position);
|
|
rt->Insert(entry);
|
|
// cout << "Inserted (" << start[0] << ", " << end[0] << ")" << endl;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~insertIntoBTree~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::insertIntoBTree(BTreeTI *bt, TupleId tid,
|
|
temporalalgebra::MInt *mint, int64_t& inst) {
|
|
Instant rightLimit(datetime::instanttype);
|
|
temporalalgebra::UInt unit(true);
|
|
NewPair<TupleId, PosType> position;
|
|
position.first = tid;
|
|
for (int i = 0; i < mint->GetNoComponents(); i++) {
|
|
mint->Get(i, unit);
|
|
if (PosType::BasicType() == "unitpos") {
|
|
position.copy2ndFrom(i);
|
|
}
|
|
else {
|
|
position.copy2ndFrom(unit.timeInterval);
|
|
}
|
|
bt->Append(unit.constValue.GetValue(), position);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mint->FinalInstant(rightLimit);
|
|
if (rightLimit.millisecondsToNull() < inst) {
|
|
inst = rightLimit.millisecondsToNull();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~insertIntoRTree1~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
bool TupleIndex<PosType, PosType2>::insertIntoRTree1(RTree1TI *rt, TupleId tid,
|
|
Attribute *m, int64_t& inst) {
|
|
Instant rightLimit(datetime::instanttype);
|
|
double start[1], end[1];
|
|
temporalalgebra::UReal unit(true);
|
|
bool correct1(true), correct2(true);
|
|
for (int i = 0; i < ((temporalalgebra::MReal*)m)->GetNoComponents(); i++) {
|
|
((temporalalgebra::MReal*)m)->Get(i, unit);
|
|
start[0] = unit.Min(correct1);
|
|
end[0] = unit.Max(correct2);
|
|
if (!correct1 || !correct2) {
|
|
cout << "Error at unit " << i << ", tuple " << tid << endl;
|
|
return false;
|
|
}
|
|
Rectangle<1> doubleIv(true, start, end);
|
|
NewPair<TupleId, PosType> position(tid, i);
|
|
// TwoLayerLeafInfo position(tid, i, i);
|
|
R_TreeLeafEntry<1, NewPair<TupleId, PosType> > entry(doubleIv, position);
|
|
rt->Insert(entry);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
((temporalalgebra::MReal*)m)->FinalInstant(rightLimit);
|
|
if (rightLimit.millisecondsToNull() < inst) {
|
|
inst = rightLimit.millisecondsToNull();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~insertIntoRTree2~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
bool TupleIndex<PosType, PosType2>::insertIntoRTree2(RTree2TI *rt, TupleId tid,
|
|
Attribute *m, std::string type, int64_t& inst) {
|
|
Instant rightLimit(datetime::instanttype);
|
|
if (type == "mpoint") {
|
|
temporalalgebra::UPoint up(true);
|
|
for (int i = 0; i < ((temporalalgebra::MPoint*)m)->GetNoComponents(); i++) {
|
|
((temporalalgebra::MPoint*)m)->Get(i, up);
|
|
if (up.IsDefined()) {
|
|
NewPair<TupleId, PosType> position(tid, i);
|
|
// TwoLayerLeafInfo position(tid, i, i);
|
|
R_TreeLeafEntry<2, NewPair<TupleId, PosType> >
|
|
entry(up.BoundingBoxSpatial(), position);
|
|
rt->Insert(entry);
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
((temporalalgebra::MPoint*)m)->FinalInstant(rightLimit);
|
|
if (rightLimit.millisecondsToNull() < inst) {
|
|
inst = rightLimit.millisecondsToNull();
|
|
}
|
|
}
|
|
}
|
|
else if (type == "mregion") {
|
|
temporalalgebra::URegionEmb ur(true);
|
|
double min[2], max[2];
|
|
for (int i = 0; i < ((temporalalgebra::MRegion*)m)->GetNoComponents(); i++){
|
|
((temporalalgebra::MRegion*)m)->Get(i, ur);
|
|
if (ur.IsDefined()) {
|
|
NewPair<TupleId, PosType> position(tid, i);
|
|
Rectangle<2> bbox2d(true);
|
|
min[0] = ur.BoundingBox().MinD(0);
|
|
max[0] = ur.BoundingBox().MaxD(0);
|
|
min[1] = ur.BoundingBox().MinD(1);
|
|
max[1] = ur.BoundingBox().MaxD(1);
|
|
bbox2d.Set(true, min, max);
|
|
R_TreeLeafEntry<2, NewPair<TupleId, PosType> > entry(bbox2d, position);
|
|
rt->Insert(entry);
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
((temporalalgebra::MRegion*)m)->FinalInstant(rightLimit);
|
|
if (rightLimit.millisecondsToNull() < inst) {
|
|
inst = rightLimit.millisecondsToNull();
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
cout << "Invalid type " << type << endl;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~addTuple~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
bool TupleIndex<PosType, PosType2>::addTuple(Tuple *tuple) {
|
|
int64_t inst = std::numeric_limits<int64_t>::max();
|
|
for (int i = 0; i < tuple->GetNoAttributes(); i++) {
|
|
std::pair<IndexType, int> indexPos = attrToIndex[i];
|
|
if (indexPos.second > -1) {
|
|
if (indexPos.first == TRIE) {
|
|
size_t maxMem = 0;/*qp->GetMemorySize(s) * 1024 * 1024*/
|
|
size_t trieCacheSize = maxMem / 20;
|
|
if (trieCacheSize < 4096) {
|
|
trieCacheSize = 4096;
|
|
}
|
|
size_t invCacheSize;
|
|
if (trieCacheSize + 4096 > maxMem) {
|
|
invCacheSize = 4096;
|
|
}
|
|
else {
|
|
invCacheSize = maxMem - trieCacheSize;
|
|
}
|
|
TrieTI *inv = tries[indexPos.second];
|
|
appendcache::RecordAppendCache* cache =
|
|
inv->createAppendCache(invCacheSize);
|
|
TrieNodeCacheType* trieCache = inv->createTrieCache(trieCacheSize);
|
|
// cout << "INSERT INTO TRIE " << indexPos.second << endl;
|
|
insertIntoTrie(inv, tuple->GetTupleId(), tuple->GetAttribute(i),
|
|
Tools::getDataType(tuple->GetTupleType(), i), cache,
|
|
trieCache, inst);
|
|
delete trieCache;
|
|
delete cache;
|
|
if (i == mainAttr) {
|
|
// cout << "FILL TIME INDEX" << endl;
|
|
if (!fillTimeIndex(timeIndex, tuple->GetTupleId(),
|
|
tuple->GetAttribute(i), Tools::getDataType(tuple->GetTupleType(), i))) {
|
|
cout << "Error adding tuple " << tuple->GetTupleId() << endl;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else if (indexPos.first == BTREE) {
|
|
// cout << "INSERT INTO BTREE" << endl;
|
|
insertIntoBTree(btrees[indexPos.second], tuple->GetTupleId(),
|
|
(temporalalgebra::MInt*)(tuple->GetAttribute(i)), inst);
|
|
}
|
|
else if (indexPos.first == RTREE1) {
|
|
// cout << "INSERT INTO RTREE1 " << indexPos.second << endl;
|
|
if (!insertIntoRTree1(rtrees1[indexPos.second], tuple->GetTupleId(),
|
|
tuple->GetAttribute(i), inst)) {
|
|
cout << "Error adding tuple " << tuple->GetTupleId() << endl;
|
|
return false;
|
|
}
|
|
}
|
|
else if (indexPos.first == RTREE2) {
|
|
// cout << "INSERT INTO RTREE2" << endl;
|
|
if (!insertIntoRTree2(rtrees2[indexPos.second], tuple->GetTupleId(),
|
|
tuple->GetAttribute(i),
|
|
Tools::getTypeName(tuple->GetTupleType(), i), inst)) {
|
|
cout << "Error adding tuple " << tuple->GetTupleId() << endl;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
while (firstEnd.size() <= tuple->GetTupleId()) {
|
|
firstEnd.resize(tuple->GetTupleId() + 1,
|
|
std::numeric_limits<int64_t>::max());
|
|
}
|
|
firstEnd[tuple->GetTupleId()] = inst;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~deleteIndexes~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::deleteIndexes() {
|
|
for (unsigned int i = 0; i < tries.size(); i++) {
|
|
delete tries[i];
|
|
}
|
|
for (unsigned int i = 0; i < btrees.size(); i++) {
|
|
delete btrees[i];
|
|
}
|
|
for (unsigned int i = 0; i < rtrees1.size(); i++) {
|
|
delete rtrees1[i];
|
|
}
|
|
for (unsigned int i = 0; i < rtrees2.size(); i++) {
|
|
delete rtrees2[i];
|
|
}
|
|
if (timeIndex != 0) {
|
|
delete timeIndex;
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~processTimeIntervals~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::processTimeIntervals(Relation *rel,
|
|
const int attr, const std::string &typeName) {
|
|
std::vector<NewPair<NewPair<double, double>, NewPair<TupleId, int> > > values;
|
|
TupleId noTuples = rel->GetNoTuples();
|
|
temporalalgebra::SecInterval iv(true);
|
|
if (typeName == "mlabel") {
|
|
MLabel *ml = 0;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
ml = (MLabel*)t->GetAttribute(attr);
|
|
int noComponents = ml->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
ml->GetInterval(j, iv);
|
|
NewPair<double,double> ivDouble(iv.start.ToDouble(), iv.end.ToDouble());
|
|
NewPair<NewPair<double, double>, NewPair<TupleId, int> > value
|
|
(ivDouble, NewPair<TupleId, int>(i, j));
|
|
values.push_back(value);
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mlabels") {
|
|
MLabels *mls = 0;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mls = (MLabels*)t->GetAttribute(attr);
|
|
int noComponents = mls->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mls->GetInterval(j, iv);
|
|
NewPair<double,double> ivDouble(iv.start.ToDouble(), iv.end.ToDouble());
|
|
NewPair<NewPair<double, double>, NewPair<TupleId, int> > value
|
|
(ivDouble, NewPair<TupleId, int>(i, j));
|
|
values.push_back(value);
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mplace") {
|
|
MPlace *mp = 0;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mp = (MPlace*)t->GetAttribute(attr);
|
|
int noComponents = mp->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mp->GetInterval(j, iv);
|
|
NewPair<double,double> ivDouble(iv.start.ToDouble(), iv.end.ToDouble());
|
|
NewPair<NewPair<double, double>, NewPair<TupleId, int> > value
|
|
(ivDouble, NewPair<TupleId, int>(i, j));
|
|
values.push_back(value);
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mplaces") {
|
|
MPlaces *mps = 0;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mps = (MPlaces*)t->GetAttribute(attr);
|
|
int noComponents = mps->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mps->GetInterval(j, iv);
|
|
NewPair<double,double> ivDouble(iv.start.ToDouble(), iv.end.ToDouble());
|
|
NewPair<NewPair<double, double>, NewPair<TupleId, int> > value
|
|
(ivDouble, NewPair<TupleId, int>(i, j));
|
|
values.push_back(value);
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
cout << values.size() << " time intervals in vector" << endl;
|
|
std::sort(values.begin(), values.end());
|
|
cout << " ............ sorted" << endl;
|
|
double start[1], end[1];
|
|
bool bulkLoadInitialized = timeIndex->InitializeBulkLoad();
|
|
assert(bulkLoadInitialized);
|
|
for (unsigned int i = 0; i < values.size(); i++) {
|
|
start[0] = values[i].first.first;
|
|
end[0] = values[i].first.second;
|
|
Rectangle<1> doubleIv(true, start, end);
|
|
NewPair<TupleId, UnitPos> position(values[i].second.first,
|
|
values[i].second.second);
|
|
// TwoLayerLeafInfo position(values[i].second.first,values[i].second.second,
|
|
// values[i].second.second);
|
|
R_TreeLeafEntry<1, NewPair<TupleId, UnitPos> > entry(doubleIv, position);
|
|
timeIndex->InsertBulkLoad(entry);
|
|
}
|
|
bool bulkLoadFinalized = timeIndex->FinalizeBulkLoad();
|
|
assert(bulkLoadFinalized);
|
|
cout << "... written into rtree1" << endl;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~setTimeLimits~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::setTimeLimits(const Instant& leftLimit,
|
|
const Instant& rightLimit, const TupleId id) {
|
|
if (rightLimit.IsDefined()) {
|
|
if (rightLimit.millisecondsToNull() < firstEnd[id]) {
|
|
firstEnd[id] = rightLimit.millisecondsToNull();
|
|
}
|
|
if (rightLimit.millisecondsToNull() > timeLimits.second) {
|
|
timeLimits.second = rightLimit.millisecondsToNull();
|
|
}
|
|
}
|
|
if (leftLimit.IsDefined()) {
|
|
if (leftLimit.millisecondsToNull() < timeLimits.first) {
|
|
timeLimits.first = leftLimit.millisecondsToNull();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~processRTree2~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::processRTree2(Relation *rel,
|
|
const int attrNo, const std::string &typeName) {
|
|
std::vector<NewPair<NewPair<NewPair<double, double>, NewPair<double,double> >,
|
|
NewPair<TupleId, PosType> > > values;
|
|
TupleId noTuples = rel->GetNoTuples();
|
|
Instant leftLimit(datetime::instanttype), rightLimit(datetime::instanttype);
|
|
if (typeName == "mpoint") {
|
|
temporalalgebra::MPoint *mp = 0;
|
|
temporalalgebra::UPoint up(true);
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mp = (temporalalgebra::MPoint*)t->GetAttribute(attrNo);
|
|
int noComponents = mp->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mp->Get(j, up);
|
|
Rectangle<2> bbox = up.BoundingBoxSpatial();
|
|
NewPair<NewPair<double, double>, NewPair<double, double> > bboxValues(
|
|
NewPair<double, double>(bbox.MinD(0), bbox.MinD(1)),
|
|
NewPair<double, double>(bbox.MaxD(0), bbox.MaxD(1)));
|
|
NewPair<NewPair<NewPair<double, double>, NewPair<double, double> >,
|
|
NewPair<TupleId, PosType> > value;
|
|
value.first = bboxValues;
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
NewInterval niv(up.timeInterval);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mp->InitialInstant(leftLimit);
|
|
mp->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mregion") {
|
|
temporalalgebra::MRegion *mr = 0;
|
|
temporalalgebra::URegionEmb ur(true);
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mr = (temporalalgebra::MRegion*)t->GetAttribute(attrNo);
|
|
int noComponents = mr->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mr->Get(j, ur);
|
|
Rectangle<3> bbox = ur.BoundingBox();
|
|
NewPair<NewPair<double, double>, NewPair<double, double> > bboxValues(
|
|
NewPair<double, double>(bbox.MinD(0), bbox.MinD(1)),
|
|
NewPair<double, double>(bbox.MaxD(0), bbox.MaxD(1)));
|
|
NewPair<NewPair<NewPair<double, double>, NewPair<double, double> >,
|
|
NewPair<TupleId, PosType> > value;
|
|
value.first = bboxValues;
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
NewInterval niv(ur.timeInterval);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mr->InitialInstant(leftLimit);
|
|
mr->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mplace") {
|
|
Rectangle<2> bbox(true);
|
|
|
|
// SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
// bool defined = false;
|
|
// Word orelPtr, geo;
|
|
// if (!sc->GetObject("Places", orelPtr, defined)) {
|
|
// cout << "Error: cannot find relation 'Places'" << endl;
|
|
// return;
|
|
// }
|
|
// if (!defined) {
|
|
// cout << "Error: relation 'Places' is undefined" << endl;
|
|
// return;
|
|
// }
|
|
// OrderedRelation *orel = static_cast<OrderedRelation*>(orelPtr.addr);
|
|
MPlace *mp = 0;
|
|
UPlace up(true);
|
|
// vector<void*> attributes(1);
|
|
// vector<SmiKey::KeyDataType> attrTypes(1);
|
|
// attrTypes[0] = SmiKey::Integer;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mp = (MPlace*)t->GetAttribute(attrNo);
|
|
int noComponents = mp->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mp->Get(j, up);
|
|
if (!Tools::getRectFromOrel("Places", up.constValue.GetRef(), bbox)) {
|
|
return;
|
|
}
|
|
if (bbox.IsDefined()) {
|
|
NewPair<NewPair<double, double>, NewPair<double, double> > bboxValues(
|
|
NewPair<double, double>(bbox.MinD(0), bbox.MinD(1)),
|
|
NewPair<double, double>(bbox.MaxD(0), bbox.MaxD(1)));
|
|
NewPair<NewPair<NewPair<double, double>, NewPair<double, double> >,
|
|
NewPair<TupleId, PosType> > value;
|
|
value.first = bboxValues;
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
NewInterval niv(up.timeInterval);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mp->InitialInstant(leftLimit);
|
|
mp->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mplaces") {
|
|
Rectangle<2> bbox(true);
|
|
MPlaces *mp = 0;
|
|
std::set<std::pair<std::string, unsigned int> > pls;
|
|
std::set<std::pair<std::string, unsigned int> >::iterator it;
|
|
temporalalgebra::SecInterval iv(true);
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mp = (MPlaces*)t->GetAttribute(attrNo);
|
|
int noComponents = mp->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mp->GetValues(j, pls);
|
|
for (it = pls.begin(); it != pls.end(); it++) {
|
|
if (!Tools::getRectFromOrel("Places", it->second, bbox)) {
|
|
return;
|
|
}
|
|
NewPair<NewPair<double, double>, NewPair<double, double> > bboxValues(
|
|
NewPair<double, double>(bbox.MinD(0), bbox.MinD(1)),
|
|
NewPair<double, double>(bbox.MaxD(0), bbox.MaxD(1)));
|
|
NewPair<NewPair<NewPair<double, double>, NewPair<double, double> >,
|
|
NewPair<TupleId, PosType> > value;
|
|
value.first = bboxValues;
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
if (it == pls.begin()) {
|
|
mp->GetInterval(j, iv);
|
|
}
|
|
NewInterval niv(iv);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mp->InitialInstant(leftLimit);
|
|
mp->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
cout << values.size() << " 2D boxes in vector" << endl;
|
|
std::sort(values.begin(), values.end());
|
|
cout << " ............ sorted" << endl;
|
|
RTree2TI *rtree = 0;
|
|
int rtreePos = 0;
|
|
TupleType *tt = rel->GetTupleType();
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
for (int i = 0; i < attrNo; i++) {
|
|
AttributeType atype = tt->GetAttributeType(i);
|
|
std::string tn = sc->GetTypeName(atype.algId, atype.typeId);
|
|
if (tn == "mpoint"|| tn == "mregion"|| tn == "mplace"|| tn == "mplaces") {
|
|
rtreePos++;
|
|
}
|
|
}
|
|
rtree = rtrees2[rtreePos];
|
|
double min[2], max[2];
|
|
bool bulkLoadInitialized = rtree->InitializeBulkLoad();
|
|
assert(bulkLoadInitialized);
|
|
for (unsigned int i = 0; i < values.size(); i++) {
|
|
min[0] = values[i].first.first.first;
|
|
min[1] = values[i].first.first.second;
|
|
max[0] = values[i].first.second.first;
|
|
max[1] = values[i].first.second.second;
|
|
Rectangle<2> rect(true, min, max);
|
|
NewPair<TupleId, PosType> position(values[i].second.first,
|
|
values[i].second.second);
|
|
// TwoLayerLeafInfo position(values[i].second.first, values[i].second.second,
|
|
// values[i].second.second);
|
|
R_TreeLeafEntry<2, NewPair<TupleId, PosType> > entry(rect, position);
|
|
rtree->InsertBulkLoad(entry);
|
|
}
|
|
bool bulkLoadFinalized = rtree->FinalizeBulkLoad();
|
|
assert(bulkLoadFinalized);
|
|
cout << "... written into rtree2" << endl;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~processRTree1~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::processRTree1(Relation *rel,
|
|
const int attr) {
|
|
Instant leftLimit(datetime::instanttype), rightLimit(datetime::instanttype);
|
|
std::vector<NewPair<NewPair<double, double>, NewPair<TupleId, PosType> > >
|
|
values;
|
|
TupleId noTuples = rel->GetNoTuples();
|
|
temporalalgebra::MReal *mr = 0;
|
|
temporalalgebra::UReal ur(true);
|
|
double start, end;
|
|
bool correct1, correct2;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mr = (temporalalgebra::MReal*)t->GetAttribute(attr);
|
|
int noComponents = mr->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mr->Get(j, ur);
|
|
start = ur.Min(correct1);
|
|
end = ur.Max(correct2);
|
|
NewPair<NewPair<double, double>, NewPair<TupleId, PosType> > value;
|
|
value.first = NewPair<double, double>(start, end);
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
NewInterval niv(ur.timeInterval);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mr->InitialInstant(leftLimit);
|
|
mr->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
cout << values.size() << " real intervals in vector" << endl;
|
|
std::sort(values.begin(), values.end());
|
|
cout << ".......... sorted" << endl;
|
|
RTree1TI *rtree = rtrees1[attrToIndex[attr].second];
|
|
double min[1], max[1];
|
|
bool bulkLoadInitialized = rtree->InitializeBulkLoad();
|
|
assert(bulkLoadInitialized);
|
|
for (unsigned int i = 0; i < values.size(); i++) {
|
|
min[0] = values[i].first.first;
|
|
max[0] = values[i].first.second;
|
|
Rectangle<1> rect(true, min, max);
|
|
NewPair<TupleId, PosType> position(values[i].second.first,
|
|
values[i].second.second);
|
|
// TwoLayerLeafInfo position(values[i].second.first, values[i].second.second,
|
|
// values[i].second.second);
|
|
R_TreeLeafEntry<1, NewPair<TupleId, PosType> > entry(rect, position);
|
|
rtree->InsertBulkLoad(entry);
|
|
}
|
|
bool bulkLoadFinalized = rtree->FinalizeBulkLoad();
|
|
assert(bulkLoadFinalized);
|
|
cout << "... written into rtree1" << endl;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~processBTree~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::processBTree(Relation *rel, const int attr){
|
|
Instant leftLimit(datetime::instanttype), rightLimit(datetime::instanttype);
|
|
std::vector<NewPair<int, NewPair<TupleId, PosType> > > values;
|
|
TupleId noTuples = rel->GetNoTuples();
|
|
temporalalgebra::MInt *mi = 0;
|
|
temporalalgebra::UInt ui(true);
|
|
NewPair<TupleId, PosType> pos;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
pos.first = i;
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mi = (temporalalgebra::MInt*)t->GetAttribute(attr);
|
|
int noComponents = mi->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mi->Get(j, ui);
|
|
if (PosType::BasicType() == "unitpos") {
|
|
pos.copy2ndFrom(j);
|
|
} else {
|
|
NewInterval niv(ui.timeInterval);
|
|
pos.copy2ndFrom(niv);
|
|
}
|
|
NewPair<int, NewPair<TupleId, PosType> > value(ui.constValue.GetValue(),
|
|
pos);
|
|
values.push_back(value);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mi->InitialInstant(leftLimit);
|
|
mi->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
cout << values.size() << " integers in vector" << endl;
|
|
std::sort(values.begin(), values.end());
|
|
cout << ".......... sorted" << endl;
|
|
BTree_t<NewPair<TupleId, PosType> > *btree = btrees[attrToIndex[attr].second];
|
|
for (unsigned int i = 0; i < values.size(); i++) {
|
|
btree->Append(values[i].first, values[i].second);
|
|
}
|
|
cout << "... written into btree" << endl;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~processTrie~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::processTrie(Relation *rel, const int attr,
|
|
const std::string &typeName, const size_t memSize) {
|
|
Instant leftLimit(datetime::instanttype), rightLimit(datetime::instanttype);
|
|
std::vector<NewPair<std::string, NewPair<TupleId, PosType> > > values;
|
|
NewPair<std::string, NewPair<TupleId, PosType> > value;
|
|
TupleId noTuples = rel->GetNoTuples();
|
|
temporalalgebra::SecInterval iv(true);
|
|
if (typeName == "mlabel") {
|
|
MLabel *ml = 0;
|
|
std::string label;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
ml = (MLabel*)t->GetAttribute(attr);
|
|
int noComponents = ml->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
ml->GetValue(j, value.first);
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
ml->GetInterval(j, iv);
|
|
NewInterval niv(iv);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
ml->InitialInstant(leftLimit);
|
|
ml->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mlabels") {
|
|
MLabels *mls = 0;
|
|
std::set<std::string> labels;
|
|
std::set<std::string>::iterator it;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mls = (MLabels*)t->GetAttribute(attr);
|
|
int noComponents = mls->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mls->GetValues(j, labels);
|
|
NewPair<TupleId, int> pos(i, j);
|
|
it = labels.begin();
|
|
while (it != labels.end()) {
|
|
value.first = *it;
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
mls->GetInterval(j, iv);
|
|
NewInterval niv(iv);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
it++;
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mls->InitialInstant(leftLimit);
|
|
mls->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mplace") {
|
|
MPlace *mp = 0;
|
|
std::pair<std::string, unsigned int> place;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mp = (MPlace*)t->GetAttribute(attr);
|
|
int noComponents = mp->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mp->GetValue(j, place);
|
|
value.first = place.first;
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
mp->GetInterval(j, iv);
|
|
NewInterval niv(iv);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mp->InitialInstant(leftLimit);
|
|
mp->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (typeName == "mplaces") {
|
|
MPlaces *mps = 0;
|
|
std::set<std::pair<std::string, unsigned int> > places;
|
|
std::set<std::pair<std::string, unsigned int> >::iterator it;
|
|
for (TupleId i = 1; i <= noTuples; i++) {
|
|
Tuple *t = rel->GetTuple(i, false);
|
|
mps = (MPlaces*)t->GetAttribute(attr);
|
|
int noComponents = mps->GetNoComponents();
|
|
for (int j = 0; j < noComponents; j++) {
|
|
mps->GetValues(j, places);
|
|
NewPair<TupleId, int> pos(i, j);
|
|
it = places.begin();
|
|
while (it != places.end()) {
|
|
value.first = it->first;
|
|
value.second.first = i;
|
|
if (PosType::BasicType() == "unitpos") {
|
|
value.second.copy2ndFrom(j);
|
|
}
|
|
else {
|
|
mps->GetInterval(j, iv);
|
|
NewInterval niv(iv);
|
|
value.second.copy2ndFrom(niv);
|
|
}
|
|
values.push_back(value);
|
|
it++;
|
|
}
|
|
}
|
|
if (PosType::BasicType() == "newinterval") {
|
|
mps->InitialInstant(leftLimit);
|
|
mps->FinalInstant(rightLimit);
|
|
setTimeLimits(leftLimit, rightLimit, t->GetTupleId());
|
|
}
|
|
t->DeleteIfAllowed();
|
|
}
|
|
}
|
|
cout << values.size() << " labels in vector" << endl;
|
|
std::sort(values.begin(), values.end());
|
|
cout << ".......... sorted" << endl;
|
|
InvertedFileT<PosType, PosType2> *trie = tries[attrToIndex[attr].second];
|
|
size_t maxMem = memSize * 16 * 1024 * 1024;
|
|
size_t trieCacheSize = maxMem / 20;
|
|
if (trieCacheSize < 4096) {
|
|
trieCacheSize = 4096;
|
|
}
|
|
size_t invCacheSize;
|
|
if (trieCacheSize + 4096 > maxMem) {
|
|
invCacheSize = 4096;
|
|
}
|
|
else {
|
|
invCacheSize = maxMem - trieCacheSize;
|
|
}
|
|
appendcache::RecordAppendCache* cache = trie->createAppendCache(invCacheSize);
|
|
TrieNodeCacheType* trieCache = trie->createTrieCache(trieCacheSize);
|
|
for (unsigned int i = 0; i < values.size(); i++) {
|
|
trie->insertString(values[i].second.first, values[i].first,
|
|
values[i].second.second, 0, cache, trieCache);
|
|
}
|
|
delete trieCache;
|
|
delete cache;
|
|
cout << "... written into trie" << endl;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~collectSortInsert~}
|
|
|
|
*/
|
|
template<class PosType, class PosType2>
|
|
void TupleIndex<PosType, PosType2>::collectSortInsert(Relation *rel,
|
|
const int attrPos, const std::string &typeName, const size_t memSize) {
|
|
if (PosType::BasicType() == "newinterval") {
|
|
firstEnd.resize(rel->GetNoTuples()+ 1, std::numeric_limits<int64_t>::max());
|
|
}
|
|
else if (attrPos == mainAttr) {
|
|
processTimeIntervals(rel, attrPos, typeName);
|
|
firstEnd.clear();
|
|
}
|
|
IndexType indexType = attrToIndex[attrPos].first;
|
|
switch (indexType) {
|
|
case TRIE: {
|
|
processTrie(rel, attrPos, typeName, memSize);
|
|
if (typeName == "mplace" || typeName == "mplaces") {
|
|
processRTree2(rel, attrPos, typeName);
|
|
}
|
|
break;
|
|
}
|
|
case BTREE: {
|
|
processBTree(rel, attrPos);
|
|
break;
|
|
}
|
|
case RTREE1: {
|
|
processRTree1(rel, attrPos);
|
|
break;
|
|
}
|
|
case RTREE2: {
|
|
processRTree2(rel, attrPos, typeName);
|
|
break;
|
|
}
|
|
case NONE: { // nothing to do
|
|
break;
|
|
}
|
|
}
|
|
Instant first(timeLimits.first), last(timeLimits.second);
|
|
cout << "After attr " << attrPos << ": " << first << " | " << last << endl;
|
|
}
|
|
|
|
/*
|
|
\section{Class GetLabelsLI}
|
|
|
|
*/
|
|
template<class T>
|
|
class GetLabelsLI {
|
|
public:
|
|
GetLabelsLI(T& src) : counter(0) {
|
|
src.InsertLabels(labels);
|
|
}
|
|
|
|
~GetLabelsLI() {}
|
|
|
|
FText* nextResult() {
|
|
if (counter >= 0 && counter < labels.size()) {
|
|
std::string label = labels[counter];
|
|
counter++;
|
|
return new FText(true, label);
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
std::vector<std::string> labels;
|
|
unsigned int counter;
|
|
};
|
|
|
|
}
|