Files
secondo/Algebras/Flock/FlockAlgebra.cpp
2026-01-23 17:03:45 +08:00

1993 lines
58 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]
[1] Source File of the Flock Algebra
June, 2009 Mahmoud Sakr
[TOC]
1 Overview
This source file essentially contains the necessary implementations for
evaluating the spatiotemporal pattern predicates (STP).
2 Defines and includes
*/
#include "FlockAlgebra.h"
#include "Symbols.h"
#include "ListUtils.h"
#include "Stream.h"
using namespace temporalalgebra;
using namespace std;
using namespace datetime;
using namespace RegionInterpol;
namespace FLOCK{
bool
Helpers::string2int(char* digit, int& result)
{
result = 0;
while (*digit >= '0' && *digit <='9') {
result = (result * 10) + (*digit - '0');
digit++;
}
return (*digit == 0); // true if at end of string!
}
string
Helpers::ToString( int number )
{
ostringstream o;
o << number ; //<< char(0)
return o.str();
}
string
Helpers::ToString( double number )
{
ostringstream o;
o << number ; //<< char(0)
return o.str();
}
Flock::Flock(double* _coords, int _coordsCount):pointsCount(0)
{
this->coordsCount= _coordsCount;
for(int i=0; i< this->coordsCount; ++i)
this->coordinates[i]= _coords[i];
this->SetDefined(true);
}
Flock::Flock(const Flock& arg){
// copy coordinates to be save from object deletion
this->SetDefined(arg.IsDefined());
for (int a = 0; a < arg.coordsCount; ++a){
this->coordinates[a] = arg.coordinates[a];
}
for (int a = 0; a < arg.pointsCount; ++a){
this->points[a] = arg.points[a];
}
this->coordsCount= arg.coordsCount;
this->pointsCount = arg.pointsCount;
}
Flock::~Flock(){
}
size_t
Flock::HashValue() const
{
int res=0;
if(IsDefined())
{
for(int pIt = 0; pIt < this->pointsCount; ++pIt)
res = res ^ points[pIt];
res= res ^ this->pointsCount;
res= res ^ this->coordsCount;
return res;
}
return 0;
}
void
Flock::CopyFrom(const Attribute* rhs)
{
const Flock * arg= dynamic_cast<const Flock*>(rhs);
this->SetDefined(arg->IsDefined());
for (int a = 0; a < arg->coordsCount; ++a){
this->coordinates[a] = arg->coordinates[a];
}
for (int a = 0; a < arg->pointsCount; ++a){
this->points[a] = arg->points[a];
}
this->coordsCount= arg->coordsCount;
this->pointsCount = arg->pointsCount;
}
int
Flock::Compare( const Attribute* rhs ) const
{
return Attribute::GenericCompare<Flock>( this,
dynamic_cast<Flock*>(const_cast<Attribute*>(rhs)),
this->IsDefined(), rhs->IsDefined() );
}
bool
Flock::operator==(const Flock& rhs) const
{
// this->coordinates playes no role in the equality comparison. In the
// ReportFlock algorithm, this->coordinates is set to the first point
// that enters the Flock.
if (! (this->coordsCount == rhs.coordsCount &&
this->pointsCount == rhs.pointsCount
)
)return false;
for(int i=0; i<this->pointsCount ; ++i)
if(this->points[i] != rhs.points[i])
return false;
return true;
}
bool
Flock::operator<(const Flock& rhs) const
{
// We have no formal definition for comparing Flocks. This function is
// provided only to fulfill the inerface requirements.
return this->pointsCount < rhs.pointsCount;
}
bool
Flock::IsSubset(const Flock& rhs) const
{
// this->coordinates playes no role in the equality comparison. In the
// ReportFlock algorithm, this->coordinates is set to the first point
// that enters the Flock.
if (! (this->coordsCount == rhs.coordsCount &&
this->pointsCount <= rhs.pointsCount
)
)return false;
int l=0, r=0;
while(l < this->pointsCount && r < rhs.pointsCount)
{
if(this->points[l] < rhs.points[r]) return false;
else if (this->points[l] == rhs.points[r]) {++l; ++r;}
else ++r;
}
return (l == this->pointsCount);
}
int
Flock::Intersection(Flock* arg, Flock* res)
{
::std::vector<int> resVec(maxFlockSize);
::std::vector<int>::iterator last;
last= std::set_intersection(this->points, this->points + this->pointsCount,
arg->points, arg->points + arg->pointsCount,
resVec.begin());
res->pointsCount = last - resVec.begin();
std::copy(resVec.begin(), ++last, res->points);
return res->pointsCount;
}
int
Flock::IntersectionCount(Flock* arg)
{
::std::vector<int> resVec(maxFlockSize);
::std::vector<int>::iterator last= resVec.begin();
last= std::set_intersection(this->points, this->points + this->pointsCount,
arg->points, arg->points + arg->pointsCount,
last);
return last - resVec.begin();
}
Points* Flock::Flock2Points(Instant& curTime, vector<int>* ids,
vector<MPoint*>*sourceMPoints)
{
//bool debugme=true;
Points* res= new Points(this->pointsCount);
MPoint* curMPoint;
Point curPoint(0, 0);
Intime<Point> pointIntime(curTime, curPoint);
vector<int>::iterator idsIt;
unsigned int pos;
for(int i=0; i<this->pointsCount; ++i)
{
for(pos=0; pos<ids->size(); ++pos)
if((*ids)[pos] == this->points[i]) break;
if(pos == ids->size())
{
cerr<<"Error! Flock::GetPoints. "
"The MPoint with ID= "<< this->points[i] <<" is not found in the "
"sourceMPoints.";
return 0;
}
curMPoint= (*sourceMPoints)[pos];
curMPoint->AtInstant(curTime, pointIntime);
assert(pointIntime.IsDefined());
(*res) += pointIntime.value;
}
return res;
}
ostream&
Flock::Print( ostream &os ) const
{
if (! this->IsDefined()) return (os << "UnDefined Flock");
string prnt= "";
prnt+= "\nFlock size:" + this->pointsCount;
prnt+= "\nFlock coordinates: ";
for(int i=0; i< this->coordsCount ; ++i)
prnt+= FLOCK::Helpers::ToString(this->coordinates[i]) + ", ";
prnt+= "\nRegistered Flock point ids: " ;
for (int pointIt=0 ;pointIt < this->pointsCount; ++pointIt)
prnt+= FLOCK::Helpers::ToString(this->points[pointIt]) + ", ";
prnt+="\n";
return (os << prnt);
}
bool
Flock::IsDefined() const
{
return this->defined;
}
void
Flock::SetDefined(const bool def)
{
this->defined= def;
}
Attribute* Flock::Clone() const
{
return new Flock(*this);
}
int
Flock::addPoint(OctreePoint* point){
if(this->pointsCount >= maxFlockSize )
{
cerr<<"Flock size overflow. For efficient implementation we allow for "
"flock sizes up to" <<maxFlockSize;
throw;
}
int i= this->pointsCount-1;
while(i >= 0)
{
if(this->points[i] <= point->getIdentifier())
break;
i--;
}
if(this->points[i] == point->getIdentifier())
return -1; //point already exists
std::memmove(this->points + ((i+2) * sizeof(int)),
this->points + ((i+1) * sizeof(int)),
(this->pointsCount - i - 1) * sizeof(int));
this->points[i+1] = point->getIdentifier();
++this->pointsCount;
return 1; //point added successfully
}
int
Flock::addPointID(int point){
bool debugme=false;
if(this->pointsCount >= maxFlockSize )
{
cerr<<"Flock size overflow. For efficient implementation we allow for "
"flock sizes up to" <<maxFlockSize;
throw;
}
int i= this->pointsCount-1;
while(i >= 0)
{
if(this->points[i] <= point)
break;
--i;
}
if(this->points[i] == point)
return -1; //point already exists
if(debugme)
{
cout<<"\nBefore Addition \n";
this->printPoints();
cout<<"\nAdding pointID \n"<< point;
}
int newpos= i+2, // ) * sizeof(int)),
oldpos = i+1, // * sizeof(int)),
numbytes= (this->pointsCount - i - 1) * sizeof(int);
std::memmove(this->points + newpos,
this->points + oldpos,
numbytes);
this->points[i+1] = point;
++this->pointsCount;
if(debugme)
{
this->printPoints();
cout<<"\nAddition done \n";
}
return 1; //point added successfully
}
int
Flock::getPoints(int*& res){
res = this->points;
return this->pointsCount;
}
void
Flock::printPoints(){
if (this->points == 0) return;
printf("registered flock points: %d, ids are ",this->pointsCount);
for (int pointIt= 0 ;pointIt < this->pointsCount; ++pointIt){
printf("%d : ", this->points[pointIt]);
}
printf("\n");
};
void
Flock::printCoordinates(){
printf("flock details: %d points",this->pointsCount);
for (int a=0; a < this->coordsCount; a++)
printf(", %f", this->coordinates[a]);
printf("\n");
};
// type name used in Secondo:
const string Flock::BasicType()
{
return "flock";
}
const bool Flock::checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
bool MFlock::CanAdd(Flock* arg)
{
if(this->GetNoComponents()== 0) return true;
UFlock lastUnit;
this->Get(this->GetNoComponents()-1, lastUnit);
return (lastUnit.constValue.Compare( arg ) == 0);
}
void MFlock::MFlockMergeAdd(UFlock& unit)
{
/*
This is a modified copy from Mappring::MergeAdd. We use this function, instead
of the standard implementation, to overcome some unclear errors in the
ReportFlocks algorithm, that are possibly due to floating point numerical
errors. According to many tests, the final results are correct when we use this
function.
*/
UFlock lastunit;
UFlock u1transfer;
int size = units.Size();
if ( !unit.IsValid() )
{
cout << __FILE__ << "," << __LINE__ << ":" << __PRETTY_FUNCTION__
<< " MFlockMergeAdd(Unit): Unit is invalid:";
unit.Print(cout); cout << endl;
assert( false );
}
if (size > 0) {
units.Get( size - 1, u1transfer );
lastunit = u1transfer;
if (lastunit.EqualValue(unit) &&
/*
The following condition is modified to be "<=" rather than "==" in the standard
implementation.
*/
(lastunit.timeInterval.end >= unit.timeInterval.start)) {
lastunit.timeInterval.end = unit.timeInterval.end;
lastunit.timeInterval.rc = unit.timeInterval.rc;
if ( !lastunit.IsValid() )
{
cout << __FILE__ << "," << __LINE__ << ":" << __PRETTY_FUNCTION__
<< "\nMFlockMergeAdd(Unit): lastunit is invalid:";
lastunit.Print(cout); cout << endl;
assert( false );
}
units.Put(size - 1, lastunit);
}
else {
units.Append( unit );
}
}
else {
units.Append( unit );
}
}
/*
3 Flock Reporting Functions
*/
void FinalizeLastUnit(::std::vector<MFlock*>* mflocks,
Instant timeStep, int k)
{
bool debugme=true;
::std::vector<MFlock*>::iterator mflockIt;
MFlock* mflock;
UFlock lastUnit;
UFlock extended(true);
for(mflockIt= mflocks->begin(); mflockIt!= mflocks->end(); ++mflockIt)
{
mflock= *mflockIt;
if((*mflockIt)->finalized) continue;
mflock->Get(mflock->GetNoComponents()-1, lastUnit);
extended.CopyFrom(&lastUnit);
if(debugme)
{
cout<<endl<<"Finalizing MFlock "<<extended.constValue.points[0];
cout<<endl<<"Last unit before finalization :"; extended.Print(cout);
cout.flush();
}
extended.timeInterval.end += timeStep * (k-1);
mflock->Put(mflock->GetNoComponents()-1, extended);
(*mflockIt)->finalized=true;
if(debugme)
{
cout<<endl<<"Last unit after finalization :"; extended.Print(cout);
cout.flush();
}
}
}
::std::vector<MFlock*>*
findFlocks(char* filename, double radius, double tolerance, int flocksize,
Instant starttime, Instant timeStep, int k, short method)
{
bool debugme=true;
bool hasMoreData=true, consumed=false;
int startCol=0;
OctreeDatParser* myParser;
::std::vector<MFlock*>* mflocks= new ::std::vector<MFlock*>(0);
::std::vector<MFlock*>::iterator mflockIt;
::std::vector<MFlock*>* mflocksNotUpdated= new ::std::vector<MFlock*>(0);
::std::vector<Flock*>* flocks;
::std::vector<Flock*>::iterator flockIt;
Instant curtime(starttime);
UFlock uflock(true);
uflock.timeInterval.lc=true;
uflock.timeInterval.rc=false;
MFlock* mflock;
myParser = new OctreeDatParser(filename, startCol, startCol + k);
hasMoreData= (myParser->activeTrajectoriesCount() >= flocksize);
while(hasMoreData)
{
if(debugme)
{
cout<<endl<<"------------------------------------------------";
cout<<endl<<"New iteration for reporting flocks startCol="<< startCol<<
", endCol= "<< startCol+k;
cout<<endl<<"StartTime= "; curtime.Print(cout);
cout<<" EndTime= "; (curtime + (timeStep * k)).Print(cout);
cout<<endl<<"Number of points =" << myParser->getPointCount();
cout.flush();
}
if(myParser->getPointCount() >= flocksize)
{
switch(method)
{
case _2Dim:
flocks= findFlocks2Dim(myParser, radius, tolerance, flocksize);
break;
case _BruteForce:
flocks= findFlocks2DimBruteforce(myParser, radius, flocksize);
break;
case _Square:
flocks= findFlocksSkiptreeSquare(myParser, radius,
tolerance, flocksize);
break;
case _Pruning:
flocks= findFlocksSkiptreeSquareWithPruning(myParser, radius,
tolerance, flocksize);
break;
}
if(debugme)
{
cout<<endl<<"Found "<< flocks->size() << " flocks";
cout.flush();
}
uflock.timeInterval.end= curtime + timeStep;
uflock.timeInterval.start= curtime;
for(mflockIt= mflocks->begin(); mflockIt != mflocks->end(); ++mflockIt)
{
for(flockIt= flocks->begin(); flockIt != flocks->end(); ++flockIt)
{
if((*mflockIt)->CanAdd(*flockIt))
{
uflock.constValue.CopyFrom(*flockIt);
(*mflockIt)->MFlockMergeAdd(uflock);
(*mflockIt)->finalized= false;
if(debugme)
{
cout<<endl<<"Flock "<< (*flockIt)->points[0]<<" joined MFlock ";
UFlock tmp1;
(*mflockIt)->Get(0,tmp1);
cout<<tmp1.constValue.points[0];
cout.flush();
}
consumed=true;
break;
}
}
if(consumed) {flocks->erase(flockIt); consumed=false;}
else {mflocksNotUpdated->push_back(*mflockIt);}
}
/*
Flocks that are not merged with any of the existing MFlocks are used to create
new MFlocks
*/
for(flockIt= flocks->begin(); flockIt != flocks->end(); ++flockIt)
{
uflock.constValue.CopyFrom(*flockIt);
mflock= new MFlock(0);
mflock->Add(uflock);
mflock->finalized= false;
mflocks->push_back(mflock);
if(debugme)
{
cout<<endl<<"Creating new MFlock ";
cout<<(*flockIt)->points[0];
cout.flush();
}
}
/*
MFlocks that are not updated (i.e. got no new units), need to be finalized
(i.e. the last unit is prolonged k-1 time steps).
*/
FinalizeLastUnit(mflocksNotUpdated, timeStep, k);
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++)
delete (*flockIt);
flocks->clear();
delete flocks;
mflocksNotUpdated->clear();
//need to be tested. The destructors should not be called
}
++startCol;
curtime += timeStep;
delete myParser;
myParser = new OctreeDatParser(filename, startCol, startCol + k);
hasMoreData= (myParser->activeTrajectoriesCount() >= flocksize);
}
delete myParser;
delete mflocksNotUpdated;
if(debugme)
cout<<endl<<"returning from FindFlocks. "<<mflocks->size()<<" flocks found";
return mflocks;
}
::std::vector<Flock*>*
findFlocks2Dim(OctreeDatParser* myParser,
double radius, double tolerance, int flocksize){
bool debugme=false;
printf("Starting the flock search:\n");
if(myParser->getPointCount() < flocksize)
return 0;
time_t first, second, third, before, after;
Flock *flock;
before= time(NULL);
first = time(NULL);
OctreeCell* tree = myParser->getOctree();
second = time(NULL);
::std::vector<OctreePoint*>* points = myParser->getPointset();
::std::vector<Flock*>* flocks = new ::std::vector<Flock*>();
::std::vector<OctreePoint*>::iterator pointIt=points->begin();
::std::vector<Flock*>::iterator flockIt;
int dimensions = (*pointIt)->getDimensions();
int amount, i, queries=0;
double *pCoords, *fCoords;
bool inFlock=false;
double distance, radiussqrd=radius*radius;
for(; pointIt!=points->end(); pointIt++){
pCoords=(*pointIt)->getCoordinates();
//check against all flocks to make sure this point is not in one already
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
fCoords=(*flockIt)->getCoordinates();
if(debugme)
{
cout<<endl<<"pCoords =";
for(i=0; i<dimensions; ++i)
cout<< pCoords[i]<< "\t";
cout<<endl<<"fCoords =";
for(i=0; i<dimensions; ++i)
cout<< fCoords[i]<< "\t";
cout.flush();
}
inFlock=true;
// calculate distance
for(i=0; i<dimensions; i+=2){
distance=0;
distance+=(pCoords[i]-fCoords[i])*(pCoords[i]-fCoords[i]);
distance+=(pCoords[i+1]-fCoords[i+1])*(pCoords[i+1]-fCoords[i+1]);
if (distance>radiussqrd){
inFlock=false;
break;
}
}
if(inFlock){
break;
}
}
// if this point is in a flock already, go to the next point
if(inFlock){
(*flockIt)->addPoint(*pointIt);
continue;
}
// this point should be in no flock found so far. query it.
tree->unmarkReported();
queries++;
amount = tree->exactRangeQuery2DimSteps(pCoords, radius, tolerance);
if(debugme)
{
cout<<endl<<"Query point: ";
for(i=0; i<dimensions; i++)
cout<<pCoords[i]<<"\t";
cout<<endl<<"Points in its range = "<<amount;
cout.flush();
}
if(amount>=flocksize){
flock=new Flock(pCoords, dimensions);
flock->addPoint(*pointIt);
flocks->push_back(flock);
}
//break; // only do the first point plz
}
third = time(NULL);
printf("Flock details (from exact query):\n");
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
(*flockIt)->printPoints();
///////////////////////////////////////////////////////////////////////
//// comment in, if you wanna have flock points reported! /////////////
///////////////////////////////////////////////////////////////////////
// // only report on "unusual" points
// ::std::vector<OctreePoint*>* fpoints = (*flockIt)->getPoints();
// pointIt = points->begin();
// fpoints->clear();
// printf("checking against all points...\n");
// fCoords = (*flockIt)->getCoordinates();
// for(;pointIt != points->end(); pointIt++){
// pCoords = (*pointIt)->getCoordinates();
// inFlock=true;
// // calculate distance
// for(i=0; i<dimensions; i+=2){
// distance=0;
// distance+=(pCoords[i]-fCoords[i])*(pCoords[i]-fCoords[i]);
// distance+=(pCoords[i+1]-fCoords[i+1])*(pCoords[i+1]-fCoords[i+1]);
// if (distance>radiussqrd){
// inFlock=false;
// break;
// }
// }
// if(inFlock){
// fpoints->push_back(*pointIt);
// }
// }
// (*flockIt)->printPoints();
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
}
printf("Quadtree contains %d points in %d dimensions,\n",
tree->getPointsContained(), dimensions);
printf("radius was %f, tolerance was %f.\n", radius, tolerance);
printf("Found a total of %lu flocks.\n", flocks->size());
printf("Building the quadtree took %d seconds.\n", (int)(second-first));
printf("Performing %d queries took %d seconds.\n", queries,
(int)(third-second));
delete tree;
after= time(NULL);
printf("\nProcessing the complete trajectory took %d seconds.\n",
(int)(after-before));
return flocks;
};
::std::vector<Flock*>*
findFlocks2DimBruteforce(OctreeDatParser* myParser, double radius,
int flocksize){
printf("Starting the flock search:\n");
if(myParser->getPointCount() < flocksize)
return 0;
time_t first, second, third, before, after;
Flock *flock;
before= time(NULL);
first = time(NULL);
second = time(NULL);
::std::vector<OctreePoint*>* points = myParser->getPointset();
::std::vector<Flock*>* flocks = new ::std::vector<Flock*>();
::std::vector<OctreePoint*>::iterator pointIt=points->begin(), compIt;
::std::vector<Flock*>::iterator flockIt;
int dimensions = (*pointIt)->getDimensions();
int amount, i, queries=0;
double *pCoords, *fCoords, *cCoords;
bool inFlock=false;
double distance, radiussqrd=radius*radius;
for(; pointIt!=points->end(); pointIt++){
pCoords=(*pointIt)->getCoordinates();
//check against all flocks to make sure this point is not in one already
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
fCoords=(*flockIt)->getCoordinates();
inFlock=true;
// calculate distance
for(i=0; i<dimensions; i+=2){
distance=0;
distance+=(pCoords[i]-fCoords[i])*(pCoords[i]-fCoords[i]);
distance+=(pCoords[i+1]-fCoords[i+1])*(pCoords[i+1]-fCoords[i+1]);
if (distance>radiussqrd){
inFlock=false;
break;
}
}
if(inFlock){
break;
inFlock=false;
}
}
// if this point is in a flock already, go to the next point
if(inFlock){
continue;
}
// this point should be in no flock found so far. Check against all other
// points
queries++;
amount=0;
for(compIt=points->begin(); compIt!=points->end(); compIt++){
cCoords=(*compIt)->getCoordinates();
// calculate distance
// misusing inFlock here as in reach!
inFlock=true;
for(i=0; i<dimensions; i+=2){
distance=0;
distance+=(pCoords[i]-cCoords[i])*(pCoords[i]-cCoords[i]);
distance+=(pCoords[i+1]-cCoords[i+1])*(pCoords[i+1]-cCoords[i+1]);
if (distance>radiussqrd){
inFlock=false;
break;
}
}
if (inFlock) amount++;
}
if(amount>=flocksize){
flock=new Flock(pCoords, dimensions);
flocks->push_back(flock);
}
}
third = time(NULL);
printf("Flock details (from brute force):\n");
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
(*flockIt)->printPoints();
}
printf("Pointset contains %lu points in %d dimensions,\n",
points->size(), dimensions);
printf("radius was %f.\n", radius);
printf("Found a total of %lu flocks.\n", flocks->size());
printf("Building the quadtree took %d seconds.\n", (int)(second-first));
printf("Performing %d queries took %d seconds.\n", queries,
(int)(third-second));
after= time(NULL);
printf("\nProcessing the complete trajectory took %d seconds.\n",
(int)(after-before));
return flocks;
};
::std::vector<Flock*>*
findFlocksSkiptreeSquare(OctreeDatParser* myParser, double radius,
double tolerance, int flocksize){
printf("Starting the flock search:\n");
if(myParser->getPointCount() < flocksize)
return 0;
time_t first, second, third, before, after;
Flock *flock;
before= time(NULL);
first = time(NULL);
::std::map<int, OctreeCell*>* tree = myParser->getSkiptree();
second = time(NULL);
::std::vector<OctreePoint*>* points = myParser->getPointset();
::std::vector<Flock*>* flocks = new ::std::vector<Flock*>();
::std::vector<OctreePoint*>::iterator pointIt=points->begin();
::std::vector<Flock*>::iterator flockIt;
int dimensions = (*pointIt)->getDimensions();
int amount, i, queries=0;
double *pCoords, *fCoords;
bool inFlock=false;
double distance, radiussqrd=radius*radius;
for(; pointIt!=points->end(); pointIt++){
pCoords=(*pointIt)->getCoordinates();
//check against all flocks to make sure this point is not in one already
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
fCoords=(*flockIt)->getCoordinates();
inFlock=true;
// calculate distance
for(i=0; i<dimensions; i+=2){
distance=0;
distance+=(pCoords[i]-fCoords[i])*(pCoords[i]-fCoords[i]);
distance+=(pCoords[i+1]-fCoords[i+1])*(pCoords[i+1]-fCoords[i+1]);
if (distance>radiussqrd){
inFlock=false;
break;
}
}
if(inFlock){
(*flockIt)->addPoint(*pointIt);
break;
inFlock=false;
}
}
// if this point is in a flock already, go to the next point
if(inFlock){
continue;
}
// this point should be in no flock found so far. query it.
(*tree)[0]->unmarkReported();
queries++;
amount = (*tree)[0]->boxedRangeQueryCounting(pCoords, radius, tolerance);
if(amount>=flocksize){
flock=new Flock(pCoords, dimensions);
flock->addPoint(*pointIt);
flocks->push_back(flock);
}
}
third = time(NULL);
printf("Flock details (from box query):\n");
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
(*flockIt)->printPoints();
}
printf("Quadtree contains %d points in %d dimensions,\n",
(*tree)[0]->getPointsContained(), dimensions);
printf("radius was %f, tolerance was %f.\n", radius, tolerance);
printf("Found a total of %lu flocks.\n", flocks->size());
printf("Building the quadtree took %d seconds.\n", (int)(second-first));
printf("Performing %d queries took %d seconds.\n", queries,
(int)(third-second));
deleteSkipQuadtree(tree);
after= time(NULL);
printf("\nProcessing the complete trajectory took %d seconds.\n",
(int)(after-before));
return flocks;
};
::std::vector<Flock*>*
findFlocksSkiptreeSquareWithPruning(OctreeDatParser* myParser,
double radius, double tolerance, int flocksize){
printf("Starting the flock search:\n");
printf("pruning the set of ponts first...");
if(myParser->getPointCount() < flocksize)
return 0;
time_t first, second, third, fourth, fifth, before, after;
Flock *flock;
before= time(NULL);
first = time(NULL);
::std::map<int, OctreeCell*>* tree = myParser->getSkiptree4Dim();
second = time(NULL);
::std::vector<OctreePoint*>* points = myParser->getPointset();
::std::vector<OctreePoint*>* prunedSet = new vector<OctreePoint*>();
::std::vector<Flock*>* flocks = new ::std::vector<Flock*>();
::std::vector<OctreePoint*>::iterator pointIt=points->begin();
::std::vector<Flock*>::iterator flockIt;
int dimensions = 4;
int dimensions2 = (*pointIt)->getDimensions();
int amount, i, queries=0, queries2=0;
double *pCoords, *fCoords;
bool inFlock=false;
double distance, radiussqrd=radius*radius;
for(; pointIt!=points->end(); pointIt++){
pCoords=(*pointIt)->getCoordinates();
//check against all flocks to make sure this point is not in one already
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
fCoords=(*flockIt)->getCoordinates();
inFlock=true;
// calculate distance
for(i=0; i<dimensions; i+=2){
distance=0;
distance+=(pCoords[i]-fCoords[i])*(pCoords[i]-fCoords[i]);
distance+=(pCoords[i+1]-fCoords[i+1])*(pCoords[i+1]-fCoords[i+1]);
if (distance>radiussqrd){
inFlock=false;
break;
}
}
if(inFlock){
(*flockIt)->addPoint(*pointIt);
prunedSet->push_back(*pointIt);
break;
inFlock=false;
}
}
// if this point is in a flock already, go to the next point
if(inFlock){
continue;
}
// this point should be in no flock found so far. query it.
(*tree)[0]->unmarkReported();
queries++;
amount = (*tree)[0]->boxedRangeQueryCounting(pCoords, radius, tolerance);
if(amount>=flocksize){
flock=new Flock(pCoords, dimensions);
flock->addPoint(*pointIt);
prunedSet->push_back(*pointIt);
flocks->push_back(flock);
}
}
third = time(NULL);
// clean up
deleteSkipQuadtree(tree);
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
delete *flockIt;
}
flocks->clear();
if (prunedSet->size()>0){
tree = myParser->getSkiptreeFromSet(prunedSet, dimensions2);
fourth = time(NULL);
// get next run started
fourth = time(NULL);
inFlock = false; // FH added this one, fragged the first run otherwise!
pointIt = prunedSet->begin();
for(; pointIt!=prunedSet->end(); pointIt++){
pCoords=(*pointIt)->getCoordinates();
//check against all flocks to make sure this point is not in one already
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
fCoords=(*flockIt)->getCoordinates();
inFlock=true;
// calculate distance
for(i=0; i<dimensions2; i+=2){//TW+DM changed dimensions to dimensions2
distance=0;
distance+=(pCoords[i]-fCoords[i])*(pCoords[i]-fCoords[i]);
distance+=(pCoords[i+1]-fCoords[i+1])*(pCoords[i+1]-fCoords[i+1]);
if (distance>radiussqrd){
inFlock=false;
break;
}
}
if(inFlock){
(*flockIt)->addPoint(*pointIt);
break;
inFlock=false;
}
}
// if this point is in a flock already, go to the next point
if(inFlock){
continue;
}
// this point should be in no flock found so far. query it.
(*tree)[0]->unmarkReported();
queries2++;
amount = (*tree)[0]->boxedRangeQueryCounting(pCoords, radius, tolerance);
if(amount>=flocksize){
flock=new Flock(pCoords); // TW+DM changed dimensions to dimensions2
flock->addPoint(*pointIt);
flocks->push_back(flock);
}
}
} else {
fourth = time(NULL);
}
fifth = time(NULL);
printf("Flock details (from box query with pruning):\n");
for(flockIt=flocks->begin(); flockIt!=flocks->end(); flockIt++){
(*flockIt)->printPoints();
}
printf("Quadtree contains %d points in %d dimensions,\n",
(*tree)[0]->getPointsContained(), dimensions2);
printf("radius was %f, tolerance was %f.\n", radius, tolerance);
printf("Found a total of %lu flocks.\n", flocks->size());
printf("Building the pruning skip quadtree took %d seconds.\n",
(int)(second-first));
printf("Performing %d queries for pruning took %d seconds.\n", queries,
(int)(third-second));
printf("Building the final skip quadtree took %d seconds.\n",
(int)(fourth-third));
printf("Performing %d final queries took %d seconds.\n", queries2,
(int)(fifth-fourth));
printf("Complete time after first build of tree was %d.\n",
(int)(fifth-second));
deleteSkipQuadtree(tree);
after= time(NULL);
printf("\nProcessing the complete trajectory took %d seconds.\n",
(int)(after-before));
return flocks;
};
/*
4 Operators
*/
ListExpr ReportFlocksTM( ListExpr args )
{
if(!nl->HasLength(args,8)){
return listutils::typeError("8 arguments expected");
}
string err = "string x real x real x int x instant x duration "
"x int x string expected";
if( !CcString::checkType(nl->First(args))
|| !CcReal::checkType(nl->Second(args))
|| !CcReal::checkType(nl->Third(args))
|| !CcInt::checkType(nl->Fourth(args))
|| !Instant::checkType(nl->Fifth(args))
|| !Duration::checkType(nl->Sixth(args))
|| !CcInt::checkType(nl->Nth(7,args))
|| !CcString::checkType(nl->Nth(8,args))){
return listutils::typeError(err);
}
return (nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom("mflock")));
}
int ReportFlocksVM(Word* args, Word& result,
int message, Word& local, Supplier s)
{
::std::vector<MFlock*>* mflocks;
switch (message)
{
case OPEN :{
string fileName= static_cast<CcString*>(args[0].addr)->GetValue();
double radius = static_cast<CcReal*>(args[1].addr)->GetRealval();
double tolerance = static_cast<CcReal*>(args[2].addr)->GetRealval();
int flockSize = static_cast<CcInt*>(args[3].addr)->GetIntval();
Instant* startTime = static_cast<Instant*>(args[4].addr);
Instant* timeStep = static_cast<Instant*>(args[5].addr);
int k = static_cast<CcInt*>(args[6].addr)->GetIntval();
string smethod= static_cast<CcString*>(args[7].addr)->GetValue();
short method=_BruteForce;
if(smethod == "bruteforce") method= _BruteForce;
else if(smethod == "square") method= _Square;
else if(smethod == "exact") method= _2Dim;
else if(smethod == "sqpruning") method= _Pruning;
mflocks= findFlocks(const_cast<char*>(fileName.c_str()), radius, tolerance,
flockSize, *startTime, *timeStep, k, method);
local.setAddr(mflocks);
return 0;
}
case REQUEST :{
mflocks = static_cast< vector<MFlock*>* >(local.addr);
MFlock* mflock;
if (!mflocks->empty())
{
mflock= mflocks->back();
mflocks->pop_back();
result.setAddr(mflock);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :{
mflocks = static_cast< vector<MFlock*>* >(local.addr);
delete mflocks;
return 0;
}
default: return CANCEL;
}
return 0;
}
const string ReportFlocksSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>string x real x real x int x instant x duration x int x string -> "
"stream(mflock)</text--->"
"<text>reportflocks(fileName, radius, tolerance, flockSize, startTime, "
"timeStep, flockDuration, method)</text--->"
"<text>The operator gets its input from the (fileName), reports the flocks "
"with parameters (radius, tolerance, flockSize, flockDuration), annotating"
" the first column in the file with (startTime), and moving one (timeStep) "
"for each further column. The computation uses the technique (method)."
"</text--->"
"<text>reportflocks(\"fileName\", 15.0, 16.0, 9, the_instant(.), "
"create_duration(.), \"exact\")</text--->"
") )";
Operator reportflocks(
"reportflocks", // name
ReportFlocksSpec, // specification
ReportFlocksVM, // value mapping
Operator::SimpleSelect, // trivial selection function
ReportFlocksTM // type mapping
);
ListExpr
Flock::Out( ListExpr typeinfo, Word value )
{
bool debugme=false;
Flock* flock = static_cast<Flock*>(value.addr);
if(!flock->IsDefined())
return nl->SymbolAtom("undef");
ListExpr lastPoint, points;
points= lastPoint= nl->TheEmptyList();
if(flock->pointsCount>0)
{
points = lastPoint = nl->OneElemList(nl->IntAtom(flock->points[0]));
for(int i=1; i< flock->pointsCount; ++i)
lastPoint = nl->Append(lastPoint,nl->IntAtom(flock->points[i]));
}
ListExpr lastCoord, coords;
coords= lastCoord= nl->TheEmptyList();
if(flock->coordsCount>0)
{
coords = lastCoord = nl->OneElemList(nl->RealAtom(flock->coordinates[0]));
for(int i=1; i< flock->coordsCount; ++i)
lastCoord = nl->Append(lastCoord,nl->RealAtom(flock->coordinates[i]));
}
ListExpr res= nl->FourElemList(
nl->IntAtom(flock->coordsCount),
nl->IntAtom(flock->pointsCount),
coords,
points);
if(debugme)
cout<< nl->ToString(res);
return res;
}
Word
Flock::In( ListExpr typeInfo, ListExpr value,
int errorPos, ListExpr& errorInfo, bool& correct )
{
bool debugme=false;
if(nl->IsEqual(value,"undef"))
return SetWord(Address( 0 ));
if (
(! (nl->ListLength(value) == 4)) ||
(!(nl->IsAtom(nl->First(value)) &&
nl->AtomType(nl->First(value))==IntType)) ||
(!(nl->IsAtom(nl->Second(value)) &&
nl->AtomType(nl->Second(value))==IntType))
)
{
correct= false;
errorInfo= nl->StringAtom("Invalid flock nested list representation");
return SetWord(Address(0));
}
Word res;
res.addr= new Flock(true);
Flock * flock= static_cast<Flock*>(res.addr);
flock->coordsCount= nl->IntValue(nl->First(value));
flock->pointsCount= nl->IntValue(nl->Second(value));
ListExpr coords= nl->Third(value);
ListExpr points= nl->Fourth(value);
if(nl->ListLength(points) != flock->pointsCount)
{
correct= false;
errorInfo= nl->StringAtom("Invalid flock nested list representation");
return SetWord(Address(0));
}
if(flock->pointsCount > maxFlockSize)
{
correct= false;
errorInfo= nl->StringAtom(" \nEncountered a flock of size " +
Helpers::ToString(flock->pointsCount) +
"For efficient implementation, flocks are limited to " +
Helpers::ToString(maxFlockSize) );
return SetWord(Address(0));
}
for(int i=0 ; i<flock->pointsCount; ++i)
{
flock->points[i]= nl->IntValue(nl->First(points));
points= nl->Rest(points);
}
if(nl->ListLength(coords) != flock->coordsCount)
{
correct= false;
errorInfo= nl->StringAtom("Invalid flock nested list representation");
return SetWord(Address(0));
}
if(flock->coordsCount > maxCoordsSize)
{
correct= false;
errorInfo= nl->StringAtom(" \nEncountered a flock coordinate list of size "
+ Helpers::ToString(flock->coordsCount) +
"For efficient implementation, coordinates are limited to " +
Helpers::ToString(maxCoordsSize) );
return SetWord(Address(0));
}
for(int i=0 ; i<flock->coordsCount; ++i)
{
flock->coordinates[i]= nl->RealValue(nl->First(coords));
coords= nl->Rest(coords);
}
if(debugme)
{
flock->Print(cout); cout<<endl; cout.flush();
}
correct= true;
return res;
}
Word
Flock::Create( const ListExpr typeInfo )
{
return (SetWord (new Flock()));
}
void
Flock::Delete( const ListExpr typeInfo, Word& w )
{
delete static_cast<Flock*>(w.addr);
w.addr= 0;
}
void
Flock::Close( const ListExpr typeInfo, Word& w )
{
Flock::Delete(typeInfo, w);
}
Word
Flock::Clone( const ListExpr typeInfo, const Word& w )
{
Flock* arg= static_cast<Flock*>(w.addr);
Flock* res= static_cast<Flock*>(arg->Clone());
return SetWord(res);
}
void*
Flock::Cast(void* addr)
{
return (new (addr) Flock);
}
bool
Flock::KindCheck( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual(type, "flock"));
}
int
Flock::SizeOfObj()
{
return sizeof(Flock);
}
ListExpr
Flock::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("-> FLOCK"),
nl->StringAtom("(flock) "),
nl->StringAtom("(size dimensions pointsCount "
"coords points)"),
nl->TextAtom("(((i1 i2 FALSE FALSE) "
"(2 2 3 (11.1 345.2) (122 524 300))) "
"((i3 i4 TRUE FALSE) "
"(2 2 2 (44.6 117.3) (12 24)))) "))));
}
template <class Alpha, Word (*InFun)( const ListExpr, const ListExpr,
const int, ListExpr&, bool& )>
Word InConstTemporalUnit2( const ListExpr typeInfo,
const ListExpr instance,
const int errorPos,
ListExpr& errorInfo,
bool& correct )
{
string errmsg;
if( nl->ListLength( instance ) == 2 )
{
//1. deal with the time interval
ListExpr first = nl->First( instance );
if( nl->ListLength( first ) == 4 &&
nl->IsAtom( nl->Third( first ) ) &&
nl->AtomType( nl->Third( first ) ) == BoolType &&
nl->IsAtom( nl->Fourth( first ) ) &&
nl->AtomType( nl->Fourth( first ) ) == BoolType )
{
Instant *start =
(Instant *)InInstant( nl->TheEmptyList(), nl->First( first ),
errorPos, errorInfo, correct ).addr;
if( !correct )
{
errmsg = "InConstTemporalUnit2(): Error in first instant.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
return SetWord( Address(0) );
}
Instant *end =
(Instant *)InInstant( nl->TheEmptyList(), nl->Second( first ),
errorPos, errorInfo, correct ).addr;
if( !correct )
{
errmsg = "InConstTemporalUnit2(): Error in second instant.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
delete end;
return SetWord( Address(0) );
}
// get closedness parameters
bool lc = nl->BoolValue( nl->Third( first ) );
bool rc = nl->BoolValue( nl->Fourth( first ) );
Interval<Instant> tinterval( *start, *end, lc, rc );
delete start;
delete end;
// check, wether interval is well defined
correct = tinterval.IsValid();
if ( !correct )
{
errmsg = "InConstTemporalUnit2(): Non valid time interval.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
return SetWord( Address(0) );
}
//2. deal with the alpha value
Alpha *value = (Alpha *)InFun( nl->TheEmptyList(), nl->Second( instance ),
errorPos, errorInfo, correct ).addr;
//3. create the class object
if( correct )
{
ConstTemporalUnit<Alpha> *constunit =
new ConstTemporalUnit<Alpha>( tinterval, *value );
if( constunit->IsValid() )
{
delete value;
return SetWord( constunit );
}
delete constunit;
}
delete value;
}
}
else if ( nl->IsAtom( instance ) &&
nl->AtomType( instance ) == SymbolType &&
nl->SymbolValue( instance ) == "undef" )
{
ConstTemporalUnit<Alpha> *constunit =
new ConstTemporalUnit<Alpha>();
constunit->SetDefined(false);
constunit->timeInterval=
Interval<DateTime>(DateTime(instanttype),
DateTime(instanttype),true,true);
correct = true;
return (SetWord( constunit ));
}
errmsg = "InConstTemporalUnit2(): Error in representation.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
correct = false;
return SetWord( Address(0) );
}
bool
CheckUFlock( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, "uflock" ));
}
bool
MFlock::KindCheck( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, "mflock" ));
}
ListExpr
UFlockProperty()
{
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("-> UFLOCK"),
nl->StringAtom("(uflock) "),
nl->StringAtom("(timeInterval flock) "),
nl->TextAtom("((i1 i2 FALSE FALSE) "
"(2 2 3 (11.1 345.2) (122 524 300)))"))));
}
ListExpr
MFlock::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("-> MFLOCK"),
nl->StringAtom("(mflock) "),
nl->StringAtom("(UFLOCK UFLOCK)"),
nl->TextAtom("(((i1 i2 FALSE FALSE) "
"(2 2 3 (11.1 345.2) (122 524 300))) "
"((i3 i4 TRUE FALSE) "
"(2 2 2 (44.6 117.3) (12 24)))) "))));
}
TypeConstructor flockTC(
"flock", //name
Flock::Property, //property function describing signature
Flock::Out,
Flock::In, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
Flock::Create,
Flock::Delete, //object creation and deletion
0, 0,
Flock::Close,
Flock::Clone, //object close and clone
Flock::Cast, //cast function
Flock::SizeOfObj, //sizeof function
Flock::KindCheck );
TypeConstructor uflockTC(
"uflock", //name
UFlockProperty, //property function describing signature
OutConstTemporalUnit<Flock, Flock::Out>,
InConstTemporalUnit2<Flock, Flock::In>, //Out and In functions
0, 0,//SaveToList and RestoreFromList functions
CreateConstTemporalUnit<Flock>,
DeleteConstTemporalUnit<Flock>, //object creation and deletion
OpenAttribute<UFlock>,
SaveAttribute<UFlock>, // object open and save
CloseConstTemporalUnit<UFlock>,
CloneConstTemporalUnit<UFlock>, //object close and clone
CastConstTemporalUnit<UFlock>, //cast function
SizeOfConstTemporalUnit<UFlock>, //sizeof function
CheckUFlock ); //kind checking function
TypeConstructor mflockTC(
"mflock", //name
MFlock::Property, //property function describing signature
OutMapping<MFlock, UFlock, OutConstTemporalUnit<Flock, Flock::Out> >,
InMapping<MFlock, UFlock, InConstTemporalUnit2<Flock, Flock::In> >,
//Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateMapping<MFlock>,
DeleteMapping<MFlock>, //object creation and deletion
OpenAttribute<MFlock>,
SaveAttribute<MFlock>, // object open and save
CloseMapping<MFlock>,
CloneMapping<MFlock>, //object close and clone
CastMapping<MFlock>, //cast function
SizeOfMapping<MFlock>, //sizeof function
MFlock::KindCheck ); //kind checking function
ListExpr RandomMFlockTM(ListExpr args)
{
//cout<<nl->ToString(args);
if(!nl->HasLength(args,2)){
return listutils::typeError("two elements expected");
}
if( !Instant::checkType(nl->First(args))
|| !CcInt::checkType(nl->Second(args))){
return listutils::typeError("instant x int expected");
}
return nl->SymbolAtom("mflock");
}
void CreateRandomMFlock(Instant starttime, int minSize, MFlock& result)
{
bool debugme=false;
result.Clear();
int rnd, ucntr=0, unum, pntcntr=0, pnum;
Flock* f;
UFlock unit(true);
Interval<Instant> intr(starttime, starttime, true, false);
rnd=rand()%20; //deciding the number of units in the mflock value
unum=++rnd;
while(ucntr++ < unum)
{
rnd=rand()%20;
pnum= rnd + minSize; //deciding the number of points in the flock
pntcntr=0;
f=new Flock(0);
while(pntcntr++ < pnum) //creating the flock
{
rnd=rand() % 30000;
while(f->addPointID(rnd) == -1)
rnd=rand() % 30000;
}
rnd=rand()%50000; //deciding the duration of a unit
while(rnd<2)
rnd=rand()%50000;
intr.end.Set(intr.start.GetYear(), intr.start.GetMonth(),
intr.start.GetGregDay(), intr.start.GetHour(),intr.start.GetMinute(),
intr.start.GetSecond(),intr.start.GetMillisecond()+rnd);
unit.constValue.CopyFrom(f);
delete f;
if(debugme)
{
cout<<"\nAdding unit number "<<ucntr <<endl;
unit.constValue.Print(cout); cout.flush();
}
unit.timeInterval= intr;
result.Add(unit);
if(debugme)
{
unit.constValue.Print(cout); cout.flush();
result.Print(cout); cout.flush();
}
intr.start= intr.end;
}
if(debugme)
{
cout<< "\nCreateMFlock returns \n";
result.Print(cout);
}
}
int
RandomMFlockVM(Word* args, Word& result, int message, Word& local, Supplier s)
{
bool debugme=false;
result = qp->ResultStorage(s);
MFlock* res = static_cast<MFlock*>( result.addr);
DateTime* tstart = (DateTime*) args[0].addr;
int flocksize = static_cast<CcInt*>(args[1].addr)->GetIntval();
CreateRandomMFlock(*tstart, flocksize, *res);
if(debugme)
{
cout<<"\nThe random mflock\n "; res->Print(cout);
}
return 0;
}
const string RandomMFlockSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text> instant x int -> mflock</text--->"
"<text>randommflock( starttime, flocksize )</text--->"
"<text>Creates a random mflock value. The operator is used for testing"
"purposes.</text--->"
"<text>let mf1 = randommflock(now(), 50)</text--->"
") )";
Operator randommflock (
"randommflock", // name
RandomMFlockSpec, // specification
RandomMFlockVM, // value mapping
Operator::SimpleSelect, // trivial selection function
RandomMFlockTM // type mapping
);
ListExpr MFlock2MRegionTM(ListExpr args)
{
string msg= nl->ToString(args);
if(!nl->HasLength(args,3)){
return listutils::typeError("three arguments expected");
}
if(!Stream<Tuple>::checkType(nl->First(args))){
return listutils::typeError("first arg is not a tuple stream");
}
if(!Stream<Tuple>::checkType(nl->Second(args))){
return listutils::typeError("second arg is not a tuple stream");
}
if(!Duration::checkType(nl->Third(args))){
return listutils::typeError("third arg is not a duration");
}
ListExpr tuple1 = nl->Second(nl->Second(nl->First(args)));
if( !nl->HasLength(tuple1,2)
|| !CcInt::checkType(nl->Second(nl->First(tuple1)))
|| !MPoint::checkType(nl->Second(nl->Second(tuple1)))){
return listutils::typeError("first arg must be "
" stream(tuple(int mpoint))");
}
ListExpr tuple2 = nl->Second(nl->Second(nl->Second(args)));
if( ! nl->HasLength(tuple2,1)
|| ! listutils::isSymbol(nl->Second(nl->First(tuple2)),"mflock")){
return listutils::typeError("second arg must be stream(tuple(mflock))");
}
return (nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom("movingregion")));
}
void test()
{
bool debugme=true;
Points* res= new Points(10);
Point p(10.0, 10.0);
for(int i=0; i<20; ++i)
{
p.Set(rand()%100 *1.0, rand()%100 *1.0);
(*res) += p;
if(debugme)
{
res->Print(cerr)<<endl;
}
}
}
MRegion*
MFlock::MFlock2MRegion(vector<int>* ids, vector<MPoint*>* sourceMPoints,
Instant& samplingDuration)
{
bool debugme=true;
/*
Validating the input
*/
MRegion* res = new MRegion(0);
res->SetDefined(false);
if(!this->IsDefined() || sourceMPoints->size()==0) return res;
/*
Do the real work. The idea is as follows:
foreach uflock in this
1- Sample uflock according to the samplingDuration (include the start and
end instants).
2- From every two consecutive samples, create a URegion
*/
res->SetDefined(true);
UFlock curUFlock;
Flock* curFlock= new Flock(0);
Instant curTime(instanttype);
Instant finalTime(instanttype);
Interval<Instant> unitInterval(curTime, curTime, true, false);
// Intime<Flock> intimeFlock(curTime, curFlock);
vector<double> weigths(4);
weigths[0] = 0.7; // AreaWeight
weigths[1] = 0.7; // OverlapWeight
weigths[2] = 0.5; // HausdorffWeight
weigths[3] = 1.0; // LinearWeight
Points* ps;
Region* reg1=new Region(0), *reg2=new Region(0), *regswap;
RegionForInterpolation *reginter1, *reginter2, *reginterswap;
Match *sm;
mLineRep *lines;
URegion *resUnit;
for(int unitIndex=0; unitIndex < this->GetNoComponents(); ++unitIndex)
{
/*
Computing the left part of the URegion (i.e. the values at the start instant)
*/
this->Get(unitIndex, curUFlock);
curTime= curUFlock.timeInterval.start;
finalTime= curUFlock.timeInterval.end;
finalTime-= samplingDuration ;
*curFlock = curUFlock.constValue;
unitInterval.start= curTime;
unitInterval.lc= curUFlock.timeInterval.lc;
ps= curFlock->Flock2Points(curTime, ids, sourceMPoints);
GrahamScan::convexHull(ps,reg1);
delete ps;
reginter1=new RegionInterpol::RegionForInterpolation(reg1);
while(curTime <= finalTime)
{
/*
Computing the right part ofthe URegion
*/
curTime+= samplingDuration;
ps= curFlock->Flock2Points(curTime, ids, sourceMPoints);
GrahamScan::convexHull(ps, reg2);
unitInterval.end= curTime;
reginter2=new RegionInterpol::RegionForInterpolation(reg2);
if(debugme)
{
cerr<<endl<<"RegionForInter1 faces count "<<reginter1->getNrOfFaces();
cerr<<endl<<"RegionForInter2 faces count "<<reginter2->getNrOfFaces();
}
sm=new OptimalMatch(reginter1, reginter2, weigths);
lines=new mLineRep(sm);
resUnit= new URegion(lines->getTriangles(), unitInterval);
res->Add(*(resUnit->GetEmbedded()));
/*
Copying the right part of this URegion to the left part of the next URegion
*/
unitInterval.start= unitInterval.end;
regswap= reg1;
reg1= reg2;
reg2= regswap;
reginterswap= reginter1;
reginter1= reginter2;
/*
Garbage collection
*/
delete resUnit;
delete lines;
// delete sm;
//delete regswap;
delete reginterswap;
delete ps;
}
/*
Adding the last instant in the unit
*/
curTime= finalTime;
ps= curFlock->Flock2Points(curTime, ids, sourceMPoints);
GrahamScan::convexHull(ps, reg2);
unitInterval.end= curTime;
unitInterval.rc= curUFlock.timeInterval.rc;
reginter2=new RegionForInterpolation(reg2);
sm=new OptimalMatch(reginter1, reginter2, weigths);
lines=new mLineRep(sm);
resUnit= new URegion(lines->getTriangles(), unitInterval);
res->Add(*(resUnit->GetEmbedded()));
delete resUnit;
delete lines;
// delete sm;
delete reg1;
delete reg2;
delete reginter1;
delete reginter2;
delete ps;
}
return res;
}
int
MFlock2MRegionVM(Word* args, Word& result, int message, Word& local, Supplier s)
{
//bool debugme=true;
result = qp->ResultStorage(s);
MRegion* res = static_cast<MRegion*>( result.addr);
MFlock* mflock;
Tuple * t;
switch (message)
{
case OPEN :{
qp->Open(args[1].addr);
return 0;
}
case REQUEST :{
int* idsUnit, count, id;
std::set<int>* usedIDs=new set<int>();
std::vector<MPoint*>* mpoints;
std::vector<MPoint*>::iterator mpointsIt;
std::vector<int>* ids;
UFlock uflock;
Tuple* tuple;
std::vector<Tuple*>* delBuffer= new std::vector<Tuple*>(0);
std::vector<Tuple*>::iterator delBufferIt;
MPoint* mpoint;
MRegion* tmpres=0;
Word w;
qp->Request(args[1].addr, w);
if(qp->Received(args[1].addr))
{
tuple= static_cast<Tuple*>(w.addr);
mflock= static_cast<MFlock*>(tuple->GetAttribute(0));
mpoints= new std::vector<MPoint*>();
ids= new std::vector<int>();
for(int i=0; i< mflock->GetNoComponents(); ++i)
{
mflock->Get(i, uflock);
count= uflock.constValue.getPoints(idsUnit);
usedIDs->insert(idsUnit, idsUnit + count);
//uflock->DeleteIfAllowed();
}
qp->Open(args[0].addr);
qp->Request(args[0].addr, w);
t= static_cast<Tuple*>(w.addr);
while(qp->Received(args[0].addr))
{
id= dynamic_cast<CcInt*>(t->GetAttribute(0))->GetIntval();
if(usedIDs->find(id) != usedIDs->end())
{
ids->push_back(id);
mpoint= dynamic_cast<MPoint*>(t->GetAttribute(1));
mpoints->push_back(mpoint);
delBuffer->push_back(t);
}
else
t->DeleteIfAllowed();
qp->Request(args[0].addr, w);
t= static_cast<Tuple*>(w.addr);
}
qp->Close(args[0].addr);
assert(ids->size()>0);
res= mflock->MFlock2MRegion(ids, mpoints,
*static_cast<Instant*>(args[2].addr));
mflock->DeleteIfAllowed();
for(delBufferIt= delBuffer->begin(); delBufferIt != delBuffer->end();
++delBufferIt)
(*delBufferIt)->DeleteIfAllowed();
delBuffer->clear();
delete delBuffer;
for(mpointsIt= mpoints->begin(); mpointsIt != mpoints->end(); ++mpointsIt)
(*mpointsIt)->DeleteIfAllowed();
mpoints->clear();
ids->clear();
delete mpoints;
delete ids;
res->CopyFrom(tmpres);
delete tmpres;
tuple->DeleteIfAllowed();
return YIELD;
}
else
return CANCEL;
}
case CLOSE :{
qp->Close(args[1].addr);
return 0;
}
default: return CANCEL;
}
return 0;
}
const string MFlock2MRegionSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text> stream(tuple(int mpoint)) x stream(tuple(mflock)) x duration -> "
"stream(movingregion)</text--->"
"<text>Trains feed addcounter[Cnt, 1] project[Cnt, Trip] Flocks feed "
"mflocks2mregions[create_duration(0, 10000)]</text--->"
"<text>Creates mving region representation for the mflocks. The resulting "
"mregions are the interpolation of the convex hull regions taken at time "
"intervals of duration at most.</text--->"
"<text>query Trains feed addcounter[Cnt, 1] project[Cnt, Trip] Flocks feed "
"mflocks2mregions[create_duration(0, 10000)] consume</text--->"
") )";
Operator mflock2mregion (
"mflock2mregion", // name
MFlock2MRegionSpec, // specification
MFlock2MRegionVM, // value mapping
Operator::SimpleSelect, // trivial selection function
MFlock2MRegionTM // type mapping
);
class FlockAlgebra : public Algebra
{
public:
FlockAlgebra() : Algebra()
{
AddTypeConstructor( &flockTC );
AddTypeConstructor( &uflockTC );
AddTypeConstructor( &mflockTC );
flockTC.AssociateKind( Kind::DATA() );
uflockTC.AssociateKind( Kind::TEMPORAL() );
uflockTC.AssociateKind( Kind::DATA() );
mflockTC.AssociateKind( Kind::TEMPORAL() );
mflockTC.AssociateKind( Kind::DATA() );
AddOperator(&reportflocks);
AddOperator(&randommflock);
AddOperator(&mflock2mregion);
}
~FlockAlgebra() {};
};
};
/*
5 Initialization
*/
extern "C"
Algebra*
InitializeFlockAlgebra( NestedList* nlRef,
QueryProcessor* qpRef )
{
// The C++ scope-operator :: must be used to qualify the full name
return new FLOCK::FlockAlgebra;
}