3261 lines
87 KiB
C++
3261 lines
87 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
|
|
----
|
|
|
|
//[_] [\_]
|
|
//[&] [\&]
|
|
//[toc] [\tableofcontents]
|
|
//[title] [ \title{TopRel Algebra} \author{Thomas Behr} \maketitle]
|
|
//[times] [\ensuremath{\times}]
|
|
//[->] [\ensuremath{\rightarrow}]
|
|
|
|
[title]
|
|
[toc]
|
|
|
|
December 2005, Victor Almeida deleted the deprecated algebra levels
|
|
(~executable~, ~descriptive~, and ~hibrid~). Only the executable
|
|
level remains. Models are also removed from type constructors.
|
|
|
|
1. Includes and Definitions
|
|
|
|
1.1 Includes
|
|
|
|
*/
|
|
|
|
#include "TopRel.h"
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include "NestedList.h"
|
|
#include "Algebra.h"
|
|
#include "QueryProcessor.h"
|
|
#include "SecondoSystem.h"
|
|
#include "Attribute.h"
|
|
#include "StandardTypes.h"
|
|
#include "../../Tools/Flob/DbArray.h"
|
|
#include "LogMsg.h"
|
|
|
|
#include "FTextAlgebra.h"
|
|
#include "GenericTC.h"
|
|
#include "Symbols.h"
|
|
|
|
|
|
|
|
|
|
extern "C"{
|
|
#include "Tree.h"
|
|
}
|
|
|
|
/*
|
|
1.2 Definition of frequently used Constants
|
|
|
|
*/
|
|
|
|
using namespace std;
|
|
|
|
|
|
// define powers of two
|
|
static const unsigned short P0 = 1;
|
|
static const unsigned short P1 = 2;
|
|
static const unsigned short P2 = 4;
|
|
static const unsigned short P3 = 8;
|
|
static const unsigned short P4 = 16;
|
|
static const unsigned short P5 = 32;
|
|
static const unsigned short P6 = 64;
|
|
static const unsigned short P7 = 128;
|
|
//static const unsigned short P8 = 256;
|
|
//static const unsigned short P9 = 512;
|
|
|
|
|
|
|
|
static const int PART_INTER = 1;
|
|
static const int NO_EXT_INTER = 2;
|
|
static const int O1_EMPTY = 4;
|
|
static const int O2_EMPTY = 8;
|
|
static const int O1_NON_EMPTY = 16;
|
|
static const int O2_NON_EMPTY = 32;
|
|
static const int O1_INNER = 64;
|
|
static const int O2_INNER = 128;
|
|
|
|
|
|
|
|
|
|
const unsigned char* getEmptyBlock(){
|
|
|
|
static const unsigned char emptyBlock[]={ (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0,
|
|
(const unsigned char)0, (const unsigned char)0, (const unsigned char)0};
|
|
return emptyBlock;
|
|
}
|
|
|
|
|
|
const unsigned char* getFullBlock(){
|
|
static const unsigned char fullBlock[]={
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255,
|
|
(const unsigned char)255, (const unsigned char)255};
|
|
return fullBlock;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// The name of the unspecified cluster
|
|
static const STRING_T UNSPECIFIED = "unspecified";
|
|
|
|
// an array containing the transposedd versions
|
|
// for a matrix number
|
|
static unsigned short TranspArray[512];
|
|
|
|
|
|
extern NestedList *nl;
|
|
extern QueryProcessor* qp;
|
|
|
|
|
|
/*
|
|
2 Realization of the classes
|
|
|
|
*/
|
|
|
|
namespace toprel{
|
|
|
|
/*
|
|
|
|
2.1 The Operations for the Int9M class
|
|
|
|
2.1.1 A Constructor
|
|
|
|
This constructor create a new 9 intersection matrix
|
|
with predefined content.
|
|
|
|
*/
|
|
Int9M::Int9M(const bool II, const bool IB, const bool IE,
|
|
const bool BI, const bool BB, const bool BE,
|
|
const bool EI, const bool EB, const bool EE):Attribute(true){
|
|
Set(II,IB,IE,BI,BB,BE,EI,EB,EE);
|
|
}
|
|
|
|
|
|
/*
|
|
2.1.2 The Set function
|
|
|
|
This function sets all entries in the matrix to the given values.
|
|
|
|
*/
|
|
void Int9M::Set( const bool II, const bool IB, const bool IE,
|
|
const bool BI, const bool BB, const bool BE,
|
|
const bool EI, const bool EB, const bool EE){
|
|
SetII(II);
|
|
SetIB(IB);
|
|
SetIE(IE);
|
|
SetBI(BI);
|
|
SetBB(BB);
|
|
SetBE(BE);
|
|
SetEI(EI);
|
|
SetEB(EB);
|
|
SetEE(EE);
|
|
value = value & 511;
|
|
SetDefined(true);
|
|
}
|
|
|
|
|
|
void Int9M::Transpose(){
|
|
value = TranspArray[value];
|
|
}
|
|
|
|
|
|
/*
|
|
2.1.3 ToListExpr
|
|
|
|
This function returns the NestedList representation of a
|
|
9 intersection matrix.
|
|
|
|
*/
|
|
ListExpr Int9M::ToListExpr(ListExpr typeInfo) const {
|
|
if(!IsDefined()){
|
|
return nl->SymbolAtom("undefined");
|
|
}
|
|
ListExpr Last;
|
|
ListExpr res = Last = nl->OneElemList(nl->BoolAtom(II&value));
|
|
Last = nl->Append(Last,nl->BoolAtom(IB&value));
|
|
Last = nl->Append(Last,nl->BoolAtom(IE&value));
|
|
Last = nl->Append(Last,nl->BoolAtom(BI&value));
|
|
Last = nl->Append(Last,nl->BoolAtom(BB&value));
|
|
Last = nl->Append(Last,nl->BoolAtom(BE&value));
|
|
Last = nl->Append(Last,nl->BoolAtom(EI&value));
|
|
Last = nl->Append(Last,nl->BoolAtom(EB&value));
|
|
Last = nl->Append(Last,nl->BoolAtom(EE&value));
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
2.1.4 ReadFrom
|
|
|
|
If this function is called, this matrix gets its value from the
|
|
given nested list. If the nested list don't represent a valid
|
|
9-intersection matrix, the matrix remains unchanged and the
|
|
result of this function will be ~false~.
|
|
Allowed representations are a single int atom in range [0, 511],
|
|
or a list containing nine boolean (or int) atoms representing the matrix entries.
|
|
|
|
*/
|
|
bool Int9M::ReadFrom(const ListExpr LE,const ListExpr typeInfo){
|
|
// case uf undefined
|
|
if(nl->IsEqual(LE,"undefined")){
|
|
SetDefined(false);
|
|
return true;
|
|
}
|
|
|
|
if(nl->AtomType(LE)==IntType){
|
|
int v = nl->IntValue(LE);
|
|
if(v<0){
|
|
ErrorReporter::ReportError("matrixnaumber less than zero");
|
|
return false;
|
|
}
|
|
if(v>511){
|
|
ErrorReporter::ReportError("matrix number more than 511");
|
|
return false;
|
|
}
|
|
value = (unsigned short) v;
|
|
SetDefined(true);
|
|
return true;
|
|
}
|
|
|
|
if(nl->ListLength(LE)!=9){
|
|
ErrorReporter::ReportError("invalid listlength");
|
|
return false;
|
|
}
|
|
unsigned short tmp=0;
|
|
unsigned short pos=256;
|
|
ListExpr r = LE;
|
|
ListExpr f;
|
|
bool b;
|
|
for(int i=0;i<9;i++){
|
|
f = nl->First(r);
|
|
if(nl->AtomType(f)==BoolType)
|
|
b = nl->BoolValue(f);
|
|
else if(nl->AtomType(f)==IntType)
|
|
b = nl->IntValue(f)!=0;
|
|
else{ // not an allowed type
|
|
ErrorReporter::ReportError("matrix entry must"
|
|
" be an int or a boolean");
|
|
return false;
|
|
}
|
|
if(b)
|
|
tmp = tmp | pos;
|
|
pos = pos/2;
|
|
r = nl->Rest(r);
|
|
}
|
|
value = tmp;
|
|
SetDefined(true);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
2.1.5 Equalize functions
|
|
|
|
By calling the Equalize function, the matrix gets its value from
|
|
the argument.
|
|
|
|
*/
|
|
void Int9M::Equalize(const Int9M& value){
|
|
Equalize(&value);
|
|
}
|
|
|
|
void Int9M::Equalize(const Int9M* v){
|
|
this->value = v->value;
|
|
SetDefined(v->IsDefined());
|
|
}
|
|
|
|
/*
|
|
2.1.6 Compare function
|
|
|
|
This functions compares this matrix with arg. arg must be of type
|
|
Int9M.
|
|
|
|
*/
|
|
int Int9M::Compare(const Attribute* arg) const{
|
|
Int9M* v = (Int9M*) arg;
|
|
if(!IsDefined() && !v->IsDefined()){
|
|
return 0;
|
|
}
|
|
if(!IsDefined()){
|
|
return -1;
|
|
}
|
|
if(!v->IsDefined()){
|
|
return 1;
|
|
}
|
|
|
|
if(value < v->value){
|
|
return -1;
|
|
} else if(value >v->value){
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
2.1.11 HashValue
|
|
|
|
*/
|
|
size_t Int9M::HashValue() const{
|
|
if(!IsDefined())
|
|
return (size_t) 512;
|
|
else
|
|
return (size_t) value;
|
|
}
|
|
|
|
/*
|
|
2.1.12 CopyFrom
|
|
|
|
*/
|
|
void Int9M::CopyFrom(const Attribute* arg){
|
|
Equalize((Int9M*) arg);
|
|
}
|
|
|
|
/*
|
|
2.1.13 Clone
|
|
|
|
*/
|
|
Int9M* Int9M::Clone() const
|
|
{
|
|
unsigned short number = 0;
|
|
Int9M* res = new Int9M(number);
|
|
res->Equalize(this);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
2.1.14 Print
|
|
|
|
*/
|
|
ostream& Int9M::Print( ostream& os ) const{
|
|
os << value;
|
|
return os;
|
|
}
|
|
|
|
/*
|
|
2.1.15 ToString
|
|
|
|
This function creates the sting repreentation of a matrix.
|
|
|
|
*/
|
|
string Int9M::ToString() const{
|
|
int ii = GetII()?1:0;
|
|
int ib = GetIB()?1:0;
|
|
int ie = GetIE()?1:0;
|
|
int bi = GetBI()?1:0;
|
|
int bb = GetBB()?1:0;
|
|
int be = GetBE()?1:0;
|
|
int ei = GetEI()?1:0;
|
|
int eb = GetEB()?1:0;
|
|
int ee = GetEE()?1:0;
|
|
stringstream res;
|
|
res << "\n"<<ii<<" "<<ib<<" "<<ie<<"\n"
|
|
<< bi<<" "<<bb<<" "<<be<<"\n"
|
|
<< ei<<" "<<eb<<" "<<ee<<"\n";
|
|
return res.str();
|
|
}
|
|
|
|
|
|
/*
|
|
2.1.15 Equal Operator
|
|
|
|
*/
|
|
bool Int9M::operator==(const Int9M& I2) const{
|
|
return CompareTo(I2)==0;
|
|
}
|
|
|
|
|
|
/*
|
|
2.2 Definitions for the Cluster Type
|
|
|
|
*/
|
|
|
|
/*
|
|
2.2.1 The ValueAt function
|
|
|
|
This functions checks whether the matrix with number pos is a
|
|
member of this cluster.
|
|
|
|
*/
|
|
bool Cluster::ValueAt(const int pos) const{
|
|
assert(pos >= 0 && pos < 512);
|
|
int bytenum = pos / 8;
|
|
int bytepos = pos % 8;
|
|
unsigned char theByte = BitVector[bytenum];
|
|
switch(bytepos){
|
|
case 0 : return P0 & theByte;
|
|
case 1 : return P1 & theByte;
|
|
case 2 : return P2 & theByte;
|
|
case 3 : return P3 & theByte;
|
|
case 4 : return P4 & theByte;
|
|
case 5 : return P5 & theByte;
|
|
case 6 : return P6 & theByte;
|
|
case 7 : return P7 & theByte;
|
|
default : assert(false); return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool Cluster::ValueAt(const int pos,const unsigned char BitVector[64]){
|
|
assert(pos >= 0 && pos < 512);
|
|
int bytenum = pos / 8;
|
|
int bytepos = pos % 8;
|
|
unsigned char theByte = BitVector[bytenum];
|
|
switch(bytepos){
|
|
case 0 : return P0 & theByte;
|
|
case 1 : return P1 & theByte;
|
|
case 2 : return P2 & theByte;
|
|
case 3 : return P3 & theByte;
|
|
case 4 : return P4 & theByte;
|
|
case 5 : return P5 & theByte;
|
|
case 6 : return P6 & theByte;
|
|
case 7 : return P7 & theByte;
|
|
default : assert(false); return false;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
2.2.2 ToString
|
|
|
|
*/
|
|
|
|
string Cluster::ToString() const{
|
|
stringstream o;
|
|
o << name << "(";
|
|
for(int i=0;i<512;i++){
|
|
if(ValueAt(i)){
|
|
o << i << " ";
|
|
}
|
|
}
|
|
o << ")";
|
|
return o.str();
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
2.2.2 The Contains function
|
|
|
|
This functions checks whether the given Int9M matrix is part of this cluster
|
|
|
|
*/
|
|
|
|
bool Cluster::Contains(const Int9M M) const{
|
|
int number = M.GetNumber();
|
|
return ValueAt(number);
|
|
}
|
|
|
|
/*
|
|
2.2.1 The SetValueAt function
|
|
|
|
This function sets the containedness of the matrix number pos to the
|
|
given value.
|
|
|
|
*/
|
|
inline static void SetValueAtSimple(const int pos,const bool value,
|
|
unsigned char bitvector[]){
|
|
assert(pos>=0 && pos < 512);
|
|
int bytenum = pos / 8;
|
|
int bytepos = pos % 8;
|
|
if(!value){
|
|
switch(bytepos){
|
|
case 0 : bitvector[bytenum] &= (255 - P0);break;
|
|
case 1 : bitvector[bytenum] &= (255 - P1);break;
|
|
case 2 : bitvector[bytenum] &= (255 - P2);break;
|
|
case 3 : bitvector[bytenum] &= (255 - P3);break;
|
|
case 4 : bitvector[bytenum] &= (255 - P4);break;
|
|
case 5 : bitvector[bytenum] &= (255 - P5);break;
|
|
case 6 : bitvector[bytenum] &= (255 - P6);break;
|
|
case 7 : bitvector[bytenum] &= (255 - P7);break;
|
|
default : assert(false);
|
|
}
|
|
} else { // value = true
|
|
switch(bytepos){
|
|
case 0 : bitvector[bytenum] |= P0;break;
|
|
case 1 : bitvector[bytenum] |= P1;break;
|
|
case 2 : bitvector[bytenum] |= P2;break;
|
|
case 3 : bitvector[bytenum] |= P3;break;
|
|
case 4 : bitvector[bytenum] |= P4;break;
|
|
case 5 : bitvector[bytenum] |= P5;break;
|
|
case 6 : bitvector[bytenum] |= P6;break;
|
|
case 7 : bitvector[bytenum] |= P7;break;
|
|
default : assert(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Cluster::SetValueAt(const int pos,const bool value,
|
|
unsigned char bitvector[],
|
|
unsigned char bitvectorT[])const{
|
|
assert(pos>=0 && pos < 512);
|
|
SetValueAtSimple(pos,value,bitvector);
|
|
int pos2 = TranspArray[pos];
|
|
SetValueAtSimple(pos2,value,bitvectorT);
|
|
}
|
|
|
|
|
|
void Cluster::SetValueAt(const int pos, const bool value,
|
|
const bool updateBox){
|
|
SetValueAt(pos,value,BitVector, BitVectorT);
|
|
if(updateBox){
|
|
updateBoxChecks();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
2.2.2 The Transpose function
|
|
|
|
The transpose function modifies this cluster, so that after calling
|
|
this function, the cluster contains the transposed matrices. This can be used
|
|
to define new cluster from existining ones e.g. a ~contains~ cluster from a
|
|
~covered-by~ one.
|
|
|
|
*/
|
|
void Cluster::Transpose(const bool updateBC /*=true*/){
|
|
unsigned char tmp[64];
|
|
memcpy(tmp,BitVector,64);
|
|
memcpy(BitVector,BitVectorT,64);
|
|
memcpy(BitVectorT,tmp,64);
|
|
if(updateBC){
|
|
int btmp = boxchecks;
|
|
boxchecks = boxchecksT;
|
|
boxchecksT = btmp;
|
|
} else {
|
|
boxchecksok = false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
2.2.2 The ToListExpr Function
|
|
|
|
This function converts the Cluster into a representation in nested list format.
|
|
The ListRepresentation is a list containing the name as string atom at the first
|
|
position followed by all matrix numbers of the
|
|
contained 9 intersection matrices.
|
|
|
|
*/
|
|
ListExpr Cluster::ToListExpr(const ListExpr TypeInfo)const{
|
|
if(!IsDefined())
|
|
return nl->SymbolAtom("undefined");
|
|
// check for contained values
|
|
|
|
ListExpr res = nl->OneElemList(nl->StringAtom(name));
|
|
ListExpr last = res;
|
|
for(int i=0;i<512;i++)
|
|
if(ValueAt(i)){
|
|
last = nl->Append(last,nl->IntAtom(i));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
2.2.3 The ReadFrom Function
|
|
|
|
This function reads the value of this cluster from its nested list
|
|
representation. A cluster can be represented in different ways.
|
|
In each case, the first element of the list is a string-atom
|
|
representing the name of this cluster. It is follows from a
|
|
list of representations of 9 intersection matrices or a textual
|
|
representation (string, or text) of the conditions which must hold for this cluster.
|
|
|
|
*/
|
|
bool Cluster::ReadFrom(const ListExpr LE,const ListExpr typeInfo){
|
|
|
|
// first, we handle the case of definition by condition
|
|
// using the tree parser
|
|
if(nl->ListLength(LE)==2 &&
|
|
nl->AtomType(nl->First(LE))==StringType &&
|
|
( nl->AtomType(nl->Second(LE))==StringType ||
|
|
nl->AtomType(nl->Second(LE))==TextType )){
|
|
// Definition by condition
|
|
struct tree* T=0;
|
|
string text;
|
|
if(nl->AtomType(nl->Second(LE))==StringType){
|
|
text = (nl->StringValue(nl->Second(LE)));
|
|
}
|
|
else{
|
|
nl->Text2String(nl->Second(LE),text);
|
|
}
|
|
const char* buffer=text.c_str();
|
|
|
|
if(!parseString(buffer,&T)){
|
|
char* tmp = GetLastMessage();
|
|
if(tmp){
|
|
string message(tmp);
|
|
ErrorReporter::ReportError(message+"\n");
|
|
free(tmp);
|
|
}else{
|
|
ErrorReporter::ReportError("Unknown error while "
|
|
"parsing condition\n");
|
|
}
|
|
return false;
|
|
}
|
|
for(unsigned short i=0;i<512;i++){
|
|
if(evalTree(T,i))
|
|
SetValueAt(i,true,false);
|
|
else
|
|
SetValueAt(i,false,false);
|
|
}
|
|
strcpy(name,nl->StringValue(nl->First(LE)).c_str());
|
|
destroyTree(T);
|
|
updateBoxChecks();
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
The second case is a list containing valid matrices.
|
|
*/
|
|
unsigned char TMP[64];
|
|
STRING_T TMPname;
|
|
// initialize the temporary bitvector
|
|
//for(int i=0;i<64;i++)
|
|
// TMP[i]=0;
|
|
memcpy(TMP,getEmptyBlock(),64);
|
|
|
|
bool correct = true;
|
|
ListExpr scan = LE;
|
|
ListExpr elem;
|
|
// first, get the name of this cluster
|
|
if(nl->ListLength(scan)<1){
|
|
ErrorReporter::ReportError("Clustername missing");
|
|
return false;
|
|
}
|
|
elem = nl->First(scan);
|
|
if(nl->AtomType(elem)!=StringType){
|
|
ErrorReporter::ReportError("The first elem in the"
|
|
" list is not a string");
|
|
return false;
|
|
}
|
|
|
|
strcpy(TMPname, nl->StringValue(elem).c_str());
|
|
scan = nl->Rest(scan);
|
|
Int9M current;
|
|
while(!nl->IsEmpty(scan) && correct){
|
|
elem = nl->First(scan);
|
|
scan = nl->Rest(scan);
|
|
if(!current.ReadFrom(elem,nl->TheEmptyList())){
|
|
correct = false;
|
|
}
|
|
else{
|
|
unsigned short v = current.GetNumber();
|
|
SetValueAt(v,true,TMP,BitVectorT);
|
|
}
|
|
}
|
|
|
|
if(!correct){
|
|
return false;
|
|
}
|
|
memcpy(BitVector,TMP,64);
|
|
strcpy(name,TMPname);
|
|
Transpose(BitVector,BitVectorT);
|
|
SetDefined(true);
|
|
updateBoxChecks();
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
2.2.5 Transpose
|
|
|
|
*/
|
|
void Cluster::Transpose(unsigned char Source[64],
|
|
unsigned char Target[64]){
|
|
for(int i=0;i<512;i++){
|
|
if(ValueAt(i,Source)){
|
|
SetValueAtSimple(TranspArray[i],true,Target);
|
|
} else {
|
|
SetValueAtSimple(TranspArray[i],false,Target);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
2.2.4 Equalize functions
|
|
|
|
Aided by this functions the value of this cluster can be setted to the
|
|
value of another existing cluster.
|
|
|
|
*/
|
|
void Cluster::Equalize(const Cluster& value){
|
|
Equalize(&value);
|
|
}
|
|
|
|
void Cluster::Equalize(const Cluster* value){
|
|
memset(name,'\0',MAX_STRINGSIZE);
|
|
strcpy(name, (char*)value->name);
|
|
memcpy(BitVector,value->BitVector,64);
|
|
memcpy(BitVectorT,value->BitVectorT,64);
|
|
SetDefined(value->IsDefined());
|
|
boxchecks = value->boxchecks;
|
|
boxchecksT = value->boxchecksT;
|
|
boxchecksok = value->boxchecksok;
|
|
}
|
|
|
|
/*
|
|
2.2.5 Compare function
|
|
|
|
The Compare function compares two clusters. Needed for to be an attribute of a tuple.
|
|
|
|
*/
|
|
int Cluster::CompareTo(const Cluster* C)const{
|
|
if(!IsDefined() && !C->IsDefined()){
|
|
return 0;
|
|
}
|
|
if(!IsDefined()){
|
|
return -1;
|
|
}
|
|
if(!C->IsDefined()){
|
|
return 1;
|
|
}
|
|
for(int i=0;i<64;i++){
|
|
if(BitVector[i]<C->BitVector[i]){
|
|
return -1;
|
|
}
|
|
if(BitVector[i]>C->BitVector[i]){
|
|
return 1;
|
|
}
|
|
}
|
|
if(string(name)<string(C->name)){
|
|
return -1;
|
|
}
|
|
if(string(name)>string(C->name)){
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
2.2.6 The Adjacent function
|
|
|
|
We don't want to build ranges over cluster.
|
|
For this reason we just return false here.
|
|
|
|
*/
|
|
bool Cluster::Adjacent(const Attribute*) const{
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
2.2.7 updateBoxChecks
|
|
|
|
This function codes some interesting information into the __boxchecks__
|
|
variable. The information is coded as
|
|
|
|
|
|
* boxchecks [&] 1 > 0: each contained matrix has a 1 entry at positions ii | ib | bi | bb,
|
|
if the boxes are disjoint, this cluster cannot contain the toprel of the corresponding
|
|
objects
|
|
|
|
* boxchecks [&] 2 > 0: each matrix has a 0 entry at positions ei [&] eb [&] ie [&] be,
|
|
if the boxes are non-equal, this cluster cannot contain the toprel of the corresponding
|
|
objects
|
|
|
|
* ...
|
|
|
|
*/
|
|
|
|
void Cluster::updateBoxChecks(const unsigned char* bitvector,
|
|
int& boxchecks){
|
|
boxchecks = 0;
|
|
Int9M m1(1,1,0,1,1,0,0,0,0);
|
|
Int9M m2(0,0,1,0,0,1,1,1,0);
|
|
|
|
Int9M m3(1,1,1,1,1,1,0,0,0);
|
|
Int9M m4(1,1,0,1,1,0,1,1,0);
|
|
|
|
Int9M m5(0,0,1,0,0,1,0,0,0);
|
|
Int9M m6(0,0,0,0,0,0,1,1,0);
|
|
|
|
|
|
int n1 = m1.GetNumber();
|
|
int n2 = m2.GetNumber();
|
|
int n3 = m3.GetNumber();
|
|
int n4 = m4.GetNumber();
|
|
int n5 = m5.GetNumber();
|
|
int n6 = m6.GetNumber();
|
|
|
|
int part_inter = PART_INTER;
|
|
int no_ext_inter = NO_EXT_INTER;
|
|
int o1_empty = O1_EMPTY;
|
|
int o2_empty = O2_EMPTY;
|
|
int o1_non_empty = O1_NON_EMPTY;
|
|
int o2_non_empty = O2_NON_EMPTY;
|
|
int o1_inner = O1_INNER;
|
|
int o2_inner = O2_INNER;
|
|
|
|
|
|
for(unsigned short i=0; i<512; i++){
|
|
if(ValueAt(i,bitvector)){
|
|
if(! ( n1 & i ) ){
|
|
part_inter = 0;
|
|
}
|
|
if( (i & n2) ){
|
|
no_ext_inter = 0;
|
|
}
|
|
if( (i & n3)){
|
|
o1_empty = 0;
|
|
}
|
|
if ((i & n4)){
|
|
o2_empty = 0;
|
|
}
|
|
if(!(i & n3)){
|
|
o1_non_empty = 0;
|
|
}
|
|
if(!(i & n4)){
|
|
o2_non_empty = 0;
|
|
}
|
|
if( (i & n5)){
|
|
o1_inner = false;
|
|
}
|
|
if( (i & n6)){
|
|
o2_inner = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
boxchecks = part_inter | no_ext_inter | o1_empty | o2_empty |
|
|
o1_non_empty | o2_non_empty | o1_inner | o2_inner;
|
|
|
|
}
|
|
|
|
void Cluster::updateBoxChecks(){
|
|
updateBoxChecks(BitVector,boxchecks);
|
|
updateBoxChecks(BitVectorT,boxchecksT);
|
|
boxchecksok = true;
|
|
}
|
|
|
|
/*
|
|
2.2.7 checkBoxes
|
|
|
|
*/
|
|
int Cluster::checkBoxes(const Rectangle<2>& box1, const bool empty1,
|
|
const Rectangle<2>& box2, const bool empty2) const{
|
|
if(!boxchecksok){
|
|
cout << "checkBoxes called but info is not up to date" << endl;
|
|
return 3;
|
|
}
|
|
|
|
if(empty1 && empty2){
|
|
Int9M m(0,0,0,0,0,0,0,0,1);
|
|
if(Contains(m)){
|
|
return 1;
|
|
} else {
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
if(!empty1 && (boxchecks & O1_EMPTY)){
|
|
return 2;
|
|
}
|
|
|
|
if(!empty2 && (boxchecks & O2_EMPTY)){
|
|
return 2;
|
|
}
|
|
|
|
if(empty1 && (boxchecks & O1_NON_EMPTY)){
|
|
return 2;
|
|
}
|
|
|
|
if(empty2 && (boxchecks & O2_NON_EMPTY)){
|
|
return 2;
|
|
}
|
|
|
|
if(boxchecks & PART_INTER){
|
|
if(empty1 || empty2 ){
|
|
return 2;
|
|
}
|
|
if(!box1.Intersects(box2)){
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
if(boxchecks & NO_EXT_INTER){
|
|
if(empty1 || empty2){ // boxes are different
|
|
return 2;
|
|
}
|
|
if(box1 != box2){
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
if(boxchecks & O1_INNER){
|
|
if(!box2.Contains(box1)){
|
|
return 2;
|
|
}
|
|
}
|
|
if(boxchecks & O2_INNER){
|
|
if(!box1.Contains(box2)){
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
|
|
return 3; // nothinng known
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
2.2.9 The HashValue function
|
|
|
|
This function computes a hash value of this cluster.
|
|
|
|
*/
|
|
size_t Cluster::HashValue() const{
|
|
size_t result = 0;
|
|
for(int i=0;i<64;i++)
|
|
result += BitVector[i];
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
2.2.10 CopyFrom
|
|
|
|
Reads the value of this cluster from arg.
|
|
|
|
*/
|
|
void Cluster::CopyFrom(const Attribute* arg){
|
|
Equalize( (Cluster*) arg);
|
|
}
|
|
|
|
/*
|
|
2.2.11 Clone
|
|
|
|
Returns a proper copy of this.
|
|
|
|
*/
|
|
Cluster* Cluster::Clone() const{
|
|
Cluster* res = new Cluster(false);
|
|
res->Equalize(this);
|
|
return res;
|
|
}
|
|
|
|
|
|
/*
|
|
2.2.12 Restrict
|
|
|
|
|
|
This function restricts the matrices contained within this cluster to such ones
|
|
fulfilling the given condition.
|
|
|
|
*/
|
|
|
|
bool Cluster::Restrict(string condition, const bool updateBC /*=true*/){
|
|
|
|
const char* cond_c = condition.c_str();
|
|
struct tree* T=0;
|
|
if(!parseString(cond_c,&T)){
|
|
char* tmp = GetLastMessage();
|
|
if(tmp){
|
|
cmsg.warning() << "Error in parsing condition"
|
|
<<" during performing of Restrict" << endl
|
|
<< tmp << endl;
|
|
cmsg.send();
|
|
free(tmp);
|
|
tmp=0;
|
|
} else{
|
|
cmsg.warning() << "Unknown error while parsing argument of"
|
|
<< " restrict" << endl;
|
|
cmsg.send();
|
|
}
|
|
return false; // don't change this cluster
|
|
}
|
|
for(int i=0;i<512;i++){
|
|
if(!evalTree(T,i)){
|
|
SetValueAt(i,false,false);
|
|
}
|
|
}
|
|
destroyTree(T);
|
|
if(updateBC){
|
|
updateBoxChecks();
|
|
} else {
|
|
boxchecksok = false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
2.2.13 Restrict
|
|
|
|
This version of ~Restrict~ removes all matrices having a different as the given
|
|
value at the specified position. The pos must be from the set [{]II,...,EE[}].
|
|
Otherwise the result will not be as expected.
|
|
|
|
|
|
*/
|
|
void Cluster::Restrict(const int pos, const bool value,
|
|
const bool updateBC/*=true*/){
|
|
for(int i=0;i<512;i++){
|
|
if( ((i&pos) !=0) != value){
|
|
SetValueAt(i,false,false);
|
|
}
|
|
}
|
|
if(updateBC){
|
|
updateBoxChecks();
|
|
} else {
|
|
boxchecksok = false;
|
|
}
|
|
}
|
|
|
|
|
|
void Cluster::Restrict(const Int9M& m, const bool value,
|
|
const bool updateBC/*=true*/){
|
|
int matrix = m.GetNumber();
|
|
if(value){
|
|
for(int i=0; i<512;i++){
|
|
if( (matrix & i) != matrix ){
|
|
SetValueAt(i,false,false);
|
|
}
|
|
}
|
|
} else { // value==false
|
|
matrix = matrix ^ 511;
|
|
for(int i=0; i<512; i++){
|
|
if(((i ^ 511 ) & matrix)!=matrix){
|
|
SetValueAt(i,false,false);
|
|
}
|
|
}
|
|
}
|
|
if(updateBC){
|
|
updateBoxChecks();
|
|
} else {
|
|
boxchecksok = false;
|
|
}
|
|
}
|
|
|
|
|
|
bool Cluster::isExtension(const Int9M& m) const{
|
|
int matrix = m.GetNumber();
|
|
for(int i=0;i<512;i++){
|
|
if(!(ValueAt(i | matrix ))){
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
2.2.12 Relax
|
|
|
|
|
|
This function adds all matrices fulfilling the given condition to
|
|
|
|
*/
|
|
|
|
bool Cluster::Relax(string condition, const bool updateBC /*=true*/){
|
|
|
|
const char* cond_c = condition.c_str();
|
|
struct tree* T=0;
|
|
if(!parseString(cond_c,&T)){
|
|
char* tmp = GetLastMessage();
|
|
if(tmp){
|
|
cmsg.warning() << "Error in parsing condition during performing"
|
|
<< " of Relax" << endl << tmp << endl;
|
|
cmsg.send();
|
|
free(tmp);
|
|
tmp=0;
|
|
} else{
|
|
cmsg.warning() << "Unknown error while parsing argument of Relax"
|
|
<< endl;
|
|
cmsg.send();
|
|
}
|
|
return false; // don't change this cluster
|
|
}
|
|
for(int i=0;i<512;i++){
|
|
if(evalTree(T,i)){
|
|
SetValueAt(i,true,false);
|
|
}
|
|
}
|
|
destroyTree(T);
|
|
if(updateBC){
|
|
updateBoxChecks();
|
|
} else {
|
|
boxchecksok = false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
2.3.12 Operators for comparisons between Clusters
|
|
|
|
*/
|
|
bool Cluster::operator==(const Cluster& C2)const{
|
|
return CompareTo(&C2)==0;
|
|
}
|
|
|
|
bool Cluster::operator<(const Cluster C2)const{
|
|
return CompareTo(&C2)<0;
|
|
}
|
|
|
|
bool Cluster::operator>(const Cluster C2)const{
|
|
return CompareTo(&C2)>0;
|
|
}
|
|
|
|
static int ClusterCompare(const void *a, const void *b){
|
|
Cluster *ca = new ((void*)a) Cluster;
|
|
Cluster *cb = new ((void*)b) Cluster;
|
|
return ca->CompareTo(cb);
|
|
}
|
|
|
|
/*
|
|
2.3 Implementation of PredicateGroup
|
|
|
|
2.3.1 Constructor taking the number of clusters
|
|
|
|
This constructor sets the size of the internal managed
|
|
DBArray to the size specified in size. Additionally,
|
|
a single cluster 'unspecified' containing all possible
|
|
matrices is added.
|
|
|
|
*/
|
|
PredicateGroup::PredicateGroup( const int size ) :
|
|
Attribute(true),
|
|
theClusters( 0 ),
|
|
canDelete( false ),
|
|
sorted(true),
|
|
unSpecified(true)
|
|
{
|
|
// at this point, we defined a single
|
|
// clusters 'unspecified containing all
|
|
// possible 9 intersection matrices
|
|
unSpecified.SetName(&UNSPECIFIED);
|
|
}
|
|
|
|
/*
|
|
2.3.2 The Equalize function
|
|
|
|
When calling this function, the value of this predicate group
|
|
is taken from the argument of this function.
|
|
|
|
*/
|
|
void PredicateGroup::Equalize(const PredicateGroup* PG){
|
|
Cluster tmp;
|
|
Attribute::operator=(*PG);
|
|
sorted = PG->sorted;
|
|
canDelete = PG->canDelete;
|
|
theClusters.copyFrom(PG->theClusters);
|
|
unSpecified.Equalize(PG->unSpecified);
|
|
}
|
|
|
|
/*
|
|
2.3.3 The Compare function
|
|
|
|
This function compares two predicategroups. If needed, the
|
|
clusters contained in this predicategroup or in the argument
|
|
are sorted.
|
|
|
|
*/
|
|
int PredicateGroup::Compare(const Attribute* right) const{
|
|
int cmp;
|
|
const PredicateGroup* PG = static_cast<const PredicateGroup*>(right);
|
|
|
|
if(!IsDefined() && !PG->IsDefined())
|
|
return 0;
|
|
if(!IsDefined() && PG->IsDefined())
|
|
return -1;
|
|
if(IsDefined() && !PG->IsDefined())
|
|
return 1;
|
|
// both predicategroups are defined
|
|
|
|
if( (cmp = unSpecified.CompareTo(&(PG->unSpecified)))!=0)
|
|
return cmp;
|
|
|
|
int size1, size2;
|
|
size1 = theClusters.Size();
|
|
size2 = PG->theClusters.Size();
|
|
if(size1<size2)
|
|
return -1;
|
|
if(size2<size1)
|
|
return 1;
|
|
// size1 == size2
|
|
Cluster tmp1, tmp2;
|
|
|
|
if(!sorted){
|
|
theClusters.Sort(toprel::ClusterCompare);
|
|
sorted=true;
|
|
}
|
|
if(!PG->sorted){
|
|
PG->theClusters.Sort(toprel::ClusterCompare);
|
|
PG->sorted=true;
|
|
}
|
|
|
|
for(int i=0;i<size1;i++){
|
|
theClusters.Get(i,tmp1);
|
|
PG->theClusters.Get(i,tmp2);
|
|
cmp = tmp1.Compare(&tmp2);
|
|
if(cmp != 0)
|
|
return cmp;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
2.3.4 ToString
|
|
|
|
*/
|
|
string PredicateGroup::ToString() const{
|
|
Cluster cc;
|
|
int size = theClusters.Size();
|
|
stringstream o;
|
|
o << "group {";
|
|
for(int i=0;i< size;i++){
|
|
theClusters.Get(i,cc);
|
|
if(i>0) {
|
|
o << ", ";
|
|
}
|
|
o << "[" << (cc) << "]";
|
|
}
|
|
o << "}";
|
|
return o.str();
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
2.3.4 ToListExpr
|
|
|
|
This function computes the external representation of this
|
|
PredicateGroup in nested list format.
|
|
|
|
*/
|
|
ListExpr PredicateGroup::ToListExpr(const ListExpr typeInfo){
|
|
// we have at least one element in the this predicategroup
|
|
if(!IsDefined())
|
|
return nl->SymbolAtom("undefined");
|
|
Cluster C;
|
|
if(theClusters.Size()==0)
|
|
return nl->TheEmptyList();
|
|
|
|
theClusters.Get(0,C);
|
|
ListExpr res = nl->OneElemList(C.ToListExpr(nl->TheEmptyList()));
|
|
ListExpr Last = res;
|
|
for(int i=1;i<theClusters.Size();i++){
|
|
theClusters.Get(i,C);
|
|
Last = nl->Append(Last,C.ToListExpr(nl->TheEmptyList()));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
2.3.5 ReadFrom
|
|
|
|
This function reads the value of this predicategroup from
|
|
instance. If the argument is not a valid representation of a
|
|
predicate-cluster, this predicate cluster is not changed and
|
|
the result will be false.
|
|
|
|
*/
|
|
bool PredicateGroup::ReadFrom(const ListExpr instance, const ListExpr typeInfo){
|
|
int length = nl->ListLength(instance);
|
|
/*
|
|
The maximum count of non-overlapping, non-empty clusters is 512.
|
|
*/
|
|
if(length>512){
|
|
ErrorReporter::ReportError("too many clusters");
|
|
return false;
|
|
}
|
|
unSpecified.MakeEmpty();
|
|
unSpecified.Invert();
|
|
Cluster CurrentCluster(false);
|
|
Cluster* AllClusters = new Cluster[length];
|
|
int pos =0;
|
|
ListExpr LE = instance;
|
|
|
|
while(!nl->IsEmpty(LE)){
|
|
// error in cluster representation
|
|
ListExpr cl = nl->First(LE);
|
|
if(!CurrentCluster.ReadFrom(cl, nl->TheEmptyList())){
|
|
delete[] AllClusters;
|
|
return false;
|
|
}
|
|
// empty clusters are not allowed
|
|
if(CurrentCluster.IsEmpty()){
|
|
ErrorReporter::ReportError("empty clusters are not allowed");
|
|
delete[] AllClusters;
|
|
return false;
|
|
}
|
|
// overlapping cluster found
|
|
if(! unSpecified.Contains(&CurrentCluster)){
|
|
ErrorReporter::ReportError("Clusters overlap");
|
|
delete[] AllClusters;
|
|
return false;
|
|
}
|
|
// check whether name already used
|
|
STRING_T name;
|
|
CurrentCluster.GetName(name);
|
|
for(int i=0;i<pos;i++){
|
|
STRING_T name2;
|
|
AllClusters[i].GetName(name2);
|
|
if(strcmp(name2,name)==0){
|
|
ErrorReporter::ReportError("non disjoint names found");
|
|
delete[] AllClusters;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(strcmp(name,UNSPECIFIED)==0){ // forbidden name
|
|
ErrorReporter::ReportError(" non valid name for cluster");
|
|
delete[] AllClusters;
|
|
return false;
|
|
}
|
|
unSpecified.Minus(&CurrentCluster);
|
|
AllClusters[pos].Equalize(CurrentCluster);
|
|
pos++;
|
|
LE = nl->Rest(LE);
|
|
}
|
|
// if this state is reached, the list representation is correct
|
|
SetDefined(true);
|
|
theClusters.resize(length);
|
|
for(int i=0;i<length;i++)
|
|
theClusters.Put(i,(AllClusters[i]));
|
|
theClusters.Sort(toprel::ClusterCompare);
|
|
sorted=true;
|
|
delete[] AllClusters;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
2.3.6 The ~Add~ Function
|
|
|
|
When this function is called, the argument is added as a new cluster to this predicate
|
|
group. If this is not possible, e.g. because of overlaps with existing clusters
|
|
or name conflicts, the result will be false and this predicate group remains
|
|
unchanged. Empty clusters can't be added.
|
|
|
|
~Note~ : The Cluster is added without correcting the order of clusters in the
|
|
DBArray. Remember to reorder the clusters after calling this function.
|
|
|
|
*/
|
|
bool PredicateGroup::Add(Cluster* C){
|
|
if(C->IsEmpty())
|
|
return false;
|
|
STRING_T name;
|
|
C->GetName(name);
|
|
|
|
if(strcmp(name,UNSPECIFIED)==0){
|
|
return false;
|
|
}
|
|
if(!unSpecified.Contains(C)){ // overlap with existing clusters
|
|
return false;
|
|
}
|
|
// check for name conflicts with existing clusters
|
|
Cluster tmp;
|
|
for(int i=0;i<theClusters.Size();i++){
|
|
theClusters.Get(i,tmp);
|
|
STRING_T name2;
|
|
tmp.GetName(name2);
|
|
if(strcmp(name2,name)==0){
|
|
return false;
|
|
}
|
|
}
|
|
// all ok, add the cluster
|
|
unSpecified.Minus(C);
|
|
theClusters.Append(*C);
|
|
sorted=false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
2.3.6 The ~AddWithPriority~ Function
|
|
|
|
When this function is called, the argument is added as a new cluster to the predicate
|
|
group. If the new cluster overlaps with clusters already contained in the
|
|
predicate group, the common matrices are removed from the new cluster before
|
|
inserting. In case of name conflicts, the result will be false, otherwise the
|
|
result is true and the predicate group will contain the new (shortened) cluster.
|
|
If the cluster is already empty, or if the cluster is empty after removing existing
|
|
matrices, this function will detect an error.
|
|
|
|
~Note~ : The Cluster is added without correcting the order of clusters in the
|
|
DBArray. Remember to reorder the clusters after calling this function.
|
|
|
|
*/
|
|
bool PredicateGroup::AddWithPriority(const Cluster *C){
|
|
if(C->IsEmpty()){
|
|
return false;
|
|
}
|
|
|
|
STRING_T name;
|
|
C->GetName(name);
|
|
if(strcmp(name,UNSPECIFIED)==0){ // name conflict
|
|
return false;
|
|
}
|
|
// check for name conflicts with existing clusters
|
|
Cluster tmp;
|
|
for(int i=0;i<theClusters.Size();i++){
|
|
theClusters.Get(i,tmp);
|
|
STRING_T name2;
|
|
tmp.GetName(name2);
|
|
if(strcmp(name2,name)==0){
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Cluster aux(*C);
|
|
aux.Intersection(&unSpecified); // remove overlapping clusters
|
|
if(aux.IsEmpty())
|
|
return false;
|
|
// all ok, add the cluster
|
|
unSpecified.Minus(&aux);
|
|
theClusters.Append(aux);
|
|
sorted=false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
~GetClusterOf~
|
|
|
|
Returns the clsuetr which has the given name or NULL if
|
|
no cluster found with this name. The Caller of this function
|
|
has to remove the result.
|
|
|
|
*/
|
|
Cluster* PredicateGroup::GetClusterOf(const STRING_T* name)const{
|
|
if(strcmp((*name),UNSPECIFIED)==0){
|
|
Cluster* res = new Cluster();
|
|
res->Equalize(unSpecified);
|
|
return res;
|
|
}
|
|
int size = theClusters.Size();
|
|
Cluster tmp;
|
|
for(int i=0;i<size;i++){
|
|
theClusters.Get(i,tmp);
|
|
STRING_T n;
|
|
tmp.GetName(n);
|
|
if(strcmp(n,*name)==0){
|
|
Cluster* res = new Cluster();
|
|
res->Equalize(&tmp);
|
|
return res;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
Cluster* PredicateGroup::GetClusterOf(const string name)const{
|
|
STRING_T theName;
|
|
strcpy(theName,name.c_str());
|
|
return GetClusterOf(&theName);
|
|
}
|
|
|
|
|
|
/*
|
|
~SetToDefault~
|
|
|
|
Sets this predicate group to a default (constant) value.
|
|
|
|
*/
|
|
void PredicateGroup::SetToDefault(){
|
|
MakeEmpty(); // remove all old stuff
|
|
SetDefined(true);
|
|
canDelete=false;
|
|
ListExpr nlCoveredBy = nl->TwoElemList(
|
|
nl->StringAtom("coveredBy"),
|
|
nl->TextAtom("ii & !ie & ei & bb")
|
|
);
|
|
ListExpr nlDisjoint = nl->TwoElemList(
|
|
nl->StringAtom("disjoint"),
|
|
nl->TextAtom("!ii & !ib & !bi & !bb")
|
|
);
|
|
|
|
ListExpr nlEqual = nl->TwoElemList(
|
|
nl->StringAtom("equal"),
|
|
nl->TextAtom("!ib & !ie & !bi & !be & !ei & !eb")
|
|
);
|
|
ListExpr nlInside =nl->TwoElemList(
|
|
nl->StringAtom("inside"),
|
|
nl->TextAtom("ii & !ie & ei & !bb")
|
|
);
|
|
ListExpr nlMeet = nl->TwoElemList(
|
|
nl->StringAtom("meet"),
|
|
nl->TextAtom("!ii & (ib | bi | bb)")
|
|
);
|
|
ListExpr nlOverlap = nl->TwoElemList(
|
|
nl->StringAtom("overlap"),
|
|
nl->TextAtom("ii & ie & ei")
|
|
);
|
|
bool ok;
|
|
Cluster clEqual(false);
|
|
|
|
ok = clEqual.ReadFrom(nlEqual,nl->TheEmptyList());
|
|
|
|
assert(ok);
|
|
Cluster clInside(false);
|
|
ok = clInside.ReadFrom(nlInside,nl->TheEmptyList());
|
|
assert(ok);
|
|
Cluster clMeet(false);
|
|
ok = clMeet.ReadFrom(nlMeet,nl->TheEmptyList());
|
|
assert(ok);
|
|
Cluster clOverlap(false);
|
|
ok = clOverlap.ReadFrom(nlOverlap,nl->TheEmptyList());
|
|
assert(ok);
|
|
Cluster clCoveredBy(false);
|
|
ok = clCoveredBy.ReadFrom(nlCoveredBy,nl->TheEmptyList());
|
|
assert(ok);
|
|
Cluster clDisjoint(false);
|
|
ok = clDisjoint.ReadFrom(nlDisjoint,nl->TheEmptyList());
|
|
assert(ok);
|
|
Cluster clContains(clInside);
|
|
clContains.Transpose();
|
|
clContains.SetName("contains");
|
|
Cluster clCovers(clCoveredBy);
|
|
clCovers.Transpose();
|
|
clCovers.SetName("covers");
|
|
|
|
ok = AddWithPriority(&clEqual);
|
|
if(!ok) {cerr << "Equal not included" << endl; }
|
|
ok = AddWithPriority(&clInside);
|
|
if(!ok) {cerr << "Inside not included" << endl; }
|
|
ok = AddWithPriority(&clContains);
|
|
if(!ok) {cerr << "Contains not included" << endl; }
|
|
ok = AddWithPriority(&clMeet);
|
|
if(!ok) {cerr << "Meet not included" << endl; }
|
|
ok = AddWithPriority(&clOverlap);
|
|
if(!ok) {cerr << "Overlap not included" << endl; }
|
|
ok = AddWithPriority(&clDisjoint);
|
|
if(!ok) {cerr << "Disjoint not included" << endl; }
|
|
ok = AddWithPriority(&clCoveredBy);
|
|
if(!ok) {cerr << "CoveredBy not included" << endl; }
|
|
ok = AddWithPriority(&clCovers);
|
|
if(!ok) {cerr << "Covers not included" << endl; }
|
|
|
|
theClusters.Sort(toprel::ClusterCompare);
|
|
sorted = true;
|
|
}
|
|
|
|
/*
|
|
3.1.15 Equal Operator
|
|
|
|
*/
|
|
bool PredicateGroup::operator==(const PredicateGroup& I2) const{
|
|
return Compare(&I2)==0;
|
|
}
|
|
|
|
|
|
/*
|
|
4 Defining Type Constructors
|
|
|
|
*/
|
|
|
|
GenTC<Int9M> int9m;
|
|
GenTC<Cluster> cluster;
|
|
GenTC<PredicateGroup> predicategroup;
|
|
|
|
|
|
/*
|
|
7 Definition of Algebra operators
|
|
|
|
7.1 Type Mapping
|
|
|
|
*/
|
|
ListExpr Int9M_Int9M(ListExpr args){
|
|
if(nl->ListLength(args)!=1){
|
|
ErrorReporter::ReportError("wrong number of arguments expected: 1");
|
|
return nl->TypeError();
|
|
}
|
|
ListExpr arg=nl->First(args);
|
|
if(nl->IsEqual(arg,"int9m")){
|
|
ErrorReporter::ReportError("int9m expected");
|
|
return nl->SymbolAtom("int9m");
|
|
}
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr Int9M_Int9M_Int9M(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("two arguments expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"int9m") &&
|
|
nl->IsEqual(nl->Second(args),"int9m")){
|
|
return nl->SymbolAtom("int9m");
|
|
}
|
|
ErrorReporter::ReportError("int9m x int9m expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr Int9M_Int(ListExpr args){
|
|
if(nl->ListLength(args)!=1){
|
|
ErrorReporter::ReportError("One argument expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"int9m")){
|
|
return nl->SymbolAtom(CcInt::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("int9m expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr Cluster_String(ListExpr args){
|
|
if(nl->ListLength(args)!=1){
|
|
ErrorReporter::ReportError("one argument expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"cluster")){
|
|
return nl->SymbolAtom(CcString::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr Cluster_Cluster(ListExpr args){
|
|
if(nl->ListLength(args)!=1){
|
|
ErrorReporter::ReportError("one argument expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"cluster")){
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
ErrorReporter::ReportError("cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr Cluster_Int9M_Cluster(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("two arguments expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"cluster") &&
|
|
nl->IsEqual(nl->Second(args),"int9m")){
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
ErrorReporter::ReportError("cluster x int9m expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr Cluster_Int9M_Bool(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("cluster x int9m expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"cluster") &&
|
|
nl->IsEqual(nl->Second(args),"int9m")){
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("cluster x int9m expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr Cluster_Cluster_Bool(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("cluster x cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"cluster") &&
|
|
nl->IsEqual(nl->Second(args),"cluster")){
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("cluster x cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr TransposeTM(ListExpr args){
|
|
if(nl->ListLength(args)==1){
|
|
if(nl->IsEqual(nl->First(args),"int9m"))
|
|
return nl->SymbolAtom("int9m");
|
|
}
|
|
else if(nl->ListLength(args)==2){
|
|
if(nl->IsEqual(nl->First(args),"cluster") &&
|
|
nl->IsEqual(nl->Second(args),CcString::BasicType()))
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
ErrorReporter::ReportError("int9m or cluster x string expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr Cluster_String_Cluster(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("Two arguments expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(!nl->IsEqual(nl->First(args),"cluster")){
|
|
ErrorReporter::ReportError("First argument must be a cluster");
|
|
return nl->TypeError();
|
|
}
|
|
if(! nl->IsEqual(nl->Second(args),CcString::BasicType())){
|
|
ErrorReporter::ReportError("The second argument must be a string");
|
|
return nl->TypeError();
|
|
}
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
|
|
ListExpr Cluster_Cluster_Cluster(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("cluster x cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"cluster") &&
|
|
nl->IsEqual(nl->Second(args),"cluster")){
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
ErrorReporter::ReportError("cluster x cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr SetOpsTM(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("int9m x int9m or "
|
|
"cluster x cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"cluster") &&
|
|
nl->IsEqual(nl->Second(args),"cluster")){
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"int9m") &&
|
|
nl->IsEqual(nl->Second(args),"int9m")){
|
|
return nl->SymbolAtom("int9m");
|
|
}
|
|
ErrorReporter::ReportError("int9m x int9m or "
|
|
"cluster x cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr InvertTM(ListExpr args){
|
|
if(nl->ListLength(args)!=1){
|
|
ErrorReporter::ReportError("int9m or cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
if(nl->IsEqual(nl->First(args),"cluster")){
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"int9m") ){
|
|
return nl->SymbolAtom("int9m");
|
|
}
|
|
ErrorReporter::ReportError("int9m or cluster expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr CreatePGroupTM(ListExpr args){
|
|
while(!nl->IsEmpty(args)){
|
|
ListExpr current = nl->First(args);
|
|
if(!nl->IsEqual(current,"cluster")){
|
|
ErrorReporter::ReportError("cluster x cluster x ... expected");
|
|
return nl->TypeError();
|
|
}
|
|
args = nl->Rest(args);
|
|
}
|
|
return nl->SymbolAtom("predicategroup");
|
|
}
|
|
|
|
ListExpr CreateValidPGroupTM(ListExpr args){
|
|
if(nl->ListLength(args)<1){
|
|
ErrorReporter::ReportError("At Least one element required");
|
|
return nl->TypeError();
|
|
}
|
|
while(!nl->IsEmpty(args)){
|
|
ListExpr current = nl->First(args);
|
|
if(!nl->IsEqual(current,"cluster")){
|
|
ErrorReporter::ReportError("only clusters are allowed\n");
|
|
return nl->TypeError();
|
|
}
|
|
args = nl->Rest(args);
|
|
}
|
|
return nl->SymbolAtom("predicategroup");
|
|
}
|
|
|
|
ListExpr ClusterName_OfTM(ListExpr args){
|
|
if(nl->ListLength(args)==2){
|
|
if(nl->IsEqual(nl->First(args),"predicategroup") &&
|
|
nl->IsEqual(nl->Second(args),"int9m")){
|
|
return nl->SymbolAtom(CcString::BasicType());
|
|
}
|
|
}
|
|
ErrorReporter::ReportError("predicategroup x int9m expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr ClusterOfTM(ListExpr args){
|
|
if(nl->ListLength(args)==2){
|
|
if(nl->IsEqual(nl->First(args),"predicategroup") &&
|
|
nl->IsEqual(nl->Second(args),"int9m")){
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
}
|
|
ErrorReporter::ReportError("predicategroup x int9m expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr GetClusterTM(ListExpr args){
|
|
if(nl->ListLength(args)==2){
|
|
if(nl->IsEqual(nl->First(args),"predicategroup") &&
|
|
nl->IsEqual(nl->Second(args),CcString::BasicType())){
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
}
|
|
ErrorReporter::ReportError("predicategroup x string expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr SizeOfTM(ListExpr args){
|
|
if(nl->ListLength(args)==1){
|
|
if(nl->IsEqual(nl->First(args),"cluster") |
|
|
nl->IsEqual(nl->First(args),"predicategroup")){
|
|
return nl->SymbolAtom(CcInt::BasicType());
|
|
} else {
|
|
ErrorReporter::ReportError("TopRel: SizeOf expects a cluster "
|
|
"or a predicategroup\n");
|
|
return nl->TypeError();
|
|
}
|
|
}
|
|
ErrorReporter::ReportError("TopRel: Wrong number of"
|
|
" arguments for sizeof\n");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr CreateClusterTM(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("CreateCluster expects 2 arguments\n");
|
|
return nl->TypeError();
|
|
}
|
|
if( nl->IsEqual(nl->First(args),CcString::BasicType()) &&
|
|
(nl->IsEqual(nl->Second(args),CcString::BasicType()) ||
|
|
nl->IsEqual(nl->Second(args),FText::BasicType())))
|
|
return nl->SymbolAtom("cluster");
|
|
ErrorReporter::ReportError("CreateCluster requires"
|
|
" string x {string,text} as arguments\n");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr IsCompleteTM(ListExpr args){
|
|
if(nl->ListLength(args)!=1){
|
|
ErrorReporter::ReportError("IsComplete has one element\n");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"predicategroup")){
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("IsComplete"
|
|
" needs a predicategroup as argument\n");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr UnSpecifiedTM(ListExpr args){
|
|
if(nl->ListLength(args)!=1){
|
|
ErrorReporter::ReportError("unspecified needs one element\n");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"predicategroup")){
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
ErrorReporter::ReportError("unspecified"
|
|
" needs a predicategroup as argument\n");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr MultiSetOpsTM(ListExpr args){
|
|
if(nl->ListLength(args)<1){
|
|
ErrorReporter::ReportError("At least one argument required\n");
|
|
return nl->TypeError();
|
|
}
|
|
ListExpr rest = nl->Rest(args);
|
|
if(nl->IsEqual(nl->First(args),"int9m")){
|
|
while(!nl->IsEmpty(rest)){
|
|
if(!nl->IsEqual(nl->First(rest),"int9m")){
|
|
ErrorReporter::ReportError("elements must be from"
|
|
" the same type");
|
|
return nl->TypeError();
|
|
}
|
|
rest = nl->Rest(rest);
|
|
}
|
|
return nl->SymbolAtom("int9m");
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"cluster")){
|
|
while(!nl->IsEmpty(rest)){
|
|
if(!nl->IsEqual(nl->First(rest),"cluster")){
|
|
ErrorReporter::ReportError("elements must be from the"
|
|
" same type");
|
|
return nl->TypeError();
|
|
}
|
|
rest = nl->Rest(rest);
|
|
}
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
ErrorReporter::ReportError("int9m or cluster required");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr PWDisjointTM(ListExpr args){
|
|
ListExpr rest = args;
|
|
while(!nl->IsEmpty(rest)){
|
|
if(!nl->IsEqual(nl->First(rest),"cluster")){
|
|
ErrorReporter::ReportError("elements must be of type cluster");
|
|
return nl->TypeError();
|
|
}
|
|
rest = nl->Rest(rest);
|
|
}
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
|
}
|
|
|
|
|
|
ListExpr RestrictRelaxTM(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("Restrict and Relax require two arguments\n");
|
|
return nl->TypeError();
|
|
}
|
|
if(!nl->IsEqual(nl->First(args),"cluster")){
|
|
ErrorReporter::ReportError("Restrict and Relax require"
|
|
" cluster as first argument \n");
|
|
return nl->TypeError();
|
|
}
|
|
if(!nl->IsEqual(nl->Second(args),CcString::BasicType()) &&
|
|
!nl->IsEqual(nl->Second(args),FText::BasicType())){
|
|
ErrorReporter::ReportError("Restrict and Relax require string or text"
|
|
" as second argument ");
|
|
return nl->TypeError();
|
|
}
|
|
return nl->SymbolAtom("cluster");
|
|
}
|
|
|
|
|
|
ListExpr StdPGroup_TM(ListExpr args){
|
|
if(nl->ListLength(args)==0){
|
|
return nl->SymbolAtom("predicategroup");
|
|
}
|
|
ErrorReporter::ReportError("stdpgroup does not expect any argument.");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
|
|
ListExpr TopRelEqualsTM(ListExpr args){
|
|
if(nl->ListLength(args)!=2){
|
|
ErrorReporter::ReportError("two arguments required");
|
|
return nl->TypeError();
|
|
}
|
|
if(!nl->Equal(nl->First(args),nl->Second(args))){
|
|
ErrorReporter::ReportError("cannot compare different types");
|
|
return nl->TypeError();
|
|
}
|
|
if(nl->IsEqual(nl->First(args),"int9m") ||
|
|
nl->IsEqual(nl->First(args),"cluster") ||
|
|
nl->IsEqual(nl->First(args),"predicategroup")){
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("int9m, cluster, or predicategroup expected");
|
|
return nl->TypeError();
|
|
}
|
|
|
|
|
|
/*
|
|
7.2 Value Mappings
|
|
|
|
*/
|
|
int Transpose_Int9M_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Int9M* a = (Int9M*) args[0].addr;
|
|
Int9M* res = (Int9M*) result.addr;
|
|
if(res->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Transpose();
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Transpose_Cluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
CcString* b = (CcString*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Transpose();
|
|
res->SetName(b->GetStringval());
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Invert_Int9M_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Int9M* a = (Int9M*) args[0].addr;
|
|
Int9M* res = (Int9M*) result.addr;
|
|
if(a->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Invert();
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Union_Int9M_Int9M_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Int9M* a = (Int9M*) args[0].addr;
|
|
Int9M* b = (Int9M*) args[1].addr;
|
|
Int9M* res = (Int9M*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Union(b);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int MultiIntersection_Int9M_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Int9M* a = (Int9M*) args[0].addr;
|
|
Int9M* res = (Int9M*) result.addr;
|
|
if(a->IsDefined()){
|
|
res->Equalize(a);
|
|
int sons = qp->GetNoSons(s);
|
|
for(int i=1;i<sons;i++){
|
|
a = static_cast<Int9M*>(args[i].addr);
|
|
if(!a->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
res->Intersection(a);
|
|
}
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Intersection_Int9M_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Int9M* a = (Int9M*) args[0].addr;
|
|
Int9M* b = (Int9M*) args[1].addr;
|
|
Int9M* res = (Int9M*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Intersection(b);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Disjoint_Cluster_Cluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Cluster* b = (Cluster*) args[1].addr;
|
|
CcBool* res = (CcBool*) result.addr;
|
|
if(a->IsDefined() && a->IsDefined()){
|
|
res->Set(true,a->Disjoint(b));
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int PWDisjoint_Cluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
int sons = qp->GetNoSons(s);
|
|
Cluster All;
|
|
All.MakeEmpty();
|
|
CcBool* res = static_cast<CcBool*>(result.addr);
|
|
|
|
bool resvalue = true;
|
|
for(int i=0;i<sons && resvalue ;i++){
|
|
Cluster* c = static_cast<Cluster*>(args[i].addr);
|
|
if(!c->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
if(All.Intersects(c)){
|
|
resvalue=false;
|
|
}
|
|
All.Union(c);
|
|
}
|
|
res->Set(true,resvalue);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int Add_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Int9M* b = (Int9M*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
unsigned short number = b->GetNumber();
|
|
res->Equalize(a);
|
|
res->SetValueAt(number,true);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Remove_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Int9M* b = (Int9M*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
unsigned short number = b->GetNumber();
|
|
res->Equalize(a);
|
|
res->SetValueAt(number,false);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int NumberOf_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Int9M* a = (Int9M*) args[0].addr;
|
|
CcInt* res = (CcInt*) result.addr;
|
|
if(a->IsDefined()){
|
|
res->Set(true,a->GetNumber());
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int NameOf_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
CcString* res = (CcString*) result.addr;
|
|
if(a->IsDefined()){
|
|
STRING_T name;
|
|
a->GetName(name);
|
|
res->Set(true,name);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Rename_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
CcString* b = (CcString*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
res->Equalize(a);
|
|
res->SetName(b->GetStringval());
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Contains_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Int9M* b = (Int9M*) args[1].addr;
|
|
CcBool* res = (CcBool*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
res->Set(true,a->ValueAt(b->GetNumber()));
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Union_Cluster_Cluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Cluster* b = (Cluster*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Union(b);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int MultiIntersection_Cluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(!a->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
res->Equalize(a);
|
|
int sons = qp->GetNoSons(s);
|
|
for(int i=1;i<sons;i++){
|
|
a = static_cast<Cluster*>(args[i].addr);
|
|
if(!a->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
res->Intersection(a);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Intersection_Cluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Cluster* b = (Cluster*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Intersection(b);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Minus_Cluster_Cluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Cluster* b = (Cluster*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(a->IsDefined() && b->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Minus(b);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Invert_Cluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* a = (Cluster*) args[0].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
if(a->IsDefined()){
|
|
res->Equalize(a);
|
|
res->Invert();
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template<class T>
|
|
int Restrict_Cluster_T_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* cluster = (Cluster*) args[0].addr;
|
|
T* cond = (T*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
|
|
if(cluster->IsDefined() && cond->IsDefined()){
|
|
string cond_s = cond->GetValue();
|
|
res->Equalize(cluster);
|
|
res->Restrict(cond_s);
|
|
}else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template<class T>
|
|
int Relax_Cluster_T_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* cluster = (Cluster*) args[0].addr;
|
|
T* cond = (T*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
|
|
if(cluster->IsDefined() && cond->IsDefined()){
|
|
string cond_s = cond->GetValue();
|
|
res->Equalize(cluster);
|
|
res->Relax(cond_s);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int CreatePGroup_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
PredicateGroup* res = (PredicateGroup*) result.addr;
|
|
//get the number of arguments
|
|
int arg_count = qp->GetNoSons(s);
|
|
res->MakeEmpty();
|
|
bool error = false;
|
|
for(int i=0;i<arg_count && ! error; i++){
|
|
Cluster* c = static_cast<Cluster*>(args[i].addr);
|
|
if(!c->IsDefined()){
|
|
res->SetDefined(false);
|
|
return false;
|
|
}
|
|
error = !res->Add(c);
|
|
}
|
|
if(error){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
} else {
|
|
res->SetDefined(true);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CreatePriorityPGroup_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
|
|
result = qp->ResultStorage(s);
|
|
PredicateGroup* res = (PredicateGroup*) result.addr;
|
|
//get the number of arguments
|
|
int arg_count = qp->GetNoSons(s);
|
|
res->MakeEmpty();
|
|
bool error = false;
|
|
for(int i=0;i<arg_count && ! error; i++){
|
|
Cluster* c = static_cast<Cluster*>(args[i].addr);
|
|
if(!c->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
error = !res->AddWithPriority(c);
|
|
}
|
|
if(error){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
} else {
|
|
res->SetDefined(true);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CreateValidPGroup_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
PredicateGroup* res = (PredicateGroup*) result.addr;
|
|
Cluster* Valid = (Cluster*)args[0].addr;
|
|
|
|
if(!Valid->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
|
|
//get the number of arguments
|
|
int arg_count = qp->GetNoSons(s);
|
|
res->MakeEmpty();
|
|
bool error = false;
|
|
Cluster* Current;
|
|
for(int i=1;i<arg_count && ! error; i++){
|
|
Current = (Cluster*) args[i].addr;
|
|
if(!Current->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
Current->Intersection(Valid);
|
|
error = !res->Add(Current);
|
|
}
|
|
if(error){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
} else {
|
|
res->SetDefined(true);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ClusterNameOf_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
PredicateGroup* PG = (PredicateGroup*) args[0].addr;
|
|
Int9M* IM = (Int9M*) args[1].addr;
|
|
CcString* res = (CcString*) result.addr;
|
|
if(PG->IsDefined() && IM->IsDefined()){
|
|
STRING_T name;
|
|
PG->GetNameOf(IM, name);
|
|
res->Set(true, name);
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ClusterOf_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
PredicateGroup* PG = (PredicateGroup*) args[0].addr;
|
|
Int9M* IM = (Int9M*) args[1].addr;
|
|
Cluster* res = (Cluster*) result.addr;
|
|
|
|
if(!IM->IsDefined() || !PG->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
Cluster* tmp = PG->GetClusterOf(*IM);
|
|
if(!tmp){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
res->Equalize(tmp);
|
|
delete tmp;
|
|
return 0;
|
|
}
|
|
|
|
int GetCluster_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
PredicateGroup* PG = static_cast<PredicateGroup*>(args[0].addr);
|
|
CcString* name = static_cast<CcString*>(args[1].addr);
|
|
Cluster* res = static_cast<Cluster*>(result.addr);
|
|
|
|
if(!PG->IsDefined() || !name->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
|
|
const STRING_T* str = name->GetStringval();
|
|
|
|
Cluster* tmp = PG->GetClusterOf(str);
|
|
|
|
if(!tmp){ // name not found
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
res->Equalize(tmp);
|
|
delete tmp;
|
|
return 0;
|
|
}
|
|
|
|
template<class T>
|
|
int SizeOf_T_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
T* arg = (T*) args[0].addr;
|
|
CcInt* res = static_cast<CcInt*>(result.addr);
|
|
if(arg->IsDefined()){
|
|
res->Set(true,arg->Size());
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template<class T>
|
|
int CreateCluster_T_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
Cluster* res = (Cluster*) result.addr;
|
|
CcString* arg1 = (CcString*) args[0].addr; // name
|
|
T* arg2 = (T*) args[1].addr; // description
|
|
|
|
if(!arg1->IsDefined() || !arg2->IsDefined()){
|
|
res->SetDefined(false);
|
|
return 0;
|
|
}
|
|
|
|
string cond = arg2->GetValue();
|
|
struct tree* t=0;
|
|
if(!parseString(cond.c_str(),&t)){
|
|
char* Emsg = GetLastMessage();
|
|
ErrorReporter::ReportError(string(Emsg)+"\n");
|
|
free(Emsg);
|
|
((Cluster*)result.addr)->SetDefined(false);
|
|
return 0;
|
|
}
|
|
// parsing successful
|
|
res->SetName(arg1->GetStringval());
|
|
res->MakeEmpty();
|
|
for(unsigned short i=0;i<512;i++){
|
|
if(evalTree(t,i)){
|
|
res->SetValueAt(i,true);
|
|
}
|
|
}
|
|
destroyTree(t);
|
|
return 0;
|
|
}
|
|
|
|
int IsComplete_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
PredicateGroup* arg = (PredicateGroup*) args[0].addr;
|
|
CcBool* res = static_cast<CcBool*>(result.addr);
|
|
if(arg->IsDefined()){
|
|
res->Set(true,arg->IsComplete());
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int UnSpecified_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
PredicateGroup* PG = (PredicateGroup*) args[0].addr;
|
|
Cluster* res = static_cast<Cluster*>(result.addr);
|
|
if(PG->IsDefined()){
|
|
res->Equalize(PG->GetUnspecified());
|
|
} else {
|
|
res->SetDefined(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int StdPGroup_Fun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result= qp->ResultStorage(s);
|
|
((PredicateGroup*) result.addr)->SetToDefault();
|
|
return 0;
|
|
}
|
|
|
|
|
|
template <class A>
|
|
int TopRelEqualsFun(Word* args, Word& result, int message,
|
|
Word& local, Supplier s){
|
|
result = qp->ResultStorage(s);
|
|
A* a1 = (A*) args[0].addr;
|
|
A* a2 = (A*) args[1].addr;
|
|
CcBool* res = (CcBool*) result.addr;
|
|
if(!a1->IsDefined() || !a2->IsDefined()){
|
|
res->Set(false,false);
|
|
} else {
|
|
res->Set(true, (*a1)==(*a2));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
7.3 Specification of operators
|
|
|
|
*/
|
|
const string TransposeSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example 1\""
|
|
" \"Example 2\" )"
|
|
" ( <text> int9m -> int9m | cluster x string -> cluster </text--->"
|
|
" \" transpose(_ [,_] ) \" "
|
|
" <text>returns the transposed matrix, or "
|
|
"the renamed cluster where all contained matrices"
|
|
" was transposed</text---> "
|
|
" \"query transpose(IM) ;\""
|
|
" <text>let contains=transpose(inside,\"contains\");</text---> ))";
|
|
|
|
const string InvertSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" t -> t , t in {int9m,cluster}\""
|
|
" \" invert(_) \" "
|
|
" \"returns the inverted element \" "
|
|
" \" query invert(IM)\" ))";
|
|
|
|
const string UnionSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( <text>type_i x type_i -> type_i ,"
|
|
" where type_i in {int9m,cluster} </text---> "
|
|
" \" _ union _ \" "
|
|
" \" union function \" "
|
|
" \" query i1 union i2 \" ))";
|
|
|
|
const string IntersectionSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( <text>type_i x type_i -> type_i ,"
|
|
" where type_i in {int9m,cluster} </text---> "
|
|
" \" _ intersection _ \" "
|
|
" \" intersection function \" "
|
|
" \" query i1 intersection i2 \" ))";
|
|
|
|
const string MultiIntersectionSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( <text>t x t x ... xt -> t,"
|
|
" where t in {int9m, cluster} </text---> "
|
|
" \" multiintersection (_,_,...) \" "
|
|
" \" computes the subset included in all arguments \" "
|
|
" \" query multiintersection(c1,c2,c3) \" ))";
|
|
|
|
const string AddSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x int9m -> cluster\""
|
|
" \" _ + _ \" "
|
|
" \"inserts a new int9m to the cluster \" "
|
|
" \" query c + i \" ))";
|
|
|
|
const string RemoveSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x int9m -> cluster\""
|
|
" \" _ - _ \" "
|
|
" \"removes a int9m from the cluster \" "
|
|
" \" query c - i \" ))";
|
|
|
|
const string MinusSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x cluster -> cluster\""
|
|
" \" _ - _ \" "
|
|
" <text>removes the elements of o cluster from other one </text---> "
|
|
" \" query c1 - c2 \" ))";
|
|
|
|
const string NumberOfSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"int9m -> int\""
|
|
" \" number_of(_) \" "
|
|
" \"returns the matrix number \" "
|
|
" \" query number_of(i) \" ))";
|
|
|
|
const string NameOfSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster -> string\""
|
|
" \" name_of(_) \" "
|
|
" \"returns the name of this cluster \" "
|
|
" \" query name_of(c) \" ))";
|
|
|
|
const string RenameSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x string -> cluster\""
|
|
" \" _ renamecluster[ _ ] \" "
|
|
" \"changes the name of a cluster \" "
|
|
" \" query c renamecluster[\"inside\"] \" ))";
|
|
|
|
const string ContainsSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x int9m -> bool\""
|
|
" \" _ contains _ \" "
|
|
" <text>checks whether the second element"
|
|
" is member of the first one </text---> "
|
|
" \" query c contains i \" ))";
|
|
|
|
const string DisjointSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x cluster -> bool\""
|
|
" \" _ disjoint _ \" "
|
|
" \"checks whether the clusters are disjoint\" "
|
|
" \" query c1 disjoint c2 \" ))";
|
|
|
|
const string CreatePGroupSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x cluster x ... -> predicategroup\""
|
|
" \" createpgroup( _, _, ... ) \" "
|
|
" \"creates a predicate group from existing clusters\" "
|
|
" \" let pc1 = createpgroup(c1, c2, c3) \" ))";
|
|
|
|
const string CreatePriorityPGroupSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x cluster x ... -> predicategroup\""
|
|
" \" createprioritypgroup( _, _, ... ) \" "
|
|
" <text>creates a predicate group from existing clusters "
|
|
" If Clusters are overlapping, the common matrixes are "
|
|
" assigned to the attribute located prior in the "
|
|
"arglist </text--->"
|
|
" \" let pc1 = createprioritypgroup(c1, c2, c3) \" ))";
|
|
|
|
const string CreateValidPGroupSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"cluster x cluster x ... -> predicategroup\""
|
|
" \" createvalidpgroup( _ _ ... ) \" "
|
|
" <text>creates a predicate group from existing clusters "
|
|
" The first cluster defines all valid matrices </text--->"
|
|
" \" let pc1 = createvalidpgroup(valid, c1, c2, c3) \" ))";
|
|
|
|
const string ClusterNameOf_pc_m_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"predicategroup x int9m -> string\""
|
|
" \" clustername_of(_ , _) \" "
|
|
" <text>returns the name of the matrix in the given "
|
|
" predicategroup </text---> "
|
|
" <text>query clustername_of(StdPG,m1)="
|
|
"\"inside\" </text---> ))";
|
|
|
|
const string ClusterOf_pc_m_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \"predicategroup x int9m -> cluster\""
|
|
" \" clusterof(_ , _) \" "
|
|
" <text>returns the predicate group containing the matrix</text---> "
|
|
" <text>query clusterof(StdPG,m1) </text---> ))";
|
|
|
|
const string SizeOf_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" {cluster, predicategroup} -> int \""
|
|
" \" sizeof(_)\" "
|
|
" \"returns the number of elements in the argument\" "
|
|
" <text>query sizeof(p) </text---> ))";
|
|
|
|
const string CreateCluster_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" string x {text, string} -> cluster \""
|
|
" \" createcluster(_ , _)\" "
|
|
" <text>creates an cluster with given name and condition</text---> "
|
|
" <text>query createcluster(\"test\",\"ii & !ee\") </text---> ))";
|
|
|
|
const string IsComplete_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" predicategroup -> bool \""
|
|
" \" isComplete(_) \" "
|
|
" <text>checks whether the clusters contained in the argument "
|
|
" cover all 512 possible matrices </text--->"
|
|
" \" query isComplete(stdpg) \"))";
|
|
|
|
const string UnSpecified_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" predicategroup -> cluster \""
|
|
" \" unspecified(_) \" "
|
|
" <text>returns the cluster containing all"
|
|
" non-used matrices </text---> "
|
|
" \" query unspecified(stdpg) \"))";
|
|
|
|
|
|
const string PWDisjoint_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" cluster x cluster x ... -> bool \""
|
|
" \" pwdisjoint(_,_,...) \" "
|
|
" <text>checks whether the arguments are pairwise"
|
|
" disjoint </text---> "
|
|
" \" query pwdisjoint(c1,c2,c3) \"))";
|
|
|
|
|
|
const string Restrict_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" cluster x {string, text} -> cluster \""
|
|
" \" restrict(_, _) \" "
|
|
" <text>restricts the arguments cluster to such matrices fulfilling"
|
|
" the condition of the second argument </text---> "
|
|
" <text> query restrict(c1, \"ee & ii\" )</text--->))";
|
|
|
|
|
|
const string Relax_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" cluster x {string, text} -> cluster \""
|
|
" \" relax(_, _) \" "
|
|
" <text>add all matrices fulfilling "
|
|
" the condition of the second argument to the cluster </text---> "
|
|
" <text> query relax(c1,\" ee & ii\") </text--->))";
|
|
|
|
const string StdPGroup_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" -> predicategroup \""
|
|
" \" predicategroup() \" "
|
|
" <text>Computes a default predicategroup.</text---> "
|
|
" <text> query stdpgroup() </text--->))";
|
|
|
|
|
|
const string TopRelEqualsSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( <text>t x t -> bool , t in {int9m, cluster, predicategroup}</text--->"
|
|
" \" _ = _ \" "
|
|
" <text>Check for equality</text---> "
|
|
" <text> query [const int9m value 3] = [const int9m value 4] "
|
|
"</text--->))";
|
|
|
|
|
|
const string GetClusterSpec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( <text>predicategroup x string -> cluster</text--->"
|
|
" \" clusterof(group,name) \" "
|
|
" <text>returns the cluster in group specified by name</text---> "
|
|
" <text> query clusterof(std,\"equals\") "
|
|
"</text--->))";
|
|
|
|
/*
|
|
|
|
This specification is for debugging only.
|
|
|
|
*/
|
|
const string STD_Spec =
|
|
"((\"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
" ( \" ---signature--- \""
|
|
" \" ---syntax--- \" "
|
|
" \" ---meaning---\""
|
|
" \" ---example--- \"))";
|
|
|
|
/*
|
|
7.4 Value Mapping Array for overloaded operators
|
|
|
|
*/
|
|
ValueMapping TransposeMap[] = { Transpose_Int9M_Fun,
|
|
Transpose_Cluster_Fun };
|
|
ValueMapping UnionMap[] = { Union_Int9M_Int9M_Fun,
|
|
Union_Cluster_Cluster_Fun };
|
|
ValueMapping InvertMap[] = { Invert_Int9M_Fun, Invert_Cluster_Fun };
|
|
ValueMapping MultiIntersectionMap[] = { MultiIntersection_Int9M_Fun,
|
|
MultiIntersection_Cluster_Fun };
|
|
|
|
ValueMapping IntersectionMap[] = { Intersection_Int9M_Fun,
|
|
Intersection_Cluster_Fun };
|
|
|
|
ValueMapping SizeOfMap[] = { SizeOf_T_Fun<Cluster>,
|
|
SizeOf_T_Fun<PredicateGroup>};
|
|
|
|
ValueMapping CreateClusterMap[] = { CreateCluster_T_Fun<CcString>,
|
|
CreateCluster_T_Fun<FText>};
|
|
|
|
ValueMapping RestrictMap[] = { Restrict_Cluster_T_Fun<CcString>,
|
|
Restrict_Cluster_T_Fun<FText>};
|
|
|
|
ValueMapping RelaxMap[] = { Relax_Cluster_T_Fun<CcString>,
|
|
Relax_Cluster_T_Fun<FText>};
|
|
|
|
ValueMapping TopRelEqualsMap[] = { TopRelEqualsFun<Int9M>,
|
|
TopRelEqualsFun<Cluster>,
|
|
TopRelEqualsFun<PredicateGroup>};
|
|
/*
|
|
7.6 Selection Functions
|
|
|
|
*/
|
|
static int TransposeSelect(ListExpr args){
|
|
if(nl->IsEqual(nl->First(args),"int9m"))
|
|
return 0;
|
|
if(nl->IsEqual(nl->First(args),"cluster") &&
|
|
nl->IsEqual(nl->Second(args),CcString::BasicType()))
|
|
return 1;
|
|
return -1; // should never be reached
|
|
}
|
|
|
|
static int SetOpsSelect(ListExpr args){
|
|
if(nl->IsEqual(nl->First(args),"int9m"))
|
|
return 0;
|
|
if(nl->IsEqual(nl->First(args),"cluster"))
|
|
return 1;
|
|
return -1; // should never be reached
|
|
}
|
|
|
|
static int InvertSelect(ListExpr args){
|
|
if(nl->IsEqual(nl->First(args),"int9m"))
|
|
return 0;
|
|
if(nl->IsEqual(nl->First(args),"cluster"))
|
|
return 1;
|
|
return -1; // should never be reached
|
|
}
|
|
|
|
static int SizeOfSelect(ListExpr args){
|
|
if(nl->IsEqual(nl->First(args),"cluster"))
|
|
return 0;
|
|
if(nl->IsEqual(nl->First(args),"predicategroup"))
|
|
return 1;
|
|
return -1; // should never be reached
|
|
}
|
|
|
|
static int CreateClusterSelect(ListExpr args){
|
|
if(nl->IsEqual(nl->Second(args),CcString::BasicType()))
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
static int RestrictSelect(ListExpr args){
|
|
if(nl->IsEqual(nl->Second(args),CcString::BasicType()))
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
static int RelaxSelect(ListExpr args){
|
|
if(nl->IsEqual(nl->Second(args),CcString::BasicType()))
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
static int TopRelEqualsSelect(ListExpr args){
|
|
string a1 = nl->SymbolValue(nl->First(args));
|
|
if(a1=="int9m") return 0;
|
|
if(a1=="cluster") return 1;
|
|
if(a1=="predicategroup") return 2;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
7.7 Definition of operators
|
|
|
|
*/
|
|
Operator toprel_equals(
|
|
"=", // name
|
|
TopRelEqualsSpec, // specification
|
|
3, // number of functions
|
|
TopRelEqualsMap, // array of value mappings
|
|
TopRelEqualsSelect,
|
|
TopRelEqualsTM);
|
|
|
|
Operator transpose(
|
|
"transpose", // name
|
|
TransposeSpec, // specification
|
|
2, // number of functions
|
|
TransposeMap, // array of value mappings
|
|
TransposeSelect,
|
|
TransposeTM);
|
|
|
|
Operator union_op(
|
|
"union", // name
|
|
UnionSpec, // specification
|
|
2, // number of functions
|
|
UnionMap, // array of value mappings
|
|
SetOpsSelect,
|
|
SetOpsTM);
|
|
|
|
Operator multiintersection(
|
|
"multiintersection", // name
|
|
MultiIntersectionSpec, // specification
|
|
2, // number of functions
|
|
MultiIntersectionMap, // array of value mappings
|
|
SetOpsSelect,
|
|
MultiSetOpsTM);
|
|
|
|
Operator intersection(
|
|
"intersection", // name
|
|
IntersectionSpec, // specification
|
|
2, // number of functions
|
|
IntersectionMap, // array of value mappings
|
|
SetOpsSelect,
|
|
SetOpsTM);
|
|
|
|
Operator invert(
|
|
"invert", // name
|
|
InvertSpec, // specification
|
|
2, // number of functions
|
|
InvertMap, // array of value mappings
|
|
InvertSelect,
|
|
InvertTM);
|
|
|
|
Operator sizeof_op(
|
|
"size", // name
|
|
SizeOf_Spec, // specification
|
|
2, // number of functions
|
|
SizeOfMap, // array of value mappings
|
|
SizeOfSelect,
|
|
SizeOfTM);
|
|
|
|
Operator restrict_op(
|
|
"restrict", // name
|
|
Restrict_Spec, // specification
|
|
2, // number of functions
|
|
RestrictMap, // array of value mappings
|
|
RestrictSelect,
|
|
RestrictRelaxTM);
|
|
|
|
Operator relax_op(
|
|
"relax", // name
|
|
Relax_Spec, // specification
|
|
2, // number of functions
|
|
RelaxMap, // array of value mappings
|
|
RelaxSelect,
|
|
RestrictRelaxTM);
|
|
|
|
Operator createcluster(
|
|
"createcluster", // name
|
|
CreateCluster_Spec, // specification
|
|
2, // number of functions
|
|
CreateClusterMap, // array of value mappings
|
|
CreateClusterSelect,
|
|
CreateClusterTM);
|
|
|
|
Operator add(
|
|
"+", // name
|
|
AddSpec, // specification
|
|
Add_Fun,
|
|
Operator::SimpleSelect,
|
|
Cluster_Int9M_Cluster);
|
|
|
|
Operator pwdisjoint(
|
|
"pwdisjoint", // name
|
|
PWDisjoint_Spec, // specification
|
|
PWDisjoint_Cluster_Fun,
|
|
Operator::SimpleSelect,
|
|
PWDisjointTM);
|
|
|
|
Operator getcluster(
|
|
"getcluster", // name
|
|
GetClusterSpec, // specification
|
|
GetCluster_Fun,
|
|
Operator::SimpleSelect,
|
|
GetClusterTM);
|
|
|
|
Operator unspecified(
|
|
"unspecified", // name
|
|
UnSpecified_Spec, // specification
|
|
UnSpecified_Fun,
|
|
Operator::SimpleSelect,
|
|
UnSpecifiedTM);
|
|
|
|
Operator iscomplete(
|
|
"isComplete", // name
|
|
IsComplete_Spec, // specification
|
|
IsComplete_Fun,
|
|
Operator::SimpleSelect,
|
|
IsCompleteTM);
|
|
|
|
Operator minus(
|
|
"-", // name
|
|
MinusSpec, // specification
|
|
Minus_Cluster_Cluster_Fun,
|
|
Operator::SimpleSelect,
|
|
Cluster_Cluster_Cluster);
|
|
|
|
Operator remove(
|
|
"-", // name
|
|
RemoveSpec, // specification
|
|
Remove_Fun,
|
|
Operator::SimpleSelect,
|
|
Cluster_Int9M_Cluster);
|
|
|
|
Operator number_of(
|
|
"number_of", // name
|
|
NumberOfSpec, // specification
|
|
NumberOf_Fun,
|
|
Operator::SimpleSelect,
|
|
Int9M_Int);
|
|
|
|
Operator name_of(
|
|
"name_of", // name
|
|
NameOfSpec, // specification
|
|
NameOf_Fun,
|
|
Operator::SimpleSelect,
|
|
Cluster_String);
|
|
|
|
Operator rename(
|
|
"renamecluster", // name
|
|
RenameSpec, // specification
|
|
Rename_Fun,
|
|
Operator::SimpleSelect,
|
|
Cluster_String_Cluster);
|
|
|
|
Operator contains(
|
|
"contains", // name
|
|
ContainsSpec, // specification
|
|
Contains_Fun,
|
|
Operator::SimpleSelect,
|
|
Cluster_Int9M_Bool);
|
|
|
|
Operator disjoint(
|
|
"disjoint", // name
|
|
DisjointSpec, // specification
|
|
Disjoint_Cluster_Cluster_Fun,
|
|
Operator::SimpleSelect,
|
|
Cluster_Cluster_Bool);
|
|
|
|
Operator createpgroup(
|
|
"createpgroup", // name
|
|
CreatePGroupSpec, // specification
|
|
CreatePGroup_Fun,
|
|
Operator::SimpleSelect,
|
|
CreatePGroupTM);
|
|
|
|
Operator createprioritypgroup(
|
|
"createprioritypgroup", // name
|
|
CreatePriorityPGroupSpec, // specification
|
|
CreatePriorityPGroup_Fun,
|
|
Operator::SimpleSelect,
|
|
CreatePGroupTM);
|
|
|
|
Operator createvalidpgroup(
|
|
"createvalidpgroup", // name
|
|
CreateValidPGroupSpec, // specification
|
|
CreateValidPGroup_Fun,
|
|
Operator::SimpleSelect,
|
|
CreateValidPGroupTM);
|
|
|
|
Operator clustername_of(
|
|
"clustername_of", // name
|
|
ClusterNameOf_pc_m_Spec, // specification
|
|
ClusterNameOf_Fun,
|
|
Operator::SimpleSelect,
|
|
ClusterName_OfTM);
|
|
|
|
Operator clusterof(
|
|
"clusterof", // name
|
|
ClusterOf_pc_m_Spec, // specification
|
|
ClusterOf_Fun,
|
|
Operator::SimpleSelect,
|
|
ClusterOfTM);
|
|
|
|
Operator stdpgroup(
|
|
"stdpgroup", // name
|
|
StdPGroup_Spec, // specification
|
|
StdPGroup_Fun,
|
|
Operator::SimpleSelect,
|
|
StdPGroup_TM);
|
|
|
|
} // namespace toprel
|
|
|
|
/*
|
|
STream operators
|
|
|
|
*/
|
|
|
|
ostream& operator<<(ostream& o, const toprel::Int9M& p){
|
|
o << p.ToString();
|
|
return o;
|
|
}
|
|
|
|
|
|
ostream& operator<<(ostream& o, const toprel::Cluster& c){
|
|
o << c.ToString();
|
|
return o;
|
|
}
|
|
|
|
ostream& operator<<(ostream& o, const toprel::PredicateGroup& p){
|
|
o << p.ToString();
|
|
return o;
|
|
}
|
|
|
|
/*
|
|
7 Creating the Algebra
|
|
|
|
*/
|
|
class TopRelAlgebra : public Algebra
|
|
{
|
|
public:
|
|
TopRelAlgebra() : Algebra()
|
|
{
|
|
AddTypeConstructor( &toprel::int9m );
|
|
AddTypeConstructor( &toprel::cluster);
|
|
AddTypeConstructor( &toprel::predicategroup);
|
|
|
|
toprel::int9m.AssociateKind(Kind::DATA());
|
|
toprel::cluster.AssociateKind(Kind::DATA());
|
|
toprel::predicategroup.AssociateKind(Kind::DATA());
|
|
|
|
AddOperator(&toprel::invert);
|
|
AddOperator(&toprel::union_op);
|
|
AddOperator(&toprel::intersection);
|
|
AddOperator(&toprel::multiintersection);
|
|
AddOperator(&toprel::add);
|
|
AddOperator(&toprel::number_of);
|
|
AddOperator(&toprel::remove);
|
|
AddOperator(&toprel::rename);
|
|
AddOperator(&toprel::name_of);
|
|
AddOperator(&toprel::contains);
|
|
AddOperator(&toprel::disjoint);
|
|
AddOperator(&toprel::minus);
|
|
AddOperator(&toprel::createpgroup);
|
|
AddOperator(&toprel::createvalidpgroup);
|
|
AddOperator(&toprel::createprioritypgroup);
|
|
AddOperator(&toprel::clustername_of);
|
|
AddOperator(&toprel::clusterof);
|
|
AddOperator(&toprel::transpose);
|
|
AddOperator(&toprel::sizeof_op);
|
|
AddOperator(&toprel::createcluster);
|
|
AddOperator(&toprel::iscomplete);
|
|
AddOperator(&toprel::unspecified);
|
|
AddOperator(&toprel::pwdisjoint);
|
|
AddOperator(&toprel::restrict_op);
|
|
AddOperator(&toprel::relax_op);
|
|
AddOperator(&toprel::stdpgroup);
|
|
AddOperator(&toprel::toprel_equals);
|
|
AddOperator(&toprel::getcluster);
|
|
}
|
|
~TopRelAlgebra() {};
|
|
};
|
|
|
|
|
|
void InitializeTranspArray(){
|
|
toprel::Int9M m(0);
|
|
for(int i=0;i<512;i++){
|
|
m.SetValue(i);
|
|
m.TransposeSlow();
|
|
TranspArray[i] = m.GetNumber();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
8 Initialization of the Algebra
|
|
|
|
|
|
*/
|
|
extern "C"
|
|
Algebra*
|
|
InitializeTopRelAlgebra( NestedList* nlRef, QueryProcessor* qpRef )
|
|
{
|
|
nl = nlRef;
|
|
qp = qpRef;
|
|
InitializeTranspArray();
|
|
return (new TopRelAlgebra());
|
|
}
|
|
|