6405 lines
184 KiB
C++
6405 lines
184 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 Spatiotemporal Group Pattern Algebra
|
|
|
|
JAN, 2010 Mahmoud Sakr
|
|
|
|
[TOC]
|
|
|
|
1 Overview
|
|
|
|
2 Defines and includes
|
|
|
|
*/
|
|
|
|
#include "GPatternAlgebra.h"
|
|
#include "Symbols.h"
|
|
#include "ListUtils.h"
|
|
#include "Stream.h"
|
|
|
|
using namespace mset;
|
|
using namespace temporalalgebra;
|
|
using namespace std;
|
|
using namespace datetime;
|
|
using namespace RegionInterpol;
|
|
|
|
namespace GPattern{
|
|
|
|
bool CheckRemoveEntry::changed = false;
|
|
|
|
/*
|
|
GPatternHelper
|
|
|
|
*/
|
|
|
|
ChangeRecord::ChangeRecord():
|
|
status(NotChanged),removedNodes(0), removedNodesInRemoved(0){}
|
|
|
|
bool ChangeRecord::UpdateStatus(StatusCode newCode)
|
|
{
|
|
if(status == NotChanged)
|
|
{
|
|
status = newCode;
|
|
return true;
|
|
}
|
|
if(status == ElemsRemoved && newCode != NotChanged)
|
|
{
|
|
status = newCode;
|
|
return true;
|
|
}
|
|
if(newCode == UnitRemoved)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ChangeRecord::AppendToRemovedNodes(int node)
|
|
{
|
|
this->removedNodes.push_back(node);
|
|
return true;
|
|
}
|
|
|
|
ostream& ChangeRecord::Print(ostream& os)
|
|
{
|
|
string statusText[]={"Unchanged", "NodesRemoved", "UnitDeleted"};
|
|
os<<"\n"<<statusText[this->status];
|
|
if(this->status == ElemsRemoved)
|
|
{
|
|
os<<": ";
|
|
PrintVector(this->removedNodes, os);
|
|
if(!this->removedNodesInRemoved.empty())
|
|
{
|
|
os<<endl<<"\tRemovedNodesInRemoved: ";
|
|
PrintVector(this->removedNodesInRemoved, os);
|
|
}
|
|
}
|
|
return os;
|
|
}
|
|
|
|
void ChangeRecord::Clear()
|
|
{
|
|
this->status= NotChanged;
|
|
this->removedNodes.clear();
|
|
this->removedNodesInRemoved.clear();
|
|
}
|
|
|
|
MSetIndex::MSetIndex(
|
|
CompressedInMemMSet& mset, vector<pair<int, int> >& edge2Nodes )
|
|
{
|
|
nodes.clear(); units.clear();
|
|
ConstructIndex(mset, edge2Nodes);
|
|
}
|
|
void MSetIndex::ConstructIndex(
|
|
CompressedInMemMSet& mset, vector<pair<int, int> >& edge2Nodes)
|
|
{
|
|
bool debugme= false;
|
|
if(debugme&& 0)
|
|
mset.Print(cerr);
|
|
if(mset.units.size()==0) return;
|
|
list<CompressedInMemUSet>::iterator i= mset.units.begin();
|
|
LWGraph graph;
|
|
set<int> deltaNodes;
|
|
int unitIndex=0;
|
|
int count=0;
|
|
while(i!= mset.units.end())
|
|
{
|
|
if(debugme)
|
|
{
|
|
// cerr<<"\n graph:";
|
|
// graph.print(cerr);
|
|
if(!(*i).added.empty())
|
|
{
|
|
cerr<<"\n addedEdges:";
|
|
PrintSet((*i).added, cerr);
|
|
}
|
|
if(!(*i).removed.empty())
|
|
{
|
|
cerr<<"\n removedEdges:";
|
|
PrintSet((*i).removed, cerr); //cerr<<"\nAccumlator: ";
|
|
}
|
|
// _mset.Print(cerr);
|
|
}
|
|
InsertEdgesUndirected(&graph, (*i).added, edge2Nodes, deltaNodes);
|
|
AppendInsertionsIntoNodeLog(deltaNodes, edge2Nodes, i, unitIndex);
|
|
count+= deltaNodes.size();
|
|
|
|
RemoveEdgesUndirected(&graph, (*i).removed, edge2Nodes, deltaNodes);
|
|
AppendRemovalsIntoNodeLog(deltaNodes, edge2Nodes, i, unitIndex);
|
|
count-= deltaNodes.size();
|
|
|
|
units.push_back(count);
|
|
// if(debugme)
|
|
// Print(&nodeHistory, cerr);
|
|
++i;
|
|
++unitIndex;
|
|
}
|
|
set<int> nodesNotFinalized;
|
|
graph.get_nodes(nodesNotFinalized);
|
|
FinalizeIndex(nodesNotFinalized, i);
|
|
}
|
|
|
|
void MSetIndex::FinalizeIndex(set<int>& nodesToBeFinalized,
|
|
list<CompressedInMemUSet>::iterator endIt)
|
|
{
|
|
NodeLogEntry* log;
|
|
list<CompressedInMemUSet>::iterator lastIt= endIt;
|
|
--lastIt;
|
|
for(set<int>::iterator it= nodesToBeFinalized.begin(); it!=
|
|
nodesToBeFinalized.end(); ++it)
|
|
{
|
|
log= &this->nodes[*it].log.back();
|
|
assertIf(log->endtime == -1);
|
|
log->endUnitIndex= this->units.size() - 1;
|
|
log->endUnitIt= lastIt;
|
|
log->endtime= (*lastIt).endtime;
|
|
}
|
|
}
|
|
|
|
void MSetIndex::AppendInsertionsIntoNodeLog(set<int>& deltaNodes,
|
|
vector<pair<int, int> >& edge2nodesMap,
|
|
list<CompressedInMemUSet>::iterator& curUSet, int curUSetIndex)
|
|
{
|
|
map<int, set<int> > nodeNeighbors;
|
|
int _edge;
|
|
int _node;
|
|
pair<int, int> edgeNodes;
|
|
map<int, set<int> >::iterator pos;
|
|
for(set<int>::iterator it= (*curUSet).added.begin(); it !=
|
|
(*curUSet).added.end(); ++it)
|
|
{
|
|
_edge= *it;
|
|
edgeNodes= edge2nodesMap[_edge];
|
|
_node= edgeNodes.first;
|
|
pos= nodeNeighbors.find(_node);
|
|
if(pos != nodeNeighbors.end())
|
|
(*pos).second.insert(_edge);
|
|
else
|
|
{
|
|
set<int> s; s.insert(_edge);
|
|
assert(
|
|
nodeNeighbors.insert(std::make_pair(_node, s)).second);
|
|
}
|
|
|
|
_node= edgeNodes.second;
|
|
pos= nodeNeighbors.find(_node);
|
|
if(pos != nodeNeighbors.end())
|
|
(*pos).second.insert(_edge);
|
|
else
|
|
{
|
|
set<int> s;
|
|
s.insert(_edge);
|
|
assert(
|
|
nodeNeighbors.insert(std::make_pair(_node, s)).second);
|
|
}
|
|
}
|
|
|
|
map<int, set<int> >::iterator nodeIt;
|
|
for(nodeIt= nodeNeighbors.begin(); nodeIt!= nodeNeighbors.end(); ++nodeIt)
|
|
{
|
|
_node= (*nodeIt).first;
|
|
if(deltaNodes.find(_node) == deltaNodes.end()){
|
|
assertIf(this->nodes.find(_node) != this->nodes.end());}
|
|
else{
|
|
assertIf((this->nodes.find(_node) == this->nodes.end()) ||
|
|
this->nodes[_node].log.back().endtime != -1);}
|
|
this->nodes[_node].Append(curUSet, curUSetIndex, (*nodeIt).second);
|
|
}
|
|
}
|
|
void MSetIndex::AppendRemovalsIntoNodeLog(set<int>& deltaNodes,
|
|
vector<pair<int, int> >& edge2nodesMap,
|
|
list<CompressedInMemUSet>::iterator& curUSet, int curUSetIndex)
|
|
{
|
|
bool debugme=false;
|
|
if(deltaNodes.empty()) return;
|
|
list<CompressedInMemUSet>::iterator lastUSet= curUSet;
|
|
--lastUSet;
|
|
if(debugme)
|
|
this->Print(cerr);
|
|
for(set<int>::iterator it= deltaNodes.begin(); it!= deltaNodes.end(); ++it)
|
|
{
|
|
assertIf(this->nodes.find(*it) != this->nodes.end());
|
|
if(debugme)
|
|
this->nodes[*it].Print(cerr);
|
|
assertIf(!this->nodes[*it].log.empty());
|
|
assertIf(this->nodes[*it].log.back().endtime == -1);
|
|
if(debugme)
|
|
cerr<<"\t"<<this->nodes[*it].log.back().endtime<<"\t";
|
|
this->nodes[*it].log.back().endtime= (*lastUSet).endtime;
|
|
this->nodes[*it].log.back().endUnitIt= lastUSet;
|
|
this->nodes[*it].log.back().endUnitIndex= curUSetIndex -1 ;
|
|
}
|
|
}
|
|
|
|
MSetIndex::NodeLogEntry::NodeLogEntry(
|
|
int64_t st, list<CompressedInMemUSet>::iterator stIt, int sUI, set<int>& aE):
|
|
starttime(st), endtime(-1), startUnitIt(stIt), startUnitIndex(sUI),
|
|
endUnitIndex(-1), associatedEdges(aE){}
|
|
|
|
ostream& MSetIndex::NodeLogEntry::Print(ostream& os)
|
|
{
|
|
// os<<"\n\tunit indexes ["<< this->startUnitIndex<<","
|
|
// <<this->endUnitIndex<<"]";
|
|
os<<",\t time [";
|
|
Instant i1(instanttype), i2(instanttype);
|
|
i1.ReadFrom(this->starttime); i1.Print(os);
|
|
os<<",";
|
|
i2.ReadFrom(this->endtime); i2.Print(os);
|
|
os<<"]";
|
|
os<<"\tDuration (min): "<< (i2 - i1).millisecondsToNull()/60000;
|
|
// os<<",\t timeFromUnit ["<< (*this->startUnitIt).starttime<<"," ;
|
|
// if(this->endUnitIndex == -1)
|
|
// os<< -1<<"]";
|
|
// else
|
|
// os<<(*this->endUnitIt).starttime;
|
|
// os<<"\n\tEdges"; PrintSet(this->associatedEdges, os);
|
|
return os;
|
|
}
|
|
|
|
void MSetIndex::NodeLog::Append(
|
|
list<CompressedInMemUSet>::iterator& usetIt, int usetIndex, set<int>& edges)
|
|
{
|
|
if(log.empty()|| log.back().endtime != -1)
|
|
{
|
|
log.push_back(NodeLogEntry((*usetIt).starttime, usetIt, usetIndex, edges));
|
|
return;
|
|
}
|
|
log.back().associatedEdges.insert(edges.begin(), edges.end());
|
|
}
|
|
|
|
bool MSetIndex::NodeLog::RemoveUnit(int index)
|
|
{
|
|
//needs tests
|
|
bool debugme=false;
|
|
if(this->log.empty() && 0)
|
|
{
|
|
cerr<<"Trying to remove from an empty NodeLog. "
|
|
"Something is going wrong here!";
|
|
return false;
|
|
}
|
|
if( this->log.empty() || //Should not really happen,
|
|
//but it happens. Needs more investigation.
|
|
index < this->log.front().startUnitIndex ||
|
|
index > this->log.back().endUnitIndex) return false;
|
|
|
|
if(debugme)
|
|
this->Print(cerr);
|
|
bool changed=false;
|
|
list<NodeLogEntry>::iterator firstPartIt, logEntryIt= this->log.begin();
|
|
NodeLogEntry* entry;
|
|
while(logEntryIt != this->log.end() && !changed)
|
|
{
|
|
entry= &(*logEntryIt);
|
|
assertIf(entry->endUnitIndex >= entry->startUnitIndex);
|
|
|
|
if(index== entry->startUnitIndex &&
|
|
entry->endUnitIndex == entry->startUnitIndex )
|
|
{
|
|
this->log.erase(logEntryIt++);
|
|
changed= true;
|
|
if(debugme)
|
|
this->Print(cerr);
|
|
}
|
|
else if(index == entry->startUnitIndex)
|
|
{
|
|
++(entry->startUnitIndex);
|
|
++(entry->startUnitIt);
|
|
entry->starttime= (*(entry->startUnitIt)).starttime;
|
|
assertIf(entry->starttime <= entry->endtime);
|
|
++logEntryIt;
|
|
changed= true;
|
|
if(debugme)
|
|
this->Print(cerr);
|
|
}
|
|
else if(index == entry->endUnitIndex )
|
|
{
|
|
--entry->endUnitIndex;
|
|
--entry->endUnitIt;
|
|
entry->endtime= (*entry->endUnitIt).endtime;
|
|
++logEntryIt;
|
|
changed= true;
|
|
if(debugme)
|
|
this->Print(cerr);
|
|
}
|
|
else if(index > entry->startUnitIndex && index < entry->endUnitIndex)
|
|
{
|
|
NodeLogEntry newEntry(*entry);
|
|
firstPartIt= this->log.insert(logEntryIt, newEntry);
|
|
(*firstPartIt).endUnitIndex= index - 1;
|
|
(*firstPartIt).endUnitIt= (*firstPartIt).startUnitIt;
|
|
for(int i=(*firstPartIt).startUnitIndex; i< index-1; ++i)
|
|
++(*firstPartIt).endUnitIt;
|
|
(*firstPartIt).endtime= (*(*firstPartIt).endUnitIt).endtime;
|
|
|
|
entry->startUnitIndex= index+1;
|
|
for(int i=entry->startUnitIndex; i< index+1; ++i)
|
|
++entry->startUnitIt;
|
|
entry->starttime= (*entry->startUnitIt).starttime;
|
|
++logEntryIt;
|
|
changed= true;
|
|
if(debugme)
|
|
this->Print(cerr);
|
|
}
|
|
else
|
|
++logEntryIt;
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
ostream& MSetIndex::NodeLog::Print(ostream& os)
|
|
{
|
|
int i=0;
|
|
list<NodeLogEntry>::iterator it= this->log.begin();
|
|
while(it != this->log.end())
|
|
{
|
|
os<<"\n NodeLog "<< i++;
|
|
(*it).Print(os);
|
|
++it;
|
|
}
|
|
return os;
|
|
}
|
|
|
|
bool MSetIndex::RemoveShortNodeEntries(
|
|
int64_t dMS, vector<ChangeRecord>& AllChanges)
|
|
{
|
|
map<int, NodeLog>::iterator nodeEntry= this->nodes.begin();
|
|
bool changed= false;
|
|
while(nodeEntry != this->nodes.end())
|
|
{
|
|
changed= RemoveShortNodeEntries(dMS, nodeEntry, AllChanges) || changed;
|
|
++nodeEntry;
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
void DecreaseUnitCount(int& cnt)
|
|
{
|
|
assertIf(cnt > 0);
|
|
--cnt;
|
|
}
|
|
|
|
class LogNodeRemoval {
|
|
private:
|
|
int nodeId;
|
|
public:
|
|
LogNodeRemoval(int id) : nodeId(id) {}
|
|
void operator() (ChangeRecord& elem) {
|
|
elem.UpdateStatus(ChangeRecord::ElemsRemoved);
|
|
elem.AppendToRemovedNodes(nodeId);
|
|
}
|
|
};
|
|
|
|
void CheckRemoveEntry::SetChanged(bool ch)
|
|
{
|
|
CheckRemoveEntry::changed= ch;
|
|
}
|
|
bool CheckRemoveEntry::GetChanged()
|
|
{
|
|
return CheckRemoveEntry::changed;
|
|
}
|
|
CheckRemoveEntry::CheckRemoveEntry(int id,
|
|
vector<ChangeRecord>& ch, MSetIndex* i, int64_t _dMS):
|
|
nodeId(id), AllChanges(&ch), index(i), dMS(_dMS){}
|
|
bool CheckRemoveEntry::operator() (MSetIndex::NodeLogEntry& logEntry)
|
|
{
|
|
bool debugme= false;
|
|
if(debugme)
|
|
{
|
|
cerr<< "\nbefore applying d:";
|
|
logEntry.Print(cerr);
|
|
}
|
|
if((logEntry.endtime - logEntry.starttime) < dMS)
|
|
{
|
|
for_each(index->units.begin() + logEntry.startUnitIndex,
|
|
index->units.begin()+ logEntry.endUnitIndex, DecreaseUnitCount);
|
|
for_each(AllChanges->begin() + logEntry.startUnitIndex,
|
|
AllChanges->begin()+ logEntry.endUnitIndex,
|
|
LogNodeRemoval(nodeId));
|
|
SetChanged(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
SetChanged(false);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool MSetIndex::RemoveShortNodeEntries(int64_t dMS,
|
|
map<int, NodeLog>::iterator nodeIt, vector<ChangeRecord>& AllChanges)
|
|
{
|
|
//bool debugme= false;
|
|
bool changed= false;
|
|
NodeLog* nodeLog= &(*nodeIt).second;
|
|
int nodeId= (*nodeIt).first;
|
|
list<NodeLogEntry>::iterator logEntryIt= nodeLog->log.begin();
|
|
NodeLogEntry* logEntry;
|
|
while(logEntryIt != nodeLog->log.end())
|
|
{
|
|
logEntry= &(*logEntryIt);
|
|
if((logEntry->endtime - logEntry->starttime) < dMS)
|
|
{
|
|
for_each(this->units.begin() + logEntry->startUnitIndex,
|
|
this->units.begin()+ logEntry->endUnitIndex + 1, DecreaseUnitCount);
|
|
// +1 is there because for_each loops over the interval [start, end)
|
|
for_each(AllChanges.begin() + logEntry->startUnitIndex,
|
|
AllChanges.begin()+ logEntry->endUnitIndex + 1,
|
|
LogNodeRemoval(nodeId));
|
|
if(AllChanges.begin() + logEntry->endUnitIndex + 1 != AllChanges.end())
|
|
AllChanges[logEntry->endUnitIndex + 1].removedNodesInRemoved.push_back(
|
|
nodeId);
|
|
nodeLog->log.erase(logEntryIt++);
|
|
changed= true;
|
|
}
|
|
else
|
|
{
|
|
++logEntryIt;
|
|
}
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
void MSetIndex::DeleteNodePart(map<int, NodeLog>::iterator& nodeIt,
|
|
list<NodeLogEntry>::iterator nodeEntryIt, vector<ChangeRecord>& AllChanges)
|
|
{
|
|
// NodeLogEntry* logEntry= &(*nodeEntryIt);
|
|
// for(int i= logEntry->startUnitIndex; i<=logEntry->endUnitIndex; ++i)
|
|
// {
|
|
// --(this->units[i]);
|
|
// AllChanges[i].UpdateStatus(ChangeRecord::ElemsRemoved);
|
|
// AllChanges[i].AppendRemovedEdges(logEntry->associatedEdges);
|
|
// }
|
|
// (*nodeIt).second.log.erase(nodeEntryIt);
|
|
}
|
|
|
|
bool MSetIndex::RemoveSmallUnits(int n, vector<ChangeRecord>& AllChanges)
|
|
{
|
|
bool changed= false;
|
|
for(unsigned int i=0; i<this->units.size(); ++i)
|
|
{
|
|
assertIf(this->units[i] >= -1);
|
|
if(this->units[i] < n && this->units[i] != -1)
|
|
{
|
|
changed= true;
|
|
RemoveUnit(i, AllChanges);
|
|
}
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
void MSetIndex::RemoveUnit(int index, vector<ChangeRecord>& AllChanges)
|
|
{
|
|
AllChanges[index].UpdateStatus(ChangeRecord::UnitRemoved);
|
|
this->units[index]= -1;
|
|
map<int, NodeLog>::iterator nodeIt= this->nodes.begin();
|
|
while(nodeIt != this->nodes.end())
|
|
{
|
|
(*nodeIt).second.RemoveUnit(index);
|
|
++nodeIt;
|
|
}
|
|
}
|
|
|
|
ostream& MSetIndex::Print(ostream& os)
|
|
{
|
|
map<int, NodeLog>::iterator nodesIt= this->nodes.begin();
|
|
while(nodesIt != this->nodes.end())
|
|
{
|
|
os<<"\n\nIndex Node: "<<(*nodesIt).first;
|
|
(*nodesIt).second.Print(os);
|
|
++nodesIt;
|
|
}
|
|
return os;
|
|
}
|
|
|
|
bool GPatternHelper::setCompareDesc (set<int>& i,set<int>& j)
|
|
{
|
|
if(includes(i.begin(), i.end(), j.begin(), j.end())) return true;
|
|
if(i > j) return true;
|
|
return false;
|
|
}
|
|
void GPatternHelper::RemoveDuplicates(list<CompressedInMemUSet>& resStream)
|
|
{
|
|
//sort(resStream.begin(), resStream.end(), setCompareDesc);
|
|
|
|
}
|
|
|
|
void GPatternHelper::removeShortUnits(MBool &mbool, int64_t dMS)
|
|
{
|
|
UBool ubool;
|
|
int64_t starttime, endtime;
|
|
for(int i= 0; i< mbool.GetNoComponents(); ++i)
|
|
{
|
|
mbool.Get(i, ubool);
|
|
starttime= ubool.timeInterval.start.millisecondsToNull();
|
|
endtime= ubool.timeInterval.end.millisecondsToNull();
|
|
if(endtime - starttime < dMS)
|
|
{
|
|
ubool.constValue.Set(false, false);
|
|
mbool.Put(i, ubool);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GPatternHelper::RemoveShortNodeMembership(
|
|
CompressedInMemMSet& Accumlator,
|
|
vector<pair<int, int> >& edge2nodesMap, int64_t dMS)
|
|
{
|
|
bool debugme= false;
|
|
if(debugme)
|
|
Accumlator.Print(cerr);
|
|
bool changed=false;
|
|
if(Accumlator.units.size()==0) return false;
|
|
list<CompressedInMemUSet>::iterator i= Accumlator.units.begin();
|
|
LWGraph graph;
|
|
typedef pair<list<CompressedInMemUSet>::iterator, set<int> > NodeItNeighbors;
|
|
map<int, NodeItNeighbors> nodeHistory;
|
|
set<int> deltaNodes;
|
|
while(i!= Accumlator.units.end())
|
|
{
|
|
if(debugme)
|
|
{
|
|
cerr<<"\n graph:";
|
|
graph.print(cerr);
|
|
cerr<<"\n addedEdges:";
|
|
PrintSet((*i).added, cerr);
|
|
cerr<<"\n removedEdges:";
|
|
PrintSet((*i).removed, cerr); cerr<<"\nAccumlator: ";
|
|
Accumlator.Print(cerr);
|
|
}
|
|
InsertEdgesUndirected(&graph, (*i).added, edge2nodesMap, deltaNodes);
|
|
InsertInNodeHistory(&nodeHistory, (*i).added, edge2nodesMap, i, deltaNodes);
|
|
if(debugme)
|
|
PrintNodeHistory(&nodeHistory, cerr);
|
|
RemoveEdgesUndirected(&graph, (*i).removed, edge2nodesMap, deltaNodes);
|
|
changed= (CheckRemoveNodeMembership(
|
|
&nodeHistory, (*i).removed, edge2nodesMap, i, deltaNodes, dMS)||changed);
|
|
if(debugme)
|
|
PrintNodeHistory(&nodeHistory, cerr);
|
|
++i;
|
|
}
|
|
//Remove the units which have empty added and removed sets
|
|
//Accumlator.RemoveConstUnits();
|
|
return changed;
|
|
}
|
|
|
|
ostream& GPatternHelper::PrintNodeHistory(
|
|
map<int, pair<list<CompressedInMemUSet>::iterator, set<int> > >* nodeHistory,
|
|
ostream &os )
|
|
{
|
|
map<int, pair<list<CompressedInMemUSet>::iterator,set<int> > >::iterator i;
|
|
i= nodeHistory->begin();
|
|
while(i != nodeHistory->end())
|
|
{
|
|
os<<endl<<"node "<< (*i).first;
|
|
os<<" started at time "<< (*((*i).second.first)).starttime;
|
|
os<<", and it is connected by edges ";
|
|
PrintSet((*i).second.second, cerr);
|
|
++i;
|
|
}
|
|
return os;
|
|
}
|
|
|
|
bool GPatternHelper::CheckRemoveNodeMembership(
|
|
map<int, pair<list<CompressedInMemUSet>::iterator, set<int> > >* nodeHistory,
|
|
set<int> removedEdges, vector<pair<int, int> >& edge2nodesMap,
|
|
list<CompressedInMemUSet>::iterator& cur, set<int>& deltaNodes, int64_t dMS)
|
|
{
|
|
int64_t nodeMembershipDuration;
|
|
bool changed=false;
|
|
map<int, pair<list<CompressedInMemUSet>::iterator,set<int> > >::iterator pos;
|
|
list<CompressedInMemUSet>::iterator nodeFirstUnitIt, curUnitIt;
|
|
set<int>* nodeEdges;
|
|
int _node;
|
|
for(set<int>::iterator it= deltaNodes.begin(); it!=deltaNodes.end(); ++it)
|
|
{
|
|
_node= *it;
|
|
pos= nodeHistory->find(_node);
|
|
assert(pos != nodeHistory->end());
|
|
nodeFirstUnitIt= (*pos).second.first;
|
|
nodeMembershipDuration= (*cur).starttime - (*nodeFirstUnitIt).starttime;
|
|
if(nodeMembershipDuration < dMS)
|
|
{
|
|
changed= true;
|
|
nodeEdges= & (*pos).second.second;
|
|
curUnitIt= nodeFirstUnitIt;
|
|
while(curUnitIt != cur)
|
|
{
|
|
InPlaceSetDifference((*curUnitIt).added, *nodeEdges);
|
|
InPlaceSetDifference((*curUnitIt).removed, *nodeEdges);
|
|
++curUnitIt;
|
|
}
|
|
InPlaceSetDifference((*curUnitIt).added, *nodeEdges);
|
|
InPlaceSetDifference((*curUnitIt).removed, *nodeEdges);
|
|
}
|
|
nodeHistory->erase(pos);
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
void GPatternHelper::InPlaceSetDifference(set<int>& set1, set<int>& set2)
|
|
{
|
|
if(set1.empty() || set2.empty()) return;
|
|
set<int>::iterator first1, first2, last1, last2;
|
|
first1= set1.begin(); first2= set2.begin();
|
|
last1 = --set1.end(); last2= --set2.end();
|
|
if( (*last1 < *first2) || (*last2 < *first1) ) return;
|
|
++last1; ++last2;
|
|
|
|
while (first1 != last1 && first2 != last2)
|
|
{
|
|
if (*first1 < *first2)
|
|
++first1;
|
|
else if (*first2 < *first1)
|
|
++first2;
|
|
else
|
|
{
|
|
set1.erase(first1++);
|
|
++first2;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void GPatternHelper::InsertInNodeHistory(
|
|
map<int, pair<list<CompressedInMemUSet>::iterator, set<int> > >* nodeHistory,
|
|
set<int> newEdges, vector<pair<int, int> >& edge2nodesMap,
|
|
list<CompressedInMemUSet>::iterator& cur, set<int>& deltaNodes)
|
|
{
|
|
int _edge;
|
|
set<int> newNodeEdges;
|
|
pair<int, int>* edgeNodes;
|
|
map<int, pair<list<CompressedInMemUSet>::iterator, set<int> > >::iterator pos;
|
|
set<int>* nodeHistoryEdges;
|
|
for(set<int>::iterator it= newEdges.begin(); it!=newEdges.end(); ++it)
|
|
{
|
|
_edge= *it;
|
|
edgeNodes= &edge2nodesMap[_edge];
|
|
pos= nodeHistory->find(edgeNodes->first);
|
|
if(pos != nodeHistory->end())
|
|
{
|
|
nodeHistoryEdges= &(*pos).second.second;
|
|
nodeHistoryEdges->insert(_edge);
|
|
}
|
|
else
|
|
{
|
|
assertIf(deltaNodes.find(edgeNodes->first) != deltaNodes.end());
|
|
FindNodeEdges(edgeNodes->first, newEdges, edge2nodesMap, newNodeEdges);
|
|
nodeHistory->insert(
|
|
make_pair(edgeNodes->first, make_pair(cur, newNodeEdges)));
|
|
}
|
|
|
|
pos= nodeHistory->find(edgeNodes->second);
|
|
if(pos != nodeHistory->end())
|
|
{
|
|
nodeHistoryEdges= &(*pos).second.second;
|
|
nodeHistoryEdges->insert(_edge);
|
|
}
|
|
else
|
|
{
|
|
assertIf(deltaNodes.find(edgeNodes->second) != deltaNodes.end());
|
|
FindNodeEdges(edgeNodes->second, newEdges, edge2nodesMap, newNodeEdges);
|
|
nodeHistory->insert(
|
|
make_pair(edgeNodes->second, make_pair(cur, newNodeEdges)));
|
|
}
|
|
}
|
|
}
|
|
|
|
void GPatternHelper::FindNodeEdges(
|
|
int newNode, set<int>& newEdges, vector<pair<int, int> >& edge2nodesMap,
|
|
set<int>& newNodeEdges)
|
|
{
|
|
newNodeEdges.clear();
|
|
pair<int, int>* edgeNodes;
|
|
for(set<int>::iterator it= newEdges.begin(); it!=newEdges.end(); ++it)
|
|
{
|
|
edgeNodes= &edge2nodesMap[*it];
|
|
if(edgeNodes->first == newNode || edgeNodes->second == newNode)
|
|
newNodeEdges.insert(*it);
|
|
}
|
|
}
|
|
bool GPatternHelper::RemoveUnitsHavingFewNodes(
|
|
CompressedInMemMSet& Accumlator,
|
|
vector<pair<int, int> >& edge2nodesMap, int n)
|
|
{
|
|
//bool debugme= false;
|
|
bool changed=false;
|
|
if(Accumlator.units.size()==0) return false;
|
|
list<CompressedInMemUSet>::iterator i= Accumlator.units.begin();
|
|
LWGraph graph;
|
|
vector<list<CompressedInMemUSet>::iterator> unitsToRemove;
|
|
while(i!= Accumlator.units.end())
|
|
{
|
|
InsertEdgesUndirected(&graph, (*i).added, edge2nodesMap);
|
|
RemoveEdgesUndirected(&graph, (*i).removed, edge2nodesMap);
|
|
if(graph.nodes_count() < n)
|
|
unitsToRemove.push_back(i);
|
|
++i;
|
|
}
|
|
|
|
if(!unitsToRemove.empty())
|
|
{
|
|
changed=true;
|
|
for(unsigned int j=0; j< unitsToRemove.size(); ++j)
|
|
Accumlator.EraseUnit(unitsToRemove[j]);
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
void GPatternHelper::FindLargeDynamicComponents(CompressedInMemMSet& Accumlator,
|
|
list<CompressedInMemUSet>::iterator begin,
|
|
list<CompressedInMemUSet>::iterator end ,
|
|
vector<pair<int,int> >& edge2nodesMap, int64_t dMS, int n, string& qts,
|
|
list<CompressedMSet*>*& finalResStream, int depth)
|
|
{
|
|
bool debugme= false;
|
|
//list<CompressedInMemUSet>::iterator cur= begin;
|
|
set<int> s;
|
|
list<CompressedMSet*>* resStream= 0;
|
|
finalResStream= new list<CompressedMSet*>(0);
|
|
GPatternHelper GPHelper;
|
|
StopWatch timer;
|
|
if(debugme)
|
|
{
|
|
cerr<<"\nFindSubGraphs started at depth " << depth;
|
|
cerr<<"\nAccumlator has " << Accumlator.GetNoComponents()<< " units";
|
|
}
|
|
|
|
timer.start();
|
|
FindDynamicComponents(Accumlator, begin, end, edge2nodesMap, dMS, n, qts,
|
|
resStream);
|
|
|
|
double FindCCSecondsCPU = timer.diffSecondsCPU();
|
|
double FindCCSecondsReal = timer.diffSecondsReal();
|
|
cerr<< "\n ########### TIMER ############ \n";
|
|
cerr<<"Finding Connected Components took (CPU/Real) (" <<
|
|
FindCCSecondsCPU << "/" << FindCCSecondsReal << ") seconds.\n";
|
|
timer.start();
|
|
|
|
if(debugme && 0)
|
|
{
|
|
list<CompressedMSet*>::iterator it= resStream->begin();
|
|
while(it != resStream->end())
|
|
{
|
|
(*it)->Print(cerr);
|
|
CompressedMSet* tmp= EdgeMSet2NodeMSet(*it, edge2nodesMap);
|
|
CompressedInMemMSet tmp1;
|
|
tmp->WriteToCompressedInMemMSet(tmp1);
|
|
MSet tmp2(true);
|
|
tmp1.WriteToMSet(tmp2);
|
|
tmp2.Print(cerr);
|
|
delete tmp;
|
|
++it;
|
|
}
|
|
}
|
|
//To be deleted
|
|
// finalResStream= resStream;
|
|
// return;
|
|
//End of to be deleted
|
|
|
|
if(debugme)
|
|
cerr<<"\nFindDynamicComponents returned";
|
|
bool changed= true;
|
|
list<CompressedMSet*> localResStream;
|
|
CompressedMSet* curMSet=0;
|
|
vector<ChangeRecord> Changes;
|
|
CompressedInMemMSet inMemMSet;
|
|
int cnt=0;
|
|
while(resStream->begin() != resStream->end())
|
|
{
|
|
++cnt;
|
|
curMSet= resStream->front();
|
|
if(debugme && 0)
|
|
{
|
|
curMSet->Print(cerr);
|
|
CompressedMSet* tmp= EdgeMSet2NodeMSet(curMSet, edge2nodesMap);
|
|
CompressedInMemMSet tmp1;
|
|
tmp->WriteToCompressedInMemMSet(tmp1);
|
|
MSet tmp2(true);
|
|
tmp1.WriteToMSet(tmp2);
|
|
tmp2.Print(cerr);
|
|
delete tmp;
|
|
}
|
|
if((size_t)curMSet->GetNoComponents() < Changes.max_size())
|
|
{
|
|
Changes.reserve(curMSet->GetNoComponents());
|
|
Changes.resize(curMSet->GetNoComponents());
|
|
}
|
|
else
|
|
assert(false);
|
|
curMSet->WriteToCompressedInMemMSet(inMemMSet);
|
|
MSetIndex index(inMemMSet, edge2nodesMap);
|
|
changed=
|
|
GPHelper.ApplyThresholds(index, n, dMS, Changes, false);
|
|
if(changed)
|
|
{
|
|
GPHelper.UpdateResult(
|
|
&inMemMSet, edge2nodesMap, n, dMS, qts, Changes, localResStream,
|
|
false);
|
|
resStream->splice(resStream->end(), localResStream);
|
|
delete curMSet;
|
|
}
|
|
else
|
|
finalResStream->push_back(curMSet);
|
|
resStream->pop_front();
|
|
if(debugme&& 0)
|
|
{
|
|
list<CompressedMSet*>::iterator it= resStream->begin();
|
|
while(it != resStream->end())
|
|
{
|
|
//cerr<<(*it)->GetNoComponents();
|
|
//(*it)->Print(cerr);
|
|
CompressedMSet* tmp= EdgeMSet2NodeMSet(*it, edge2nodesMap);
|
|
CompressedInMemMSet tmp1;
|
|
tmp->WriteToCompressedInMemMSet(tmp1);
|
|
MSet tmp2(true);
|
|
tmp1.WriteToMSet(tmp2);
|
|
tmp2.Print(cerr);
|
|
delete tmp;
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
double FindLCCSecondsCPU = timer.diffSecondsCPU();
|
|
double FindLCCSecondsReal = timer.diffSecondsReal();
|
|
cerr<< "\n ########### TIMER ############ \n";
|
|
cerr<<"Finding Large Connected Components took (CPU/Real) (" <<
|
|
FindLCCSecondsCPU << "/" << FindLCCSecondsReal << ") seconds.\n";
|
|
delete resStream;
|
|
}
|
|
|
|
struct
|
|
checkShortDelete: binary_function< CompressedMSet* , int64_t, bool>
|
|
{
|
|
public:
|
|
bool operator() (CompressedMSet* _mset, int64_t dMS) const
|
|
{
|
|
if(_mset->units.Size() == 0)
|
|
{
|
|
delete _mset;
|
|
return true;
|
|
}
|
|
CompressedUSetRef uset;
|
|
_mset->units.Get(0, uset);
|
|
int64_t starttime= uset.starttime;
|
|
_mset->units.Get(_mset->units.Size() - 1, uset);
|
|
int64_t endtime= uset.endtime;
|
|
if(endtime - starttime < dMS)
|
|
{
|
|
delete _mset;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
CompressedMSet* GPatternHelper::CollectResultParts(
|
|
vector<CompressedMSet*>& ResultParts, vector<int>& partIndexs)
|
|
{
|
|
bool debugme= false;
|
|
if(debugme)
|
|
{
|
|
cerr<<"\nCollecting parts:";
|
|
for(unsigned int partIndex=0; partIndex < partIndexs.size(); ++partIndex)
|
|
cerr<<partIndexs[partIndex]<< ", ";
|
|
}
|
|
|
|
CompressedMSet* result= new CompressedMSet(0);
|
|
for(unsigned int partIndex=0; partIndex < partIndexs.size(); ++partIndex)
|
|
{
|
|
if(debugme)
|
|
ResultParts[partIndexs[partIndex]]->Print(cerr);
|
|
result->Concat( ResultParts[partIndexs[partIndex]]);
|
|
if(debugme)
|
|
{
|
|
//ResultParts[partIndexs[partIndex]]->Print(cerr);
|
|
result->Print(cerr);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void GPatternHelper::FindDynamicComponents(CompressedInMemMSet& Accumlator,
|
|
list<CompressedInMemUSet>::iterator begin,
|
|
list<CompressedInMemUSet>::iterator end ,
|
|
vector<pair<int, int> >& edge2nodesMap, int64_t dMS, int n, string& qts,
|
|
list<CompressedMSet*>*& FinalResultStream)
|
|
{
|
|
bool debugme= true;
|
|
set<int> constValue;
|
|
map<int, int> _map;
|
|
vector<int> mergeIndex;
|
|
int cnt= 0, totalNodesNum= Accumlator.GetNoComponents();
|
|
|
|
vector<CompressedMSet*>* ResultParts= new vector<CompressedMSet*>(0);
|
|
list<vector<int> > *ResultStream= new list<vector<int> >(0);
|
|
FinalResultStream= new list<CompressedMSet*>(0);
|
|
list<CompressedInMemUSet>::iterator cur= begin;
|
|
LWGraph* graph= new LWGraph();
|
|
list<Component*>* components= new list<Component*>();
|
|
map<int, list<Component*>::iterator> compLabelsMap;
|
|
int NextComponentLabel= 0;
|
|
|
|
while(cur != end)
|
|
{
|
|
if(debugme && (cnt%100 == 0))
|
|
{
|
|
cerr<<"\n\nProcessing unit number: " << cnt <<"/" << totalNodesNum;
|
|
cerr<<". Unit has: " <<(*cur).count<<" elems";
|
|
cerr<<"\nresStream has: " <<ResultStream->size();
|
|
cerr<<" results, finalResStream has: " <<FinalResultStream->size();
|
|
}
|
|
++cnt;
|
|
|
|
DynamicGraphAppend(graph, components, compLabelsMap, cur,
|
|
edge2nodesMap, dMS, n, qts, NextComponentLabel, ResultParts,
|
|
ResultStream, FinalResultStream);
|
|
++cur;
|
|
}
|
|
|
|
if(debugme && 0)
|
|
{
|
|
cerr<< "\nfinalResStream contains "<<
|
|
FinalResultStream->size() << " results\n";
|
|
for(list<CompressedMSet*>::iterator
|
|
it= FinalResultStream->begin(); it != FinalResultStream->end(); ++it)
|
|
(*it)->Print(cerr);
|
|
}
|
|
|
|
|
|
//finalize the components
|
|
--cur;
|
|
for(list<Component*>::iterator compIt= components->begin(); compIt!=
|
|
components->end(); ++compIt)
|
|
(*compIt)->ExtendResStreamsTillNow(*ResultParts, (*cur).endtime, (*cur).rc);
|
|
++cur;
|
|
|
|
//list<vector<int> >::iterator resultIt= ResultStream->begin();
|
|
while(!ResultStream->empty())
|
|
{
|
|
CompressedMSet* result=
|
|
CollectResultParts(*ResultParts, ResultStream->front());
|
|
FinalResultStream->push_back(result);
|
|
ResultStream->pop_front();
|
|
}
|
|
if(debugme && 0)
|
|
{
|
|
cerr<< "\nfinalResStream contains "<<
|
|
FinalResultStream->size() << " results\n";
|
|
for(list<CompressedMSet*>::iterator
|
|
it= FinalResultStream->begin(); it != FinalResultStream->end(); ++it)
|
|
(*it)->Print(cerr);
|
|
}
|
|
while(!ResultParts->empty())
|
|
{
|
|
delete ResultParts->back();
|
|
ResultParts->pop_back();
|
|
}
|
|
for(list<Component*>::iterator it= components->begin(); it!=
|
|
components->end(); ++it)
|
|
delete *it;
|
|
delete components;
|
|
delete graph;
|
|
delete ResultParts;
|
|
delete ResultStream;
|
|
}
|
|
|
|
/*
|
|
SetIntersects
|
|
|
|
*/
|
|
bool GPatternHelper::SetIntersects(set<int> &set1, set<int> &set2)
|
|
{
|
|
if(set1.empty() || set2.empty()) return false;
|
|
set<int>::iterator first1= set1.begin(), first2= set2.begin(),
|
|
last1 = set1.end(), last2 = set2.end();
|
|
--last1; --last2;
|
|
|
|
if( (*last1 < *first2) || (*last2 < *first1) ) return false;
|
|
++last1; ++last2;
|
|
|
|
while (first1 != last1 && first2 != last2)
|
|
{
|
|
if (*first1 < *first2)
|
|
++first1;
|
|
else if (*first2 < *first1)
|
|
++first2;
|
|
else return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void GPatternHelper::CheckAdd( LWGraph* g, NewComponent& comp, int n ,
|
|
list<Component*>* components,
|
|
map<int, list<Component*>::iterator>& compLabelsMap,
|
|
int& NextComponentLabel)
|
|
{
|
|
if((comp.newNodes.size()* 1.0) >= n)
|
|
{
|
|
Component* newComp= new Component();
|
|
newComp->message = Component::NewlyAdded;
|
|
newComp->label= NextComponentLabel++;
|
|
newComp->nodes.insert(comp.newNodes.begin(), comp.newNodes.end());
|
|
components->push_back(newComp);
|
|
compLabelsMap[newComp->label]= --components->end();
|
|
SetGraphNodesComponent(g, comp.newNodes, newComp->label);
|
|
}
|
|
}
|
|
|
|
void GPatternHelper::UpdateMerge(LWGraph *g, NewComponent& newComp,
|
|
set<int>& newEdges, vector<pair<int, int> >& edge2nodesMap,
|
|
list<Component*>* components,
|
|
map<int, list<Component*>::iterator>& compLabelsMap)
|
|
{
|
|
map<int, list<Component*>::iterator>::iterator affectedCompMap=
|
|
compLabelsMap.find(newComp.affectedComponents[0]);
|
|
assertIf(affectedCompMap != compLabelsMap.end());
|
|
list<Component*>::iterator affectedComp= (*affectedCompMap).second;
|
|
|
|
assertIf(affectedComp != components->end());
|
|
assertIf((*affectedComp)->addedEdges.empty());
|
|
|
|
for(set<int>::iterator newNodesIt= newComp.newNodes.begin(); newNodesIt!=
|
|
newComp.newNodes.end(); ++newNodesIt)
|
|
{
|
|
set<pair<int,int> >* newNodeNeighbors= &(*(g->node_index[*newNodesIt]));
|
|
for(set<pair<int,int> >::iterator neis= newNodeNeighbors->begin(); neis!=
|
|
newNodeNeighbors->end(); ++neis)
|
|
(*affectedComp)->addedEdges.insert((*neis).second);
|
|
}
|
|
pair<int,int>* edgeNodes;
|
|
for(set<int>::iterator newEdge= newEdges.begin(); newEdge!=
|
|
newEdges.end(); ++newEdge)
|
|
{
|
|
edgeNodes= &edge2nodesMap[*newEdge];
|
|
if(((*affectedComp)->nodes.find(edgeNodes->first) !=
|
|
(*affectedComp)->nodes.end())
|
|
||
|
|
((*affectedComp)->nodes.find(edgeNodes->second) !=
|
|
(*affectedComp)->nodes.end()))
|
|
(*affectedComp)->addedEdges.insert(*newEdge);
|
|
}
|
|
assert((*affectedComp)->UpdateMessage(Component::AddedEdges));
|
|
(*affectedComp)->nodes.insert(
|
|
newComp.newNodes.begin(), newComp.newNodes.end());
|
|
for(set<int>::iterator nodeIt= newComp.newNodes.begin(); nodeIt !=
|
|
newComp.newNodes.end(); ++nodeIt)
|
|
{
|
|
assertIf(g->node_component.find(*nodeIt) == g->node_component.end());
|
|
g->node_component.insert(make_pair(*nodeIt, (*affectedComp)->label));
|
|
}
|
|
|
|
}
|
|
|
|
void GPatternHelper::MergeComponents(LWGraph* g, NewComponent& newComp,
|
|
list<Component*>* components,
|
|
map<int, list<Component*>::iterator>& compLabelsMap,
|
|
int& NextComponentLabel)
|
|
{
|
|
vector< list<Component*>::iterator> affectedComponents;
|
|
map<int, list<Component*>::iterator>::iterator affectedCompMap;
|
|
list<Component*>::iterator affectedComp;
|
|
|
|
for(unsigned int i=0; i< newComp.affectedComponents.size(); ++i)
|
|
{
|
|
affectedCompMap= compLabelsMap.find(newComp.affectedComponents[i]);
|
|
assertIf(affectedCompMap != compLabelsMap.end());
|
|
affectedComp= (*affectedCompMap).second;
|
|
affectedComponents.push_back(affectedComp);
|
|
}
|
|
|
|
Component* bigComp= new Component();
|
|
for(unsigned int i=0; i< affectedComponents.size(); ++i)
|
|
bigComp->Union(*affectedComponents[i]);
|
|
//a union of nodes, messages, and associatedResults
|
|
if(! newComp.newNodes.empty())
|
|
{
|
|
bigComp->nodes.insert(newComp.newNodes.begin(), newComp.newNodes.end());
|
|
assert(bigComp->UpdateMessage(Component::AddedEdges));
|
|
}
|
|
bigComp->label= NextComponentLabel++;
|
|
assert(bigComp->UpdateMessage(Component::MergedFromExistingComponents));
|
|
for(unsigned int i=0; i< affectedComponents.size(); ++i)
|
|
{
|
|
compLabelsMap.erase((*affectedComponents[i])->label);
|
|
delete *affectedComponents[i];
|
|
components->erase(affectedComponents[i]);
|
|
}
|
|
|
|
for(set<int>::iterator nodeIt= bigComp->nodes.begin(); nodeIt !=
|
|
bigComp->nodes.end(); ++nodeIt)
|
|
g->node_component[*nodeIt] = bigComp->label;
|
|
|
|
components->push_back(bigComp);
|
|
compLabelsMap[bigComp->label]= --components->end();
|
|
}
|
|
|
|
void GPatternHelper::UpdateRemove(LWGraph* graph, list<Component*>* components,
|
|
map<int, list<Component*>::iterator>& compLabelsMap,
|
|
vector<pair<int, int> >& edge2nodesMap, int n, int& NextComponentLabel,
|
|
set< int>& affectedComponentsLabels)
|
|
{
|
|
list<Component*>::iterator affectedComponentIt;
|
|
pair<int, int>* edgeNodes;
|
|
list<set<int> > splitComponents;
|
|
set<int>* splitComponent;
|
|
bool disconnected= false;
|
|
list<Component*>::iterator affectedComponentsIt;
|
|
map<int, list<Component*>::iterator>::iterator affectedCompMap;
|
|
|
|
for(set<int>::iterator affectedComponentLabelIt=
|
|
affectedComponentsLabels.begin(); affectedComponentLabelIt!=
|
|
affectedComponentsLabels.end(); ++affectedComponentLabelIt)
|
|
{
|
|
affectedCompMap= compLabelsMap.find(*affectedComponentLabelIt);
|
|
assertIf(affectedCompMap != compLabelsMap.end());
|
|
affectedComponentIt= (*affectedCompMap).second;
|
|
assertIf(affectedComponentIt != components->end());
|
|
(*affectedComponentIt)->SynchronizeNodes(graph);
|
|
if((*affectedComponentIt)->nodes.size() < (unsigned int) n)
|
|
{
|
|
assert((*affectedComponentIt)->UpdateMessage(Component::RemoveNow));
|
|
RemoveGraphNodesComponent(graph, (*affectedComponentIt)->nodes);
|
|
continue;
|
|
}
|
|
|
|
disconnected= false;
|
|
for(set<int>::iterator edgeIt=
|
|
(*affectedComponentIt)->removedEdges.begin(); edgeIt!=
|
|
(*affectedComponentIt)->removedEdges.end() && !disconnected; ++edgeIt)
|
|
{
|
|
edgeNodes= &edge2nodesMap[*edgeIt];
|
|
disconnected= disconnected || !(*affectedComponentIt)->IsConnected(graph,
|
|
edgeNodes->first, edgeNodes->second);
|
|
}
|
|
if(disconnected)
|
|
{
|
|
splitComponents.clear();
|
|
(*affectedComponentIt)->Cluster(graph, splitComponents);
|
|
list<set<int> >::iterator splitComponentIt= splitComponents.begin();
|
|
while(splitComponentIt != splitComponents.end())
|
|
{
|
|
splitComponent= &(*splitComponentIt);
|
|
if(splitComponent->size()< (unsigned int) n)
|
|
{
|
|
RemoveGraphNodesComponent(graph, *splitComponent);
|
|
splitComponents.erase(splitComponentIt++);
|
|
}
|
|
else
|
|
++splitComponentIt;
|
|
}
|
|
|
|
if(splitComponents.empty())
|
|
{
|
|
//a deletion of a complete component
|
|
assert((*affectedComponentIt)->UpdateMessage(Component::RemoveNow));
|
|
}
|
|
else if(splitComponents.size() ==1 )
|
|
{
|
|
splitComponent= &(*splitComponents.begin());
|
|
assert((*affectedComponentIt)->UpdateMessage(Component::RemovedEdges));
|
|
vector<int> removedNodes(
|
|
(*affectedComponentIt)->nodes.size()- (*splitComponent).size()+1);
|
|
vector<int>::iterator removedNodesEndIt=
|
|
set_difference(
|
|
(*affectedComponentIt)->nodes.begin(),
|
|
(*affectedComponentIt)->nodes.end(),
|
|
(*splitComponent).begin(), (*splitComponent).end(),
|
|
removedNodes.begin());
|
|
|
|
int curNode;
|
|
list< set< pair<int, int> > >::iterator curNodeNeighborsIt;
|
|
set< pair<int, int> >* curNodeNeighbors;
|
|
|
|
for(vector<int>::iterator rn= removedNodes.begin(); rn!=
|
|
removedNodesEndIt; ++rn)
|
|
{
|
|
curNode= *rn;
|
|
(*affectedComponentIt)->nodes.erase(curNode);
|
|
curNodeNeighborsIt= graph->node_index[curNode];
|
|
curNodeNeighbors= &(*curNodeNeighborsIt);
|
|
for(set<pair<int,int> >::iterator nIt= curNodeNeighbors->begin();
|
|
nIt!= curNodeNeighbors->end(); ++nIt)
|
|
(*affectedComponentIt)->removedEdges.insert((*nIt).second);
|
|
}
|
|
}
|
|
else// If(splitComponents.count > 1)
|
|
{
|
|
//a split of a component
|
|
list<set<int> >::iterator splitComponentIt= splitComponents.begin();
|
|
splitComponent= &(*splitComponentIt);
|
|
assert((*affectedComponentIt)->UpdateMessage(
|
|
Component::SplitFromExtistingComponent));
|
|
(*affectedComponentIt)->nodes.clear();
|
|
(*affectedComponentIt)->nodes = *splitComponent ;
|
|
++splitComponentIt;
|
|
while(splitComponentIt != splitComponents.end())
|
|
{
|
|
splitComponent= &(*splitComponentIt);
|
|
Component* newComponent= new Component();
|
|
newComponent->SetMessage((*affectedComponentIt)->message);
|
|
newComponent->nodes= *splitComponent;
|
|
newComponent->associatedResults.assign(
|
|
(*affectedComponentIt)->associatedResults.begin(),
|
|
(*affectedComponentIt)->associatedResults.end());
|
|
newComponent->label= NextComponentLabel++;
|
|
newComponent->parentLabel= (*affectedComponentIt)->label;
|
|
UpdateGraphNodesComponent(
|
|
graph, *splitComponent, newComponent->label);
|
|
components->push_back(newComponent);
|
|
compLabelsMap[newComponent->label]= --components->end();
|
|
++splitComponentIt;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
Finalize
|
|
|
|
*/
|
|
void GPatternHelper::Finalize(LWGraph* graph, list<Component*>* components,
|
|
int64_t dMS, CompressedInMemUSet& cur, vector<CompressedMSet*>& ResultParts,
|
|
list<vector<int> > *ResultStream, list<CompressedMSet*>* FinalResultStream,
|
|
vector<pair<int, int> >& edge2nodesMap)
|
|
{
|
|
bool debugme= false;
|
|
|
|
string CounterName[]={"NotChanged", "AddedEdges", "RemovedEdges",
|
|
"AddRemoveMix", "NewlyAdded", "RemoveNow", "SplitFromExtistingComponent",
|
|
"MergedFromExistingComponents", "ReDistribute"};
|
|
|
|
vector<list<Component*>::iterator> compsToErase;
|
|
vector<list< vector<int> >::iterator> resToErase;
|
|
set<int> processedParents;
|
|
for(list<Component*>::iterator compIt= components->begin(); compIt!=
|
|
components->end(); ++compIt)
|
|
{
|
|
Component* comp= *compIt;
|
|
Counter::getRef("ComponentStatus" + CounterName[comp->message])++ ;
|
|
if(debugme)
|
|
comp->Print(cerr);
|
|
switch(comp->message)
|
|
{
|
|
case Component::NotChanged:
|
|
{
|
|
comp->ExtendedTillLastChange= false;
|
|
}break;
|
|
case Component::NewlyAdded:
|
|
{
|
|
set<int> compEdges;
|
|
comp->GetEdges(graph, compEdges);
|
|
CompressedMSet* newMSet= new CompressedMSet(0);
|
|
newMSet->AddUnit(compEdges, cur.starttime, cur.endtime, cur.lc, cur.rc);
|
|
ResultParts.push_back(newMSet);
|
|
comp->resultPartIndex= ResultParts.size() -1;
|
|
|
|
vector<int> res(1, comp->resultPartIndex);
|
|
ResultStream->push_back(res);
|
|
list< vector<int> >::iterator newResIt= --ResultStream->end();
|
|
comp->associatedResults.push_back(newResIt);
|
|
|
|
comp->ExtendedTillLastChange= true;
|
|
comp->Reset();
|
|
if(debugme)
|
|
{
|
|
list<vector<int> >::iterator associatedResultIt;
|
|
for(unsigned int associatedResultIndex=0; associatedResultIndex <
|
|
comp->associatedResults.size(); ++associatedResultIndex)
|
|
{
|
|
associatedResultIt= comp->associatedResults[associatedResultIndex];
|
|
vector<int> associatedResult= *associatedResultIt;
|
|
CompressedMSet* theMSet=
|
|
CollectResultParts(ResultParts, associatedResult);
|
|
theMSet->Print(cerr);
|
|
delete theMSet;
|
|
}
|
|
if(!IsOneComponent(newMSet, 0, edge2nodesMap))
|
|
cerr<<"Not One Component!!!!!!!!!!!!!!!!!!!!!";
|
|
}
|
|
}break;
|
|
case Component::AddedEdges:
|
|
case Component::RemovedEdges:
|
|
case Component::AddRemoveMix:
|
|
{
|
|
comp->ExtendResStreamsTillNow(ResultParts, cur.starttime, !cur.lc);
|
|
CompressedMSet* theMSet= ResultParts[comp->resultPartIndex];
|
|
theMSet->AddUnit(comp->addedEdges, comp->removedEdges, cur.starttime,
|
|
cur.endtime, cur.lc, cur.rc);
|
|
if(debugme)
|
|
if(!IsOneComponent(theMSet, 0, edge2nodesMap))
|
|
cerr<<"Not One Component!!!!!!!!!!!!!!!!!!!!!";
|
|
// remainingResStreams.remove(*res);
|
|
|
|
comp->ExtendedTillLastChange= true;
|
|
comp->Reset();
|
|
}break;
|
|
case Component::MergedFromExistingComponents:
|
|
{
|
|
/*
|
|
comp->ExtendResStreamsTillNow(ResultParts, cur.starttime, !cur.lc);
|
|
This was called within MergeComponents. The component now contains the merge
|
|
result, and not the merged components. ExtendResStreamsTillNow is applied to
|
|
the merged/small components, before they are deleted inside the MergeComponents
|
|
function.
|
|
|
|
*/
|
|
set<int> compEdges;
|
|
comp->SynchronizeNodes(graph);
|
|
comp->ExtendResStreamsTillNow(ResultParts, cur.starttime, !cur.lc);
|
|
comp->GetEdges(graph, compEdges);
|
|
CompressedMSet* newMSet= new CompressedMSet(0);
|
|
newMSet->AddUnit(compEdges, cur.starttime, cur.endtime, cur.lc, cur.rc);
|
|
ResultParts.push_back(newMSet);
|
|
comp->resultPartIndex= ResultParts.size() -1;
|
|
for(unsigned int associatedResultIndex=0; associatedResultIndex <
|
|
comp->associatedResults.size(); ++associatedResultIndex)
|
|
{
|
|
vector<int>* associatedResult=
|
|
&(*(comp->associatedResults[associatedResultIndex]));
|
|
associatedResult->push_back(ResultParts.size() -1);
|
|
if(debugme)
|
|
if(!IsOneComponent(newMSet, 0, edge2nodesMap))
|
|
cerr<<"Not One Component!!!!!!!!!!!!!!!!!!!!!";
|
|
// remainingResStreams.remove(*res);
|
|
}
|
|
comp->ExtendedTillLastChange= true;
|
|
comp->Reset();
|
|
}break;
|
|
case Component::SplitFromExtistingComponent:
|
|
{
|
|
comp->ExtendResStreamsTillNow(ResultParts, cur.starttime, !cur.lc);
|
|
vector<list< vector<int> >::iterator> resStreams;
|
|
set<int> compEdges;
|
|
comp->GetEdges(graph, compEdges);
|
|
CompressedMSet* newMSet= new CompressedMSet(0);
|
|
newMSet->AddUnit(compEdges, cur.starttime, cur.endtime, cur.lc, cur.rc);
|
|
ResultParts.push_back(newMSet);
|
|
comp->resultPartIndex= ResultParts.size() -1;
|
|
for(unsigned int associatedResultIndex=0; associatedResultIndex <
|
|
comp->associatedResults.size(); ++associatedResultIndex)
|
|
{
|
|
vector<int> associatedResult=
|
|
(*(comp->associatedResults[associatedResultIndex]));
|
|
vector<int> newResult(associatedResult);
|
|
newResult.push_back(ResultParts.size() -1);
|
|
ResultStream->push_back(newResult);
|
|
resStreams.push_back( --ResultStream->end());
|
|
if(find(resToErase.begin(), resToErase.end(),
|
|
comp->associatedResults[associatedResultIndex]) ==
|
|
resToErase.end())
|
|
resToErase.push_back(comp->associatedResults[associatedResultIndex]);
|
|
if(debugme)
|
|
if(!IsOneComponent(newMSet, 0, edge2nodesMap))
|
|
cerr<<"Not One Component!!!!!!!!!!!!!!!!!!!!!";
|
|
// remainingResStreams.remove(*res);
|
|
}
|
|
comp->associatedResults.clear();
|
|
comp->associatedResults.resize(resStreams.size());
|
|
copy(resStreams.begin(), resStreams.end(),
|
|
comp->associatedResults.begin());
|
|
comp->ExtendedTillLastChange= true;
|
|
comp->Reset();
|
|
}break;
|
|
case Component::RemoveNow:
|
|
{
|
|
comp->ExtendResStreamsTillNow(ResultParts, cur.starttime, !cur.lc);
|
|
for(unsigned int associatedResultIndex=0; associatedResultIndex <
|
|
comp->associatedResults.size(); ++associatedResultIndex)
|
|
{
|
|
vector<int>* associatedResult=
|
|
&(*(comp->associatedResults[associatedResultIndex]));
|
|
CompressedMSet* theMSet=
|
|
CollectResultParts(ResultParts, *associatedResult);
|
|
if(theMSet->DurationLength() >= dMS)
|
|
{
|
|
if(debugme)
|
|
{
|
|
cerr<<"Moving the following mset from resStream to finalResStream:";
|
|
theMSet->Print(cerr);
|
|
}
|
|
FinalResultStream->push_back(theMSet);
|
|
}
|
|
else
|
|
delete theMSet;
|
|
ResultStream->erase(comp->associatedResults[associatedResultIndex]);
|
|
// remainingResStreams.remove(*res);
|
|
}
|
|
delete comp;
|
|
compsToErase.push_back(compIt);
|
|
}break;
|
|
case Component::ReDistribute: //very unexpected case
|
|
{
|
|
bool NotYetImplemented= false;
|
|
assert(NotYetImplemented);
|
|
// comp->ExtendResStreamsTillNow(ResultParts, cur.starttime, !cur.lc);
|
|
// list< list<mset::CompressedMSet*>::iterator > resStreams;
|
|
// bool matched=false;
|
|
// set<int> compEdges;
|
|
// comp->GetEdges(graph, compEdges);
|
|
// for(list< list<mset::CompressedMSet*>::iterator >::iterator res=
|
|
// comp->resStreams.begin(); res!= comp->resStreams.end(); ++res)
|
|
// {
|
|
//
|
|
// CompressedMSet* theMSet= **res;
|
|
// set<int>* resFinalEdgeSet= theMSet->GetFinalSet(), resFinalNodeSet;
|
|
// EdgeSet2NodeSet(*resFinalEdgeSet, resFinalNodeSet, edge2nodesMap);
|
|
// if(debugme)
|
|
// {
|
|
// cerr<<endl;
|
|
// PrintSet(*resFinalEdgeSet, cerr);
|
|
// cerr<<endl;
|
|
// PrintSet(resFinalNodeSet, cerr);
|
|
// }
|
|
// if(SetIntersects(comp->nodes, resFinalNodeSet))
|
|
// {
|
|
// matched= true;
|
|
// CompressedMSet* newMSet= new CompressedMSet(*theMSet);
|
|
// newMSet->MergeAdd(compEdges, cur.starttime, cur.endtime,
|
|
// cur.lc, cur.rc);
|
|
// resStream->push_back(newMSet);
|
|
// list<CompressedMSet*>::iterator newMSetIt= --resStream->end();
|
|
// resStreams.push_back(newMSetIt);
|
|
// resToErase.push_back(*res);
|
|
// if(debugme)
|
|
// if(!IsOneComponent(newMSet, 0, edge2nodesMap))
|
|
// cerr<<"Not One Component!!!!!!!!!!!!!!!!!!!!!";
|
|
// // remainingResStreams.remove(*res);
|
|
// }
|
|
// }
|
|
//
|
|
// comp->resStreams.clear();
|
|
// comp->resStreams.resize(resStreams.size());
|
|
// copy(resStreams.begin(), resStreams.end(), comp->resStreams.begin());
|
|
// comp->ExtendedTillLastChange= true;
|
|
// comp->Reset();
|
|
//
|
|
// if(!matched) // a new component that is split from an existing component
|
|
// //this is an extremely unexpected case that should not happen under
|
|
// //normal moving objects scenarios
|
|
// {
|
|
// CompressedMSet* newMSet= new CompressedMSet(0);
|
|
// newMSet->AddUnit(compEdges, cur.starttime, cur.endtime, cur.lc, cur.rc);
|
|
// resStream->push_back(newMSet);
|
|
// list<CompressedMSet*>::iterator newMSetIt= --resStream->end();
|
|
// comp->resStreams.push_back(newMSetIt);
|
|
// comp->ExtendedTillLastChange= true;
|
|
// if(debugme)
|
|
// if(!IsOneComponent(newMSet, 0, edge2nodesMap))
|
|
// cerr<<"Not One Component!!!!!!!!!!!!!!!!!!!!!";
|
|
// }
|
|
}break;
|
|
default:
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
};
|
|
}
|
|
|
|
|
|
for(unsigned int i= 0; i< resToErase.size(); ++i)
|
|
ResultStream->erase(resToErase[i]);
|
|
resToErase.clear();
|
|
|
|
// assert(remainingResStreams.empty());
|
|
for(unsigned int i=0; i<compsToErase.size(); ++i)
|
|
components->erase(compsToErase[i]);
|
|
|
|
}
|
|
|
|
void GPatternHelper::DynamicGraphAppend(LWGraph* graph,
|
|
list<Component*>* components,
|
|
map<int, list<Component*>::iterator>& compLabelsMap,
|
|
list<CompressedInMemUSet>::iterator cur,
|
|
vector<pair<int, int> >& edge2nodesMap, int64_t dMS,
|
|
int n, string& qts, int& NextComponentLabel,
|
|
vector<CompressedMSet*>* ResultParts,
|
|
list<vector<int> >* ResultStream,
|
|
list<CompressedMSet*>*& FinalResultStream)
|
|
{
|
|
bool debugme= false;
|
|
|
|
if(debugme)
|
|
graph->print(cerr);
|
|
|
|
bool SingleUpdate= (((*cur).added.size() + (*cur).removed.size()) <= 1);
|
|
Counter::getRef("SingleGraphUpdate")+= SingleUpdate? 1: 0;
|
|
Counter::getRef("MultipleGraphUpdate")+= SingleUpdate? 0: 1;
|
|
|
|
if(!(*cur).added.empty())
|
|
{
|
|
vector<NewComponent> newComponents;
|
|
InsertEdgesUndirected(graph, (*cur).added, edge2nodesMap);
|
|
FindComponentsOf(
|
|
graph, components, (*cur).added, edge2nodesMap, newComponents);
|
|
|
|
for(vector<NewComponent>::iterator newComp=
|
|
newComponents.begin(); newComp!= newComponents.end(); ++newComp)
|
|
{
|
|
if(debugme)
|
|
(*newComp).Print(cerr);
|
|
if( (*newComp).affectedComponents.empty())
|
|
CheckAdd( graph, *newComp, n , components,
|
|
compLabelsMap, NextComponentLabel);
|
|
|
|
else if( (*newComp).affectedComponents.size() == 1)
|
|
UpdateMerge(graph, *newComp, (*cur).added, edge2nodesMap, components,
|
|
compLabelsMap);
|
|
//new edges/nodes are added to an existing component without causing a
|
|
//merge with other component. This causes no change.
|
|
|
|
else if( (*newComp).affectedComponents.size() > 1)
|
|
MergeComponents(graph, *newComp, components, compLabelsMap,
|
|
NextComponentLabel);
|
|
//the added edges caused some components to merge together.
|
|
//delete *newComp;
|
|
}
|
|
//delete newComponents;
|
|
}
|
|
|
|
if(!(*cur).removed.empty())
|
|
{
|
|
|
|
set<int> affectedComponentsLabels;
|
|
list<Component*>::iterator affectedComponentIt;
|
|
pair<int, int>* edgeNodes;
|
|
int componentLabel;
|
|
map<int, list<Component*>::iterator>::iterator affectedCompMap;
|
|
for(set<int>::iterator edgeIt= (*cur).removed.begin(); edgeIt!=
|
|
(*cur).removed.end(); ++edgeIt)
|
|
{
|
|
edgeNodes= &edge2nodesMap[*edgeIt];
|
|
if(debugme)
|
|
cerr<<"\n Removing edge ("<<edgeNodes->first <<", "<<edgeNodes->second
|
|
<<")";
|
|
componentLabel= FindEdgeComponent(graph, edgeNodes);
|
|
RemoveEdgeUndirected(graph, *edgeIt, edgeNodes);
|
|
if(componentLabel != -1)
|
|
{
|
|
affectedCompMap= compLabelsMap.find(componentLabel);
|
|
assertIf(affectedCompMap != compLabelsMap.end());
|
|
affectedComponentIt= (*affectedCompMap).second;
|
|
assertIf(affectedComponentIt != components->end());
|
|
affectedComponentsLabels.insert(componentLabel);
|
|
(*affectedComponentIt)->removedEdges.insert(*edgeIt);
|
|
assert((*affectedComponentIt)->UpdateMessage(Component::RemovedEdges));
|
|
}
|
|
}
|
|
|
|
if(!affectedComponentsLabels.empty())
|
|
UpdateRemove(graph, components, compLabelsMap, edge2nodesMap, n,
|
|
NextComponentLabel, affectedComponentsLabels);
|
|
}
|
|
|
|
Finalize(graph, components, dMS, *cur, *ResultParts, ResultStream,
|
|
FinalResultStream, edge2nodesMap);
|
|
|
|
}
|
|
|
|
void GPatternHelper::GraphNodes2Edges(set<int>& subGraphNodes,
|
|
set<int>& graphEdges,
|
|
vector<pair<int, int> >& edge2Nodes, set<int>& res)
|
|
{
|
|
res.clear();
|
|
pair<int, int> edge;
|
|
for(set<int>::iterator it= graphEdges.begin(); it!= graphEdges.end(); ++it)
|
|
{
|
|
edge= edge2Nodes[*it];
|
|
if(subGraphNodes.find(edge.first) != subGraphNodes.end() &&
|
|
subGraphNodes.find(edge.second) != subGraphNodes.end())
|
|
res.insert(*it);
|
|
}
|
|
|
|
}
|
|
|
|
bool GPatternHelper::Merge(CompressedInMemMSet *_mset, set<int> *subGraph,
|
|
int64_t starttime, int64_t endtime, bool lc, bool rc)
|
|
{
|
|
set<int>* finalSet= _mset->GetFinalSet();
|
|
bool intersects = SetIntersects(*finalSet, *subGraph);
|
|
if(intersects)
|
|
{
|
|
_mset->MergeAdd(*subGraph, starttime, endtime, lc, rc);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void GPatternHelper::SetAddRemove(
|
|
set<int>& _set, set<int>& _add, set<int>& _remove)
|
|
{
|
|
_set.insert(_add.begin(), _add.end());
|
|
for(set<int>::iterator it= _remove.begin(); it!= _remove.end(); ++it)
|
|
_set.erase(*it);
|
|
}
|
|
|
|
void GPatternHelper::EdgeSet2NodeSet(
|
|
set<int> &edges, set<int> &nodes, vector<pair<int, int> > edge2nodesMap)
|
|
{
|
|
pair<int, int> edge;
|
|
nodes.clear();
|
|
for(set<int>::iterator it= edges.begin(); it != edges.end(); ++it)
|
|
{
|
|
edge= edge2nodesMap[*it];
|
|
nodes.insert(edge.first);
|
|
nodes.insert(edge.second);
|
|
}
|
|
}
|
|
|
|
CompressedMSet* GPatternHelper::EdgeMSet2NodeMSet(
|
|
CompressedMSet* edgeMSet, vector<pair<int, int> >& edge2nodesMap)
|
|
{
|
|
//bool debugme= false;
|
|
LWGraph graph;
|
|
CompressedMSet* nodeMSet= new CompressedMSet(0);
|
|
CompressedUSetRef edgeUnit(true), nodeUnit(true);
|
|
set<int> newNodes, removedNodes, curNodeSet;
|
|
int count=0;
|
|
int numUnits= edgeMSet->GetNoComponents();
|
|
int elem;
|
|
if(edgeMSet == 0 || numUnits == 0) return nodeMSet;
|
|
|
|
set<int> toAdd, toRemove;
|
|
|
|
edgeMSet->units.Get( 0, edgeUnit );
|
|
for(int j=edgeUnit.addedstart; j<= edgeUnit.addedend; ++j)
|
|
{
|
|
edgeMSet->added.Get(j, elem);
|
|
toAdd.insert(elem);
|
|
}
|
|
InsertEdgesUndirected(&graph, toAdd, edge2nodesMap, newNodes);
|
|
nodeUnit.starttime= edgeUnit.starttime; nodeUnit.lc= edgeUnit.lc;
|
|
nodeUnit.addedstart=0; nodeUnit.removedstart=0;
|
|
count= newNodes.size();
|
|
for(set<int>::iterator it= newNodes.begin(); it!=newNodes.end(); ++it)
|
|
nodeMSet->added.Append(*it);
|
|
for(int i= 1; i< edgeMSet->units.Size(); ++i)
|
|
{
|
|
edgeMSet->units.Get( i, edgeUnit );
|
|
toAdd.clear(); toRemove.clear();
|
|
for(int j=edgeUnit.addedstart; j<= edgeUnit.addedend; ++j)
|
|
{
|
|
edgeMSet->added.Get(j, elem);
|
|
toAdd.insert(elem);
|
|
}
|
|
for(int j=edgeUnit.removedstart; j<= edgeUnit.removedend; ++j)
|
|
{
|
|
edgeMSet->removed.Get(j, elem);
|
|
toRemove.insert(elem);
|
|
}
|
|
InsertEdgesUndirected(&graph, toAdd, edge2nodesMap, newNodes);
|
|
RemoveEdgesUndirected(&graph, toRemove, edge2nodesMap, removedNodes);
|
|
|
|
if(! newNodes.empty() || ! removedNodes.empty())
|
|
{
|
|
nodeUnit.addedend= nodeMSet->added.Size()-1;
|
|
nodeUnit.removedend= nodeMSet->removed.Size()-1;
|
|
nodeUnit.endtime= edgeUnit.starttime;
|
|
nodeUnit.rc= ! edgeUnit.lc;
|
|
nodeUnit.count= count;
|
|
nodeMSet->units.Append(nodeUnit);
|
|
|
|
nodeUnit.starttime= edgeUnit.starttime; nodeUnit.lc= edgeUnit.lc;
|
|
nodeUnit.addedstart= nodeMSet->added.Size();
|
|
nodeUnit.removedstart= nodeMSet->removed.Size();
|
|
count+= newNodes.size() - removedNodes.size();
|
|
assertIf(count >= 0);
|
|
}
|
|
if(!newNodes.empty())
|
|
{
|
|
for(set<int>::iterator it= newNodes.begin(); it!=newNodes.end(); ++it)
|
|
nodeMSet->added.Append(*it);
|
|
}
|
|
if(!removedNodes.empty())
|
|
{
|
|
for(set<int>::iterator it= removedNodes.begin(); it!=
|
|
removedNodes.end(); ++it)
|
|
nodeMSet->removed.Append(*it);
|
|
}
|
|
}
|
|
|
|
nodeUnit.addedend= nodeMSet->added.Size()-1;
|
|
nodeUnit.removedend= nodeMSet->removed.Size()-1;
|
|
nodeUnit.endtime= edgeUnit.endtime;
|
|
nodeUnit.rc= edgeUnit.rc;
|
|
nodeUnit.count= count;
|
|
nodeMSet->units.Append(nodeUnit);
|
|
|
|
return nodeMSet;
|
|
}
|
|
|
|
void GPatternHelper::ComputeAddSubSets(InMemMSet& acc,
|
|
list<InMemUSet>::iterator t1, list<InMemUSet>::iterator t2,
|
|
unsigned int n, int64_t dMS, vector<InMemMSet*>* result)
|
|
{
|
|
bool debugme= false;
|
|
assert(acc.GetNoComponents() > 0 );
|
|
assert(dMS > 0);
|
|
assert(((*t2).endtime - (*t1).starttime) > dMS);
|
|
|
|
if(debugme)
|
|
{
|
|
cerr<<"\nComputeResultStreamPart Called: n= "<< n <<"---------------\n";
|
|
for(list<InMemUSet>::iterator t= t1; t!=t2; ++t)
|
|
(*t).Print(cerr);
|
|
(*t2).Print(cerr);
|
|
cerr<<"End of input -----------------------";
|
|
}
|
|
multimap< set<int>, Int64Interval> res;
|
|
|
|
list<InMemUSet>::iterator unitIterator1=t1, unitIterator2=t2;
|
|
int64_t startInstant= (*t1).starttime, curInstant=0,
|
|
endInstant= (*t2).endtime;
|
|
bool lc= (*t1).lc, rc=false;
|
|
list<InMemUSet>::iterator curUnit;
|
|
InMemUSet candidates;
|
|
curUnit= unitIterator1;
|
|
while( endInstant - startInstant >= dMS)
|
|
{
|
|
unitIterator2= unitIterator1;
|
|
curInstant= (*curUnit).endtime;
|
|
rc= (*curUnit).rc;
|
|
candidates.CopyFrom(*curUnit);
|
|
while( candidates.Count() >= n &&
|
|
curInstant - startInstant < dMS && unitIterator2 != t2)
|
|
{
|
|
curUnit = ++unitIterator2;
|
|
curInstant= (*curUnit).endtime;
|
|
rc= (*curUnit).rc;
|
|
candidates.Intersection((*curUnit).constValue);
|
|
}
|
|
if(candidates.Count() >= n && curInstant - startInstant >= dMS)
|
|
AddAllSubSetsToVector(candidates, startInstant, curInstant,
|
|
lc, rc, n, res);
|
|
|
|
while( curInstant < endInstant && candidates.Count() >=n &&
|
|
unitIterator2 != t2)
|
|
{
|
|
curUnit= ++unitIterator2;
|
|
curInstant= (*curUnit).endtime;
|
|
rc= (*curUnit).rc;
|
|
candidates.Intersection( (*curUnit).constValue);
|
|
if(candidates.Count() >= n )
|
|
AddAllSubSetsToVector(candidates, startInstant, curInstant,
|
|
lc, rc, n, res);
|
|
}
|
|
candidates.Clear();
|
|
if(unitIterator1 != t2)
|
|
{
|
|
curUnit= ++unitIterator1;
|
|
startInstant = (*curUnit).starttime;
|
|
lc= (*curUnit).lc;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
//result.reserve(res.size());
|
|
multimap< set<int>, Int64Interval>::iterator i;
|
|
for(i= res.begin(); i != res.end(); ++i)
|
|
{
|
|
InMemMSet* mset= new InMemMSet();
|
|
InMemUSet uset( (*i).first, (*i).second.start, (*i).second.end,
|
|
(*i).second.lc, (*i).second.rc);
|
|
mset->units.push_back(uset);
|
|
if(debugme)
|
|
{
|
|
cerr<<"Adding \n"; mset->Print(cerr);
|
|
}
|
|
result->push_back(mset);
|
|
}
|
|
if(debugme)
|
|
{
|
|
cerr<<result->size();
|
|
}
|
|
}
|
|
|
|
void GPatternHelper::GenerateAllCombinations(InMemUSet& cand, int select,
|
|
vector< set<int> > & res)
|
|
{
|
|
int *a = new int[select];
|
|
for (int k = 0; k < select; ++k) // initialize
|
|
a[k] = k + 1; // 1 - 2 - 3 - 4 - ...
|
|
|
|
vector<int> candidates(cand.constValue.begin(), cand.constValue.end());
|
|
int number= candidates.size();
|
|
while (true)
|
|
{
|
|
set<int> s;
|
|
for (int i = 0; i < select; ++i)
|
|
{
|
|
int index= a[i] -1;
|
|
s.insert(candidates[index]);
|
|
}
|
|
res.push_back(s);
|
|
// generate next combination in lexicographical order
|
|
int i = select - 1; // start at last item
|
|
// find next item to increment
|
|
while ( (i > -1) && (a[i] == (number - select + i + 1)))
|
|
--i;
|
|
|
|
if (i < 0) break; // all done
|
|
++a[i]; // increment
|
|
|
|
// do next
|
|
for (int j = i + 1; j < select; ++j)
|
|
a[j] = a[i] + j - i;
|
|
}
|
|
delete[] a;
|
|
}
|
|
|
|
void GPatternHelper::AddAllSubSetsToVector(InMemUSet& candidates,
|
|
int64_t startInstant,
|
|
int64_t curInstant, bool lc, bool rc,
|
|
int n, multimap< set<int>, Int64Interval>& res)
|
|
{
|
|
bool debugme= false;
|
|
bool changed=false;
|
|
vector< set<int> > sets(0);
|
|
if(debugme)
|
|
{
|
|
cerr<<"AddAllSubSetsToVector: recieved interval= ["<<startInstant
|
|
<<" "<<curInstant<<" "<<lc<<" "<<rc;
|
|
candidates.Print(cerr);
|
|
}
|
|
|
|
GenerateAllCombinations(candidates, n, sets);
|
|
changed = (sets.size() != 0);
|
|
|
|
if(changed)
|
|
{
|
|
pair<multimap< set<int>, Int64Interval>::iterator,
|
|
multimap< set<int>, Int64Interval>::iterator> ret;
|
|
multimap< set<int>, Int64Interval>::iterator i;
|
|
bool consumed= false;
|
|
Int64Interval timeInterval(startInstant, curInstant, lc, rc);
|
|
for(unsigned int k=0; k<sets.size(); ++k)
|
|
{
|
|
consumed= false;
|
|
ret = res.equal_range(sets[k]);
|
|
for (i=ret.first; i!=ret.second && !consumed; ++i)
|
|
{
|
|
if((*i).second.Inside(timeInterval))
|
|
{
|
|
(*i).second.Set(startInstant, curInstant, lc, rc);
|
|
consumed= true;
|
|
}
|
|
else if (timeInterval.Inside((*i).second))
|
|
consumed= true;
|
|
}
|
|
if(!consumed)
|
|
{
|
|
Int64Interval tmp(startInstant, curInstant, lc, rc);
|
|
res.insert( pair<set<int>, Int64Interval>(sets[k],tmp) );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
void ClearChangeRecord(ChangeRecord& rec)
|
|
{
|
|
rec.Clear();
|
|
}
|
|
bool GPatternHelper::ApplyThresholds(MSetIndex& index, int n, int64_t dMS,
|
|
vector<ChangeRecord>& AllChanges, bool debugme)
|
|
{
|
|
for_each(AllChanges.begin(), AllChanges.end(), ClearChangeRecord);
|
|
bool changed= true, globallyChanged= false;
|
|
if(debugme)
|
|
index.Print(cerr);
|
|
while(changed)
|
|
{
|
|
changed= index.RemoveShortNodeEntries(dMS, AllChanges);
|
|
globallyChanged |= changed;
|
|
changed= index.RemoveSmallUnits(n, AllChanges);
|
|
globallyChanged |= changed;
|
|
}
|
|
if(debugme)
|
|
{
|
|
index.Print(cerr);
|
|
cerr<<"The changes";
|
|
for(unsigned int i=0; i<AllChanges.size(); ++i)
|
|
{
|
|
cerr<<i<<"\t\t";
|
|
AllChanges[i].Print(cerr);
|
|
}
|
|
}
|
|
|
|
return globallyChanged;
|
|
}
|
|
|
|
|
|
void GPatternHelper::UpdateResult(CompressedInMemMSet* curMSet,
|
|
vector<pair<int,int> >& edge2nodesMap,int n, int64_t dMS, string qts,
|
|
vector<ChangeRecord>& Changes,
|
|
list<CompressedMSet*>& resStream, bool debugme)
|
|
{
|
|
/*
|
|
Find the ChangeRecoreds marked as UnitDeleted, and partition curMSet and Changes
|
|
accordingly.
|
|
Insert curMSet partitions into msetParts, and Changes partitions into
|
|
changesParts (two parallel arrays)
|
|
FOREACH msetPart in msetParts, and
|
|
FOREACH corresponding changesPart in changesParts
|
|
ApplyChanges(msetPart, changesPart, resStream, msetParts, changesParts)
|
|
|
|
*/
|
|
|
|
//bool debugme= false;
|
|
unsigned int offset=0, length=0, it=0;
|
|
list<CompressedInMemUSet>::iterator begin= curMSet->units.begin(),
|
|
usetIt= begin, end;
|
|
list<CompressedInMemMSet*> msetParts;
|
|
list<vector<ChangeRecord> > changeParts;
|
|
bool lastUnitIsDeleted=(Changes[0].status == ChangeRecord::UnitRemoved);
|
|
while(++it < Changes.size())
|
|
{
|
|
++usetIt;
|
|
if(lastUnitIsDeleted && Changes[it].status != ChangeRecord::UnitRemoved)
|
|
{
|
|
offset= it;
|
|
begin= usetIt;
|
|
}
|
|
else
|
|
if(!lastUnitIsDeleted && Changes[it].status == ChangeRecord::UnitRemoved)
|
|
{
|
|
length= it - offset;
|
|
end= usetIt;
|
|
CompressedInMemMSet* newMSetPart=
|
|
new CompressedInMemMSet(*curMSet, begin, end);
|
|
msetParts.push_back(newMSetPart);
|
|
changeParts.resize(changeParts.size()+1);
|
|
changeParts.back().insert(changeParts.back().end(),
|
|
Changes.begin() + offset, Changes.begin() + offset + length);
|
|
}
|
|
lastUnitIsDeleted= (Changes[it].status == ChangeRecord::UnitRemoved);
|
|
}
|
|
|
|
if(!lastUnitIsDeleted)
|
|
{
|
|
CompressedInMemMSet* newMSetPart= new CompressedInMemMSet(
|
|
*curMSet, begin, curMSet->units.end());
|
|
msetParts.push_back(newMSetPart);
|
|
|
|
changeParts.resize(changeParts.size()+1);
|
|
changeParts.back().insert(changeParts.back().end(),
|
|
Changes.begin() + offset, Changes.end());
|
|
}
|
|
|
|
assertIf(msetParts.size() == changeParts.size());
|
|
int cnt=0;
|
|
while(!msetParts.empty())
|
|
{
|
|
++cnt;
|
|
// if(debugme )
|
|
// {
|
|
// //MSet tmp(true);
|
|
// cerr<<"\nBefore Change: ";
|
|
// //msetParts.front()->WriteToMSet(tmp);
|
|
// //tmp.Print(cerr);
|
|
// //inMemMSet->Print(cerr);
|
|
// CompressedMSet tmp1(0);
|
|
// tmp1.ReadFromCompressedInMemMSet(*msetParts.front());
|
|
// CompressedMSet* tmp= EdgeMSet2NodeMSet(&tmp1, edge2nodesMap);
|
|
// CompressedInMemMSet tmp2;
|
|
// tmp->WriteToCompressedInMemMSet(tmp2);
|
|
// MSet tmp3(true);
|
|
// tmp2.WriteToMSet(tmp3);
|
|
// tmp3.Print(cerr);
|
|
// delete tmp;
|
|
// }
|
|
ApplyChanges(msetParts.front(), changeParts.front(), edge2nodesMap,
|
|
n, dMS, qts, resStream, msetParts, changeParts, false);
|
|
delete msetParts.front();
|
|
msetParts.pop_front();
|
|
changeParts.pop_front();
|
|
if(debugme && 0)
|
|
{
|
|
cerr<<"\nAfter Change: ";
|
|
list<CompressedMSet*>::iterator it= resStream.begin();
|
|
while(it != resStream.end())
|
|
{
|
|
(*it)->Print(cerr);
|
|
CompressedMSet* tmp= EdgeMSet2NodeMSet(*it, edge2nodesMap);
|
|
CompressedInMemMSet tmp1;
|
|
tmp->WriteToCompressedInMemMSet(tmp1);
|
|
MSet tmp2(true);
|
|
tmp1.WriteToMSet(tmp2);
|
|
tmp2.Print(cerr);
|
|
delete tmp;
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GPatternHelper::ApplyChanges(CompressedInMemMSet* inMemMSet,
|
|
vector<ChangeRecord>& changesPart,
|
|
vector<pair<int,int> >& edge2nodesMap,int n, int64_t dMS, string qts,
|
|
list<CompressedMSet*>& resStream, list<CompressedInMemMSet*>& msetParts,
|
|
list<vector<ChangeRecord> >& changeParts, bool debugme)
|
|
{
|
|
|
|
|
|
// localResStream: vector<CompressedMSet>
|
|
//
|
|
// FOREACH uset in msetPart and
|
|
// FOREACH corresponding changeRec in changesPart
|
|
// ASSERT(changeRec.status != UnitRemoved)
|
|
// IF changeRec.status == UnChanged continue
|
|
// ELSE IF changeRec.status == NodesRemoved
|
|
// Remove nodes from the uset
|
|
// changeRes.status= Unchanged
|
|
// IF uset has one large component continue
|
|
// ELSE IF uset has no large components
|
|
// resStream.pushback(msetPart[0..uset.index-1])
|
|
// msetParts.pushback(msetPart[uset.index+1..end])
|
|
// changesParts.pushback(changesParts[uset.index+1..end])
|
|
// RETURN
|
|
// ELSE IF uset has several large components
|
|
// FindDynamicComponents(msetPart,..., localResStream)
|
|
// resStream.splice(resStream.end(), localResStream)
|
|
// RETURN
|
|
// resStream.pushback(msetPart)
|
|
|
|
|
|
|
|
//bool debugme= false;
|
|
list<CompressedMSet*>* localResStream= 0;
|
|
CompressedInMemUSet* inMemUSet;
|
|
list<CompressedInMemUSet>::iterator usetIt= inMemMSet->units.begin();
|
|
vector<ChangeRecord>::iterator changeIt= changesPart.begin();
|
|
ChangeRecord* ch;
|
|
set<int> edges;
|
|
int noComponents;
|
|
bool changed=false;
|
|
while(changeIt!= changesPart.end())
|
|
{
|
|
ch= &(*changeIt);
|
|
assertIf(ch->status != ChangeRecord::UnitRemoved);
|
|
|
|
if(!ch->removedNodesInRemoved.empty())
|
|
{
|
|
inMemUSet= &(*usetIt);
|
|
changed= inMemUSet->EraseNodes(ch->removedNodesInRemoved, edge2nodesMap);
|
|
//assertIf(changed);
|
|
}
|
|
if(ch->status == ChangeRecord::NotChanged)
|
|
{
|
|
++changeIt; ++usetIt; continue;
|
|
}
|
|
else if (ch->status == ChangeRecord::ElemsRemoved)
|
|
{
|
|
inMemUSet= &(*usetIt);
|
|
changed= inMemUSet->EraseNodes(ch->removedNodes, edge2nodesMap);
|
|
ch->status= ChangeRecord::NotChanged;
|
|
if(!changed)
|
|
{
|
|
++changeIt; ++usetIt; continue;
|
|
}
|
|
inMemMSet->GetSet(usetIt, edges);
|
|
noComponents= GetNumComponents(edges, n, edge2nodesMap);
|
|
if(noComponents == 1)
|
|
{
|
|
++changeIt; ++usetIt; continue;
|
|
}
|
|
else if(noComponents == 0)
|
|
{
|
|
if(usetIt != inMemMSet->units.begin())
|
|
{
|
|
CompressedInMemMSet firstPart(
|
|
*inMemMSet, inMemMSet->units.begin(), usetIt);
|
|
firstPart.MakeMinimal();
|
|
CompressedMSet* resPart= new CompressedMSet(0);
|
|
resPart->ReadFromCompressedInMemMSet(firstPart);
|
|
resStream.push_back(resPart);
|
|
if(debugme && 0)
|
|
resStream.back()->Print(cerr);
|
|
}
|
|
list<CompressedInMemUSet>::iterator last= inMemMSet->units.end();
|
|
--last;
|
|
if(usetIt != last)
|
|
{
|
|
list<CompressedInMemUSet>::iterator it= usetIt; ++it;
|
|
CompressedInMemMSet* lastPart= new CompressedInMemMSet(*inMemMSet,
|
|
it, inMemMSet->units.end());
|
|
// if(debugme )
|
|
// {
|
|
// //MSet tmp(true);
|
|
// cerr<<"\nBefore Change: ";
|
|
// //msetParts.front()->WriteToMSet(tmp);
|
|
// //tmp.Print(cerr);
|
|
// //inMemMSet->Print(cerr);
|
|
// CompressedMSet tmp1(0);
|
|
// tmp1.ReadFromCompressedInMemMSet(*lastPart);
|
|
// CompressedMSet* tmp= EdgeMSet2NodeMSet(&tmp1, edge2nodesMap);
|
|
// CompressedInMemMSet tmp2;
|
|
// tmp->WriteToCompressedInMemMSet(tmp2);
|
|
// MSet tmp3(true);
|
|
// tmp2.WriteToMSet(tmp3);
|
|
// tmp3.Print(cerr);
|
|
// delete tmp;
|
|
// }
|
|
msetParts.push_back(lastPart);
|
|
vector<ChangeRecord> chPart(changeIt +1, changesPart.end());
|
|
changeParts.push_back(chPart);
|
|
}
|
|
return;
|
|
}
|
|
else if(noComponents > 1)
|
|
{
|
|
if(debugme)
|
|
{
|
|
inMemMSet->Print(cerr);
|
|
CompressedMSet tmp1(0);
|
|
tmp1.ReadFromCompressedInMemMSet(*inMemMSet);
|
|
CompressedMSet* tmp= EdgeMSet2NodeMSet(&tmp1, edge2nodesMap);
|
|
CompressedInMemMSet tmp2;
|
|
tmp->WriteToCompressedInMemMSet(tmp2);
|
|
MSet tmp3(true);
|
|
tmp2.WriteToMSet(tmp3);
|
|
tmp3.Print(cerr);
|
|
delete tmp;
|
|
}
|
|
inMemMSet->MakeMinimal();
|
|
FindDynamicComponents(*inMemMSet, inMemMSet->units.begin(),
|
|
inMemMSet->units.end(), edge2nodesMap, dMS, n, qts, localResStream);
|
|
resStream.splice(resStream.end(), *localResStream);
|
|
delete localResStream;
|
|
localResStream= 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
inMemMSet->MakeMinimal();
|
|
CompressedMSet* result= new CompressedMSet(0);
|
|
result->ReadFromCompressedInMemMSet(*inMemMSet);
|
|
resStream.push_back(result);
|
|
if(debugme)
|
|
resStream.back()->Print(cerr);
|
|
}
|
|
|
|
|
|
|
|
GPatternSolver GPSolver;
|
|
/*
|
|
3 Classes
|
|
|
|
*/
|
|
|
|
|
|
int GPatternSolver::PickVariable()
|
|
{
|
|
bool debugme=false;
|
|
vector<int> vars(0);
|
|
vector<double> numconstraints(0);
|
|
double cnt=0;
|
|
int index=-1;
|
|
for(unsigned int i=0;i<Agenda.size();i++)
|
|
{
|
|
if(Agenda[i] != 0)
|
|
{
|
|
vars.push_back(i);
|
|
cnt=0;
|
|
for(unsigned int r=0; r< ConstraintGraph.size(); r++)
|
|
{
|
|
for(unsigned int c=0; c< ConstraintGraph[r].size(); c++)
|
|
{
|
|
if( r == i && ConstraintGraph[r][c].size() != 0)
|
|
{
|
|
cnt+= ConstraintGraph[r][c].size() * 0.5;
|
|
for(unsigned int v=0; v< assignedVars.size(); v++)
|
|
{
|
|
if(c == (unsigned int)assignedVars[v])
|
|
cnt+=0.5 * ConstraintGraph[r][c].size();
|
|
}
|
|
|
|
}
|
|
|
|
if( c == i && ConstraintGraph[r][c].size() != 0)
|
|
{
|
|
cnt+=0.5 * ConstraintGraph[r][c].size();
|
|
for(unsigned int v=0; v< assignedVars.size(); v++)
|
|
{
|
|
if(r == (unsigned int)assignedVars[v])
|
|
cnt+=0.5 * ConstraintGraph[r][c].size();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
numconstraints.push_back(cnt);
|
|
}
|
|
}
|
|
double max=-1;
|
|
|
|
for(unsigned int i=0; i<numconstraints.size(); i++)
|
|
{
|
|
if(numconstraints[i]>max){ max=numconstraints[i]; index=vars[i];}
|
|
}
|
|
if(debugme)
|
|
{
|
|
for(unsigned int i=0; i<numconstraints.size(); i++)
|
|
cout<< "\nConnectivity of variable " <<vars[i] <<" = "
|
|
<< numconstraints[i];
|
|
cout<<endl<< "Picking variable "<< index<<endl;
|
|
cout.flush();
|
|
}
|
|
if(index== -1) return -1;
|
|
assignedVars.push_back(index);
|
|
return index;
|
|
}
|
|
|
|
bool GPatternSolver::MoveNext()
|
|
{
|
|
if(iterator < (signed int)SA.size()-1)
|
|
iterator++;
|
|
else
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool GPatternSolver::GetStart(string alias, Instant& result)
|
|
{
|
|
map<string, int>::iterator it;
|
|
|
|
it=VarAliasMap.find(alias);
|
|
if(it== VarAliasMap.end()) return false;
|
|
|
|
int index=(*it).second;
|
|
result.CopyFrom(&(SA[iterator][index].first.start));
|
|
return true;
|
|
}
|
|
|
|
bool GPatternSolver::GetEnd(string alias, Instant& result)
|
|
{
|
|
map<string, int>::iterator it;
|
|
|
|
it=VarAliasMap.find(alias);
|
|
if(it== VarAliasMap.end()) return false;
|
|
|
|
int index=(*it).second;
|
|
result.CopyFrom(&(SA[iterator][index].first.end));
|
|
return true;
|
|
}
|
|
|
|
ostream& GPatternSolver::Print(ostream &os)
|
|
{
|
|
os<< "\n==========================\nSA.size() = "<< SA.size()<< endl;
|
|
Instant tmp(instanttype);
|
|
for(unsigned int i=0; i< SA.size(); i++)
|
|
{
|
|
os<< "Tuple number:" << i;
|
|
for(unsigned int j=0; j<SA[i].size(); j++)
|
|
{
|
|
if(Agenda[j] !=0) continue;
|
|
os<< "Attribute number:" << j;
|
|
SA[i][j].second->Print(os);
|
|
// tmp.ReadFrom(SA[i][j].first.start.GetRealval());
|
|
// tmp.Print(os);
|
|
// os<< "\t ";
|
|
// tmp.ReadFrom(SA[i][j].first.end.GetRealval());
|
|
// tmp.Print(os);
|
|
// os<<"\t{";
|
|
// for(set<int>::iterator itr= SA[i][j].second.begin();
|
|
// itr!= SA[i][j].second.end(); ++itr)
|
|
// {
|
|
// os<< *itr << ", ";
|
|
// }
|
|
// os<<"} |";
|
|
}
|
|
os<<endl;
|
|
}
|
|
return os;
|
|
}
|
|
|
|
int GPatternSolver::Clear()
|
|
{
|
|
SA.clear();
|
|
Agenda.clear();
|
|
ConstraintGraph.clear();
|
|
VarAliasMap.clear();
|
|
assignedVars.clear();
|
|
count=0;
|
|
iterator=-1;
|
|
return 0;
|
|
}
|
|
|
|
void GPatternSolver::IntervalInstant2IntervalCcReal(
|
|
const Interval<Instant>& in, Interval<CcReal>& out)
|
|
{
|
|
bool debugme=false;
|
|
out.start.Set(in.start.IsDefined(), in.start.ToDouble());
|
|
out.end.Set(in.end.IsDefined(), in.end.ToDouble());
|
|
out.lc= in.lc;
|
|
out.rc= in.rc;
|
|
if(debugme)
|
|
{
|
|
in.Print(cerr);
|
|
out.Print(cerr);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
Extend
|
|
|
|
*/
|
|
|
|
bool GPatternSolver::Extend(int varIndex)
|
|
{
|
|
bool debugme= false;
|
|
vector< pair< Interval<Instant>, MSet* > > sa(count);
|
|
qp->Open(Agenda[varIndex]);
|
|
Interval<Instant> deftime;
|
|
Interval<Instant> period;
|
|
Periods periods(0);
|
|
set<int> val;
|
|
USetRef unit;
|
|
Word Value;
|
|
|
|
if(SA.size() == 0) //This is the first varirable to be evaluated
|
|
{
|
|
for(int i=0; i<count; i++)
|
|
sa[i].first.CopyFrom(nullInterval);
|
|
|
|
qp->Request(Agenda[varIndex], Value);
|
|
while(qp->Received(Agenda[varIndex]))
|
|
{
|
|
MSet* res = static_cast<MSet*>(Value.addr)->Clone();
|
|
ToDelete.push_back(res);
|
|
if(res->IsDefined())
|
|
{
|
|
if(debugme) res->Print(cerr);
|
|
res->DefTime(periods);
|
|
periods.Get(0, period);
|
|
sa[varIndex].first= period;
|
|
sa[varIndex].second= res;
|
|
SA.push_back(sa);
|
|
}
|
|
qp->Request(Agenda[varIndex], Value);
|
|
}
|
|
qp->Close(Agenda[varIndex]);
|
|
}
|
|
else
|
|
{
|
|
vector< pair< Interval<Instant>, MSet* > > stream;
|
|
pair< Interval<Instant>, MSet* > elem;
|
|
qp->Request(Agenda[varIndex], Value);
|
|
while(qp->Received(Agenda[varIndex]))
|
|
{
|
|
MSet* res = static_cast<MSet*>(Value.addr)->Clone() ;
|
|
ToDelete.push_back(res);
|
|
if(res->IsDefined())
|
|
{
|
|
res->DefTime(periods);
|
|
periods.Get(0, period);
|
|
elem.first= period;
|
|
elem.second= res;
|
|
stream.push_back(elem);
|
|
}
|
|
qp->Request(Agenda[varIndex], Value);
|
|
}
|
|
// SA has already entries
|
|
unsigned int SASize= SA.size();
|
|
for(unsigned int i=0; i<SASize; i++)
|
|
{
|
|
sa= SA[0];
|
|
|
|
for(unsigned int j=0; j<stream.size(); ++j)
|
|
{
|
|
sa[varIndex]= stream[j];
|
|
if(IsSupported(sa, varIndex))
|
|
SA.push_back(sa);
|
|
}
|
|
SA.erase(SA.begin());
|
|
}
|
|
}
|
|
if(debugme) Print(cerr);
|
|
return true;
|
|
}
|
|
|
|
bool GPatternSolver::IsSupported(
|
|
vector< pair<Interval<Instant>, MSet* > >& sa, int index)
|
|
{
|
|
bool supported=false;
|
|
for(unsigned int i=0; i<assignedVars.size()-1; i++)
|
|
{
|
|
for(unsigned int j=0; j<assignedVars.size(); j++)
|
|
{
|
|
if(i== (unsigned int)index || j == (unsigned int)index )
|
|
{
|
|
if(ConstraintGraph[assignedVars[i]][assignedVars[j]].size() != 0)
|
|
{
|
|
supported= CheckConstraint(sa[assignedVars[i]].first,
|
|
sa[assignedVars[j]].first,
|
|
ConstraintGraph[assignedVars[i]][assignedVars[j]]);
|
|
if(!supported) return false;
|
|
}
|
|
|
|
if(ConstraintGraph[assignedVars[j]][assignedVars[i]].size() != 0)
|
|
{
|
|
supported= CheckConstraint(sa[assignedVars[j]].first,
|
|
sa[assignedVars[i]].first,
|
|
ConstraintGraph[assignedVars[j]][assignedVars[i]]);
|
|
if(!supported) return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return supported;
|
|
}
|
|
|
|
/*
|
|
CheckCopnstraint
|
|
|
|
*/
|
|
|
|
bool GPatternSolver::CheckConstraint(Interval<Instant>& p1,
|
|
Interval<Instant>& p2, vector<Supplier> constraint)
|
|
{
|
|
bool debugme=false;
|
|
Word Value;
|
|
bool satisfied=false;
|
|
for(unsigned int i=0;i< constraint.size(); i++)
|
|
{
|
|
if(debugme)
|
|
{
|
|
cout<< "\nChecking constraint "<< qp->GetType(constraint[i])<<endl;
|
|
cout.flush();
|
|
}
|
|
qp->Request(constraint[i],Value);
|
|
STP::STVector* vec= (STP::STVector*) Value.addr;
|
|
satisfied= vec->ApplyVector(p1, p2);
|
|
if(!satisfied) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int GPatternSolver::AddConstraint(string alias1, string alias2, Supplier handle)
|
|
{
|
|
int index1=-1, index2=-1;
|
|
try{
|
|
index1= VarAliasMap[alias1];
|
|
index2= VarAliasMap[alias2];
|
|
if(index1==index2)
|
|
throw;
|
|
}
|
|
catch(...)
|
|
{
|
|
return -1;
|
|
}
|
|
ConstraintGraph[index1][index2].push_back(handle);
|
|
return 0;
|
|
}
|
|
|
|
int GPatternSolver::AddVariable(string alias, Supplier handle)
|
|
{
|
|
Agenda.push_back(handle);
|
|
VarAliasMap[alias]=count;
|
|
count++;
|
|
ConstraintGraph.resize(count);
|
|
for(int i=0; i<count; i++)
|
|
ConstraintGraph[i].resize(count);
|
|
return 0;
|
|
}
|
|
|
|
bool GPatternSolver::Solve()
|
|
{
|
|
int varIndex;
|
|
while( (varIndex= PickVariable()) != -1)
|
|
{
|
|
if(! Extend(varIndex)) return false;
|
|
if(SA.size() == 0) return false;
|
|
Agenda[varIndex]=0;
|
|
}
|
|
if(SA.size() == 0)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void GPatternSolver::WriteTuple(Tuple* tuple)
|
|
{
|
|
vector< pair< Interval<Instant>, MSet* > > sa= SA[iterator];
|
|
USet uset(true);
|
|
Instant instant(instanttype);
|
|
MSet mset(0);
|
|
for(unsigned int i=0; i<sa.size(); ++i)
|
|
{
|
|
// MSet* mset= new MSet(0);
|
|
// uset.constValue.Clear();
|
|
// instant.ReadFrom(sa[i].first.start.GetValue());
|
|
// uset.timeInterval.start= instant;
|
|
// instant.ReadFrom(sa[i].first.end.GetValue());
|
|
// uset.timeInterval.end= instant;
|
|
// uset.timeInterval.lc= sa[i].first.lc;
|
|
// uset.timeInterval.rc= sa[i].first.rc;
|
|
// for(set<int>::iterator it=sa[i].second.begin();
|
|
// it != sa[i].second.end(); ++it)
|
|
// uset.constValue.Insert(*it);
|
|
// uset.SetDefined(true);
|
|
// uset.constValue.SetDefined(true);
|
|
// assert(uset.IsValid());
|
|
// mset->Add(uset);
|
|
tuple->PutAttribute(i, sa[i].second->Clone());
|
|
}
|
|
}
|
|
|
|
/*
|
|
4 Algebra Types and Operators
|
|
|
|
*/
|
|
|
|
|
|
|
|
ListExpr CrossPatternTM(ListExpr args)
|
|
{
|
|
bool debugme= false;
|
|
bool error=false;
|
|
string argstr;
|
|
|
|
if(debugme)
|
|
{
|
|
cout<<endl<< nl->ToString(args)<<endl;
|
|
cout.flush();
|
|
}
|
|
|
|
nl->WriteToString(argstr, args);
|
|
if(nl->ListLength(args) != 7)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern expects 7 arguments \n but got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
ListExpr streamTuple = nl->First(args),
|
|
tupleIdent1= nl->Second(args),
|
|
tupleIdent2= nl->Third(args),
|
|
liftedPred = nl->Fourth(args),
|
|
duration = nl->Fifth(args),
|
|
count = nl->Sixth(args),
|
|
subGraph = nl->Nth(7,args),
|
|
tupleType=0;
|
|
|
|
nl->WriteToString(argstr, streamTuple);
|
|
if(listutils::isTupleStream(streamTuple))
|
|
{
|
|
tupleType = nl->Second(streamTuple);
|
|
if(!listutils::isTupleDescription(tupleType))
|
|
error= true;
|
|
}
|
|
else
|
|
error= true;
|
|
|
|
if(error)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern expects a stream(tuple) as the first "
|
|
"argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, tupleIdent1);
|
|
if(listutils::isMap<1>(tupleIdent1))
|
|
{
|
|
if(nl->Second(tupleIdent1) == tupleType)
|
|
{
|
|
if(!nl->Equal(nl->Third(tupleIdent1), nl->SymbolAtom(CcInt::BasicType())))
|
|
error= true;
|
|
}
|
|
else
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern: error in the tuple type passed to the map in "
|
|
"the second argument. It must be the same as the tuple type in the "
|
|
"stream(tuple) in the first arguement. "
|
|
"\nOperator crosspattern got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
}
|
|
else
|
|
error= true;
|
|
|
|
if(error)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern expects a (map tuple int) as a second "
|
|
"argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, tupleIdent2);
|
|
if(listutils::isMap<1>(tupleIdent2))
|
|
{
|
|
if(nl->Second(tupleIdent2) == tupleType)
|
|
{
|
|
if(!nl->Equal(nl->Third(tupleIdent2), nl->SymbolAtom(CcInt::BasicType())))
|
|
error= true;
|
|
}
|
|
else
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern: error in the tuple type passed to the map in "
|
|
"the third argument. It must be the same as the tuple type in the "
|
|
"stream(tuple) in the first arguement. "
|
|
"\nOperator crosspattern got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
}
|
|
else
|
|
error= true;
|
|
|
|
if(error)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern expects a (map tuple int) as a third "
|
|
"argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, liftedPred);
|
|
if(listutils::isMap<1>(liftedPred))
|
|
{
|
|
if(nl->Second(liftedPred) == tupleType)
|
|
{
|
|
if(!nl->Equal(nl->Third(liftedPred), nl->SymbolAtom(MBool::BasicType())))
|
|
error= true;
|
|
}
|
|
else
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern: error in the tuple type passed to the map in "
|
|
"the fourth argument. It must be the same as the tuple type in the "
|
|
"stream(tuple) in the first arguement. "
|
|
"\nOperator gpattern got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
}
|
|
else
|
|
error= true;
|
|
|
|
if(error)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern expects a (map tuple mbool) as the fourth "
|
|
"argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, duration);
|
|
if( !nl->IsAtom(duration) ||
|
|
nl->SymbolValue(duration) != Duration::BasicType())
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern expects a duration as the fifth argument. "
|
|
"\nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, count);
|
|
if( !nl->IsAtom(count) || nl->SymbolValue(count) != CcInt::BasicType())
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern expects an int as the sixth argument. "
|
|
"\nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, subGraph);
|
|
if( !nl->IsAtom(subGraph) )
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator crosspattern expects a subgraph name (...) as the "
|
|
"last argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr result =
|
|
nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom("mset"));
|
|
if(debugme)
|
|
{
|
|
cout<<endl<<endl<<"Operator gpattern accepted the input";
|
|
cout.flush();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
ListExpr GPatternTM(ListExpr args)
|
|
{
|
|
bool debugme= false;
|
|
bool error=false;
|
|
string argstr;
|
|
|
|
if(debugme)
|
|
{
|
|
cout<<endl<< nl->ToString(args)<<endl;
|
|
cout.flush();
|
|
}
|
|
|
|
nl->WriteToString(argstr, args);
|
|
if(nl->ListLength(args) != 6)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern expects 6 arguments \n but got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
ListExpr streamTuple = nl->First(args),
|
|
tupleIdent= nl->Second(args),
|
|
liftedPred = nl->Third(args),
|
|
duration = nl->Fourth(args),
|
|
count = nl->Fifth(args),
|
|
quantifier = nl->Sixth(args),
|
|
tupleType=0;
|
|
|
|
nl->WriteToString(argstr, streamTuple);
|
|
if(listutils::isTupleStream(streamTuple))
|
|
{
|
|
tupleType = nl->Second(streamTuple);
|
|
if(!listutils::isTupleDescription(tupleType))
|
|
error= true;
|
|
}
|
|
else
|
|
error= true;
|
|
|
|
if(error)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern expects a stream(tuple) as the first "
|
|
"argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, tupleIdent);
|
|
if(listutils::isMap<1>(tupleIdent))
|
|
{
|
|
if(nl->Second(tupleIdent) == tupleType)
|
|
{
|
|
if(!nl->Equal(nl->Third(tupleIdent), nl->SymbolAtom(CcInt::BasicType())))
|
|
error= true;
|
|
}
|
|
else
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern: error in the tuple type passed to the map in the "
|
|
"second argument. It must be the same as the tuple type in the "
|
|
"stream(tuple) in the first arguement. "
|
|
"\nOperator gpattern got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
}
|
|
else
|
|
error= true;
|
|
|
|
if(error)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern expects a (map tuple int) as a second "
|
|
"argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, liftedPred);
|
|
if(listutils::isMap<1>(liftedPred))
|
|
{
|
|
if(nl->Second(liftedPred) == tupleType)
|
|
{
|
|
if(!nl->Equal(nl->Third(liftedPred), nl->SymbolAtom(MBool::BasicType())))
|
|
error= true;
|
|
}
|
|
else
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern: error in the tuple type passed to the map in the "
|
|
"third argument. It must be the same as the tuple type in the "
|
|
"stream(tuple) in the first arguement. "
|
|
"\nOperator gpattern got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
}
|
|
else
|
|
error= true;
|
|
|
|
if(error)
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern expects a (map tuple mbool) as the third "
|
|
"argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, duration);
|
|
if( !nl->IsAtom(duration) ||
|
|
nl->SymbolValue(duration) != Duration::BasicType())
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern expects a duration as the fourth argument. "
|
|
"\nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, count);
|
|
if( !nl->IsAtom(count) || nl->SymbolValue(count) != CcInt::BasicType())
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern expects an int as the fifth argument. "
|
|
"\nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
//////////////////////////
|
|
nl->WriteToString(argstr, quantifier);
|
|
if( !nl->IsAtom(quantifier) ||
|
|
( nl->SymbolValue(quantifier) != "exactly" &&
|
|
nl->SymbolValue(quantifier) != "atleast"))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"Operator gpattern expects a quantifier (exactly or atleast) as the "
|
|
"last argument. \nBut got: " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr result =
|
|
nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom("mset"));
|
|
if(debugme)
|
|
{
|
|
cout<<endl<<endl<<"Operator gpattern accepted the input";
|
|
cout.flush();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
Type map ReportPattern
|
|
|
|
*/
|
|
|
|
ListExpr ReportPatternTM(ListExpr args)
|
|
{
|
|
bool debugme= false;
|
|
|
|
if(debugme)
|
|
{
|
|
cout<<endl<< nl->ToString(args)<<endl;
|
|
cout.flush();
|
|
}
|
|
if(!nl->HasLength(args,4)){
|
|
return listutils::typeError("4 arguments expected");
|
|
}
|
|
|
|
ListExpr streamExpr = nl->First(args), //stream(tuple(int, mx))
|
|
NamedPatternoidList = nl->Second(args), //named list of patternoids
|
|
ConstraintList = nl->Third(args), //TConstraint list
|
|
BoolCondition = nl->Fourth(args);
|
|
|
|
if(!Stream<Tuple>::checkType(streamExpr)){
|
|
return listutils::typeError("first argument must be a tuple stream");
|
|
}
|
|
ListExpr errorInfo;
|
|
ListExpr tuple = nl->Second(nl->Second(streamExpr));
|
|
if( !nl->HasLength(tuple,2)
|
|
|| !CcInt::checkType(nl->Second(nl->First(tuple)))
|
|
|| !am->CheckKind(Kind::TEMPORAL(),
|
|
nl->Second(nl->Second(tuple)),errorInfo)){
|
|
return listutils::typeError("first arg must be stream(tuple(int mx))");
|
|
}
|
|
|
|
if( nl->IsAtom(NamedPatternoidList)){
|
|
return listutils::typeError("second arg must be a list of "
|
|
"aliased patternoid");
|
|
}
|
|
|
|
ListExpr NamedPatternoidListRest = NamedPatternoidList;
|
|
ListExpr NamedPatternoid;
|
|
vector<ListExpr> aliases;
|
|
vector<ListExpr>::iterator it;
|
|
while( !nl->IsEmpty(NamedPatternoidListRest) )
|
|
{
|
|
NamedPatternoid = nl->First(NamedPatternoidListRest);
|
|
NamedPatternoidListRest = nl->Rest(NamedPatternoidListRest);
|
|
if( !nl->HasLength(NamedPatternoid,2)
|
|
|| !listutils::isSymbol(nl->First(NamedPatternoid))
|
|
|| !listutils::isMap<1>(nl->Second(NamedPatternoid))
|
|
|| !Stream<Attribute>::checkType(nl->Third(nl->Second(NamedPatternoid)))
|
|
|| !listutils::isSymbol(
|
|
(nl->Second(nl->Third(nl->Second(NamedPatternoid)))),"mset")){
|
|
return listutils::typeError("Invalid named Pattern" +
|
|
nl->ToString(NamedPatternoid));
|
|
}
|
|
aliases.push_back(nl->First(NamedPatternoid));
|
|
}
|
|
|
|
ListExpr ConstraintListRest = ConstraintList;
|
|
ListExpr STConstraint;
|
|
while( !nl->IsEmpty(ConstraintListRest) )
|
|
{
|
|
STConstraint = nl->First(ConstraintListRest);
|
|
ConstraintListRest = nl->Rest(ConstraintListRest);
|
|
if(!CcBool::checkType(STConstraint)){
|
|
return listutils::typeError("wrong temporal connector");
|
|
}
|
|
}
|
|
|
|
if(!CcBool::checkType(BoolCondition)){
|
|
return listutils::typeError("invalid boolean Condition");
|
|
}
|
|
|
|
it= aliases.begin();
|
|
ListExpr attr = nl->TwoElemList(*it, nl->SymbolAtom("mset"));
|
|
ListExpr attrList = nl->OneElemList(attr);
|
|
ListExpr lastlistn = attrList;
|
|
++it;
|
|
while (it != aliases.end())
|
|
{
|
|
attr = nl->TwoElemList(*it, nl->SymbolAtom("mset"));
|
|
lastlistn = nl->Append(lastlistn, attr);
|
|
++it;
|
|
}
|
|
|
|
ListExpr result =
|
|
nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
|
nl->TwoElemList(nl->SymbolAtom(Tuple::BasicType()), attrList));
|
|
if(debugme)
|
|
{
|
|
cout<<endl<<endl<<"Operator reportpattern accepted the input";
|
|
cout<< "return type is "<< nl->ToString(result);
|
|
cout.flush();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
ListExpr EmptyMSetTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if(!nl->IsEmpty(args)){
|
|
return listutils::typeError("no arguments expected");
|
|
}
|
|
ListExpr result = nl->SymbolAtom("mset");
|
|
return result;
|
|
}
|
|
|
|
ListExpr MBool2MSetTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if( !nl->HasLength(args,2)
|
|
|| !MBool::checkType(nl->First(args))
|
|
|| !CcInt::checkType(nl->Second(args))){
|
|
return listutils::typeError("expected mbool x int");
|
|
}
|
|
ListExpr result = nl->SymbolAtom("mset");
|
|
return result;
|
|
}
|
|
|
|
ListExpr UnionTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if(nl->ListLength(args) == 2 && nl->IsAtom(nl->First(args)) &&
|
|
nl->IsAtom(nl->Second(args)))
|
|
{
|
|
if(nl->IsEqual(nl->First(args), MSet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), MSet::BasicType()))
|
|
return nl->SymbolAtom(MSet::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), IntSet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), IntSet::BasicType()))
|
|
return nl->SymbolAtom(IntSet::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("Operator union expects (mset x mset) or "
|
|
"(intset x intset), but got " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr EqualsTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if(nl->ListLength(args) == 2 && nl->IsAtom(nl->First(args)) &&
|
|
nl->IsAtom(nl->Second(args)))
|
|
{
|
|
if(nl->IsEqual(nl->First(args), MSet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), MSet::BasicType()))
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), IntSet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), IntSet::BasicType()))
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("Operator = expects (mset x mset) or "
|
|
"(intset x intset), but got " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr DeftimeTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if(nl->ListLength(args) == 1 && nl->IsAtom(nl->First(args)))
|
|
{
|
|
if(nl->IsEqual(nl->First(args), MSet::BasicType()))
|
|
return nl->SymbolAtom(Periods::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), USet::BasicType()))
|
|
return nl->SymbolAtom(Periods::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("Operator = expects mset or uset, "
|
|
"but got " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr ComponentsTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if (nl->ListLength(args) != 1 ||
|
|
!nl->IsAtom(nl->First(args)) ||
|
|
!nl->IsEqual(nl->First(args), mset::IntSet::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError("Operator components expects (intset), but got "
|
|
+ argstr+ ".");
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
|
nl->SymbolAtom(CcInt::BasicType()));
|
|
|
|
}
|
|
|
|
ListExpr SmoothTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if (nl->ListLength(args) != 2 ||
|
|
!nl->IsAtom(nl->First(args)) ||
|
|
!nl->IsEqual(nl->First(args), MBool::BasicType()) ||
|
|
!nl->IsAtom(nl->Second(args)) ||
|
|
!nl->IsEqual(nl->Second(args), Duration::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError("Operator smooth expects (" +
|
|
MBool::BasicType() + " x " + Duration::BasicType()+ " ), but got "+
|
|
argstr+ ".");
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
return nl->SymbolAtom(MBool::BasicType());
|
|
|
|
}
|
|
|
|
ListExpr Union2MSetTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if( !nl->HasLength(args,2)
|
|
|| !listutils::isSymbol(nl->First(args),"mset")
|
|
|| !listutils::isSymbol(nl->Second(args),"mset")){
|
|
return listutils::typeError("mset x mset expected");
|
|
}
|
|
ListExpr result = nl->SymbolAtom("mset");
|
|
return result;
|
|
}
|
|
|
|
ListExpr IsSubsetTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if(nl->ListLength(args) == 2 && nl->IsAtom(nl->First(args)) &&
|
|
nl->IsAtom(nl->Second(args)))
|
|
{
|
|
if(nl->IsEqual(nl->First(args), MSet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), MSet::BasicType()))
|
|
return nl->SymbolAtom(MBool::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), USet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), USet::BasicType()))
|
|
return nl->SymbolAtom(MBool::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), IntSet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), IntSet::BasicType()))
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("Operator = expects (mset x mset), "
|
|
"(intset x intset), or (mset x mset), but got " + argstr + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
|
|
ListExpr UnitsTM( ListExpr args )
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if (nl->ListLength(args) != 1 ||
|
|
!nl->IsAtom(nl->First(args)) ||
|
|
!nl->IsEqual(nl->First(args), mset::MSet::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError("Operator units expects (mset), but got "+
|
|
argstr+ ".");
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
|
nl->SymbolAtom(mset::USet::BasicType()));
|
|
|
|
}
|
|
|
|
ListExpr InitFinTM( ListExpr args )
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if ( nl->ListLength( args ) == 1 )
|
|
{
|
|
ListExpr arg1 = nl->First( args );
|
|
|
|
if( nl->IsEqual( arg1, MSet::BasicType() ) )
|
|
return nl->SymbolAtom( ISet::BasicType() );
|
|
|
|
if( nl->IsEqual( arg1, USet::BasicType() ) )
|
|
return nl->SymbolAtom( ISet::BasicType() );
|
|
}
|
|
ErrorReporter::ReportError("Operator initial/final expects (mset) or (uset),"
|
|
" but got "+ argstr+ ".");
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
ListExpr CardinalityTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
|
|
if(nl->ListLength(args)==1 && nl->IsAtom(nl->First(args)))
|
|
{
|
|
if(nl->IsEqual(nl->First(args), MSet::BasicType()))
|
|
return nl->SymbolAtom(MInt::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), USet::BasicType()))
|
|
return nl->SymbolAtom(CcInt::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), ISet::BasicType()))
|
|
return nl->SymbolAtom(CcInt::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), IntSet::BasicType()))
|
|
return nl->SymbolAtom(CcInt::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("Operator cardinality expects any of {" +
|
|
MSet::BasicType()+ ", "+ USet::BasicType() + ", " + ISet::BasicType() +
|
|
", "+ IntSet::BasicType() + "}\nbut got: " + argstr);
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr MinusTM(ListExpr args)
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
|
|
if(nl->ListLength(args)==2 && nl->IsAtom(nl->First(args)) &&
|
|
nl->IsAtom(nl->Second(args)))
|
|
{
|
|
if(nl->IsEqual(nl->First(args), MSet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), MSet::BasicType()))
|
|
return nl->SymbolAtom(MSet::BasicType());
|
|
else if(nl->IsEqual(nl->First(args), IntSet::BasicType()) &&
|
|
nl->IsEqual(nl->Second(args), IntSet::BasicType()))
|
|
return nl->SymbolAtom(IntSet::BasicType());
|
|
}
|
|
ErrorReporter::ReportError("Operator cardinality expects any of {" +
|
|
MSet::BasicType()+ ", "+ USet::BasicType() + ", " + ISet::BasicType() +
|
|
", "+ IntSet::BasicType() + "}\nbut got: " + argstr);
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr ValTM( ListExpr args )
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if ( nl->ListLength( args ) == 1 )
|
|
{
|
|
ListExpr arg1 = nl->First( args );
|
|
|
|
if( nl->IsEqual( arg1, ISet::BasicType() ) )
|
|
return nl->SymbolAtom( IntSet::BasicType() );
|
|
}
|
|
ErrorReporter::ReportError("Operator val expects (iset), but got "+
|
|
argstr+ ".");
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
ListExpr InstTM( ListExpr args )
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if ( nl->ListLength( args ) == 1 )
|
|
{
|
|
ListExpr arg1 = nl->First( args );
|
|
|
|
if( nl->IsEqual( arg1, ISet::BasicType() ))
|
|
return nl->SymbolAtom( Instant::BasicType() );
|
|
}
|
|
ErrorReporter::ReportError("Operator inst expects (iset), but got "+
|
|
argstr+ ".");
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
/*
|
|
TConstraint
|
|
|
|
*/
|
|
|
|
//operators
|
|
template <int Alfa>
|
|
ListExpr CreateAlfaSetTM(ListExpr args)
|
|
{
|
|
bool debugme= false;
|
|
//type names according to secondo type mapping
|
|
string thetypes[]={CcInt::BasicType(), CcReal::BasicType(),
|
|
CcString::BasicType(), CcBool::BasicType()};
|
|
string alfa(thetypes[Alfa]);
|
|
string argstr;
|
|
|
|
if(debugme)
|
|
{
|
|
cout<<endl<< nl->ToString(args)<<endl;
|
|
cout.flush();
|
|
}
|
|
|
|
if(!nl->HasLength(args,2)){
|
|
return listutils::typeError("2 arguments expected");
|
|
}
|
|
|
|
ListExpr streamExpr = nl->First(args); //stream(tuple(X))
|
|
if(!Stream<Tuple>::checkType(streamExpr)) {
|
|
return listutils::typeError("first argument is not a tuple stream");
|
|
}
|
|
|
|
if(!listutils::isSymbol(nl->Second(args))){
|
|
return listutils::typeError("second argument is not a "
|
|
"valid attribute name");
|
|
}
|
|
|
|
ListExpr attrType;
|
|
string attrName = nl->SymbolValue(nl->Second(args));
|
|
int attrIndex=
|
|
listutils::findAttribute(nl->Second(nl->Second(streamExpr)),
|
|
attrName, attrType);
|
|
|
|
if(!attrIndex){
|
|
return listutils::typeError("Attribute " + attrName + " not found");
|
|
}
|
|
|
|
if(!nl->IsEqual(attrType,alfa)){
|
|
return listutils::typeError("Attribute " + attrName + " is of type "
|
|
+ nl->ToString(attrType) + " but should be of type "
|
|
+ alfa);
|
|
}
|
|
|
|
ListExpr res= nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
|
nl->TwoElemList(nl->IntAtom(attrIndex), attrType),
|
|
nl->SymbolAtom("intset"));
|
|
if(debugme)
|
|
{
|
|
cout<<endl<<endl<<"Operator create" + alfa + "set accepted the input";
|
|
cout.flush();
|
|
}
|
|
return res;
|
|
}
|
|
|
|
ListExpr BoundingRegionTM(ListExpr args)
|
|
{
|
|
string msg= nl->ToString(args);
|
|
if(nl->ListLength(args) < 2)
|
|
{
|
|
ErrorReporter::ReportError("Operator boundingregion expects atleast 2 "
|
|
"arguments.\nBut got: " + msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
};
|
|
|
|
ListExpr muiset= nl->Second(args);
|
|
msg= nl->ToString(muiset);
|
|
if(!nl->IsAtom(muiset))
|
|
{
|
|
ErrorReporter::ReportError("Operator boundingregion expects any of {"
|
|
+ MSet::BasicType() + "," + USet::BasicType() + "," + ISet::BasicType()
|
|
+ "} as second argument.\nBut got: " + msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr stream= nl->First(args);
|
|
msg= nl->ToString(stream);
|
|
if(!listutils::isTupleStream(stream))
|
|
{
|
|
ErrorReporter::ReportError("Operator boundingregion expects "
|
|
"stream(tuple(" + CcInt::BasicType() +"," + MPoint::BasicType() +
|
|
")) as first argument.\nBut got: " + msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
};
|
|
ListExpr tuple = nl->Second(nl->Second(stream));
|
|
msg= nl->ToString(tuple);
|
|
if(nl->ListLength(tuple) != 2 ||
|
|
!nl->IsAtom(nl->Second(nl->First(tuple))) ||
|
|
nl->SymbolValue(nl->Second(nl->First (tuple)))!= CcInt::BasicType() ||
|
|
!nl->IsAtom(nl->Second(nl->Second(tuple))) ||
|
|
nl->SymbolValue(nl->Second(nl->Second(tuple)))!= MPoint::BasicType())
|
|
{
|
|
ErrorReporter::ReportError("Operator boundingregion expects "
|
|
"stream(tuple(" + CcInt::BasicType() +"," + MPoint::BasicType() +
|
|
")) as first argument.\nBut got: stream(tuple(" + msg + ")).");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
};
|
|
|
|
if(nl->IsEqual(muiset, MSet::BasicType()) ||
|
|
nl->IsEqual(muiset, USet::BasicType()))
|
|
{
|
|
ListExpr duration= nl->Third(args);
|
|
msg= nl->ToString(duration);
|
|
if(!nl->IsAtom(duration)|| !nl->IsEqual(duration, Duration::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError("Operator boundingregion expects "
|
|
+ Duration::BasicType() + " as third argument.\nBut got: " +
|
|
msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
};
|
|
return nl->SymbolAtom(MRegion::BasicType());
|
|
}
|
|
else if(nl->IsEqual(muiset, ISet::BasicType()))
|
|
{
|
|
return nl->SymbolAtom(Region::BasicType());
|
|
}
|
|
|
|
ErrorReporter::ReportError("Operator boundingregion expects any of {"
|
|
+ MSet::BasicType() + "," + USet::BasicType() + "," + ISet::BasicType()
|
|
+ "} as second argument.\nBut got: " + msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr ConvexHullTM(ListExpr args)
|
|
{
|
|
if(!nl->HasLength(args,2)){
|
|
return listutils::typeError("expected 2 arguments");
|
|
}
|
|
if(!Stream<MPoint>::checkType(nl->First(args))){
|
|
return listutils::typeError("first argument must be of "
|
|
"type stream(mpoint)");
|
|
}
|
|
|
|
if(!Instant::checkType(nl->Second(args))){
|
|
return listutils::typeError("expected instant as second argument");
|
|
}
|
|
return nl->SymbolAtom(Region::BasicType());
|
|
}
|
|
|
|
ListExpr MembersTM(ListExpr args)
|
|
{
|
|
string msg= nl->ToString(args);
|
|
if(nl->ListLength(args) != 3)
|
|
{
|
|
ErrorReporter::ReportError("Operator members expects 3 "
|
|
"arguments.\nBut got: " + msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
};
|
|
|
|
ListExpr muiset= nl->Second(args);
|
|
msg= nl->ToString(muiset);
|
|
if(!nl->IsAtom(muiset))
|
|
{
|
|
ErrorReporter::ReportError("Operator members expects any of {"
|
|
+ MSet::BasicType() + "," + USet::BasicType() + "," + ISet::BasicType()
|
|
+ "} as second argument.\nBut got: " + msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
ListExpr stream= nl->First(args);
|
|
msg= nl->ToString(stream);
|
|
if(!listutils::isTupleStream(stream))
|
|
{
|
|
ErrorReporter::ReportError("Operator members expects "
|
|
"stream(tuple(" + CcInt::BasicType() +"," + MPoint::BasicType() +
|
|
")) as first argument.\nBut got: " + msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
};
|
|
ListExpr tuple = nl->Second(nl->Second(stream));
|
|
msg= nl->ToString(tuple);
|
|
if(nl->ListLength(tuple) != 2 ||
|
|
!nl->IsAtom(nl->Second(nl->First (tuple))) ||
|
|
nl->SymbolValue(nl->Second(nl->First (tuple)))!= CcInt::BasicType() ||
|
|
!nl->IsAtom(nl->Second(nl->Second(tuple))) ||
|
|
nl->SymbolValue(nl->Second(nl->Second(tuple)))!= MPoint::BasicType())
|
|
{
|
|
ErrorReporter::ReportError("Operator members expects "
|
|
"stream(tuple(" + CcInt::BasicType() +"," + MPoint::BasicType() +
|
|
")) as first argument.\nBut got: stream(tuple(" + msg + ")).");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
};
|
|
|
|
if(nl->IsEqual(muiset, MSet::BasicType()) ||
|
|
nl->IsEqual(muiset, USet::BasicType()))
|
|
{
|
|
ListExpr restrictTraj= nl->Third(args);
|
|
msg= nl->ToString(restrictTraj);
|
|
if(!nl->IsAtom(restrictTraj)||
|
|
!nl->IsEqual(restrictTraj, CcBool::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError("Operator members expects "
|
|
+ CcBool::BasicType() + " as third argument.\nBut got: " +
|
|
msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
};
|
|
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
|
nl->SymbolAtom(MPoint::BasicType()));
|
|
}
|
|
else if(nl->IsEqual(muiset, ISet::BasicType()))
|
|
{
|
|
return nl->SymbolAtom(Points::BasicType());
|
|
}
|
|
|
|
ErrorReporter::ReportError("Operator members expects any of {"
|
|
+ MSet::BasicType() + "," + USet::BasicType() + "," + ISet::BasicType()
|
|
+ "} as second argument.\nBut got: " + msg + ".");
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
|
|
ListExpr
|
|
IntersectsTM( ListExpr args )
|
|
{
|
|
string argstr;
|
|
if ( nl->ListLength( args ) == 2 )
|
|
{
|
|
ListExpr arg1 = nl->First( args ), //first argument
|
|
arg2 = nl->Second( args );//second argument
|
|
if(nl->IsEqual( arg1, "intset" ) && nl->IsEqual( arg2, "intset" ))
|
|
return nl->SymbolAtom( CcBool::BasicType() );
|
|
}
|
|
nl->WriteToString(argstr, args);
|
|
ErrorReporter::ReportError("typemap error in operator intersects. "
|
|
"Operator received: " + argstr);
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
ListExpr TheUnitTM( ListExpr args )
|
|
{
|
|
string argstr;
|
|
nl->WriteToString(argstr, args);
|
|
if (argstr == "(intset instant instant bool bool)")
|
|
return nl->SymbolAtom( "uset" );
|
|
ErrorReporter::ReportError
|
|
("Operator 'the_unit' expects a list with structure\n"
|
|
"'(intset instant instant bool bool)'"
|
|
", but it gets a list of type \n'" + argstr + "'.");
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
|
|
ListExpr TheMValueTM( ListExpr args )
|
|
{
|
|
string argstr;
|
|
|
|
// quick check for signature (stream uT) --> mT
|
|
nl->WriteToString(argstr, args);
|
|
if ( argstr == "((stream uset))" ) return nl->SymbolAtom( "mset" );
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
ListExpr CollectIntSetTypeMap(ListExpr args) {
|
|
string operatorName;
|
|
string resultType;
|
|
|
|
const string errMsg = "Operator " + operatorName
|
|
+ " expects (stream int)";
|
|
ListExpr argStream;
|
|
ListExpr argType;
|
|
|
|
if ( nl->ListLength(args) == 1 )
|
|
{
|
|
argStream = nl->First(args);
|
|
|
|
if ( !nl->IsAtom(argStream) && nl->ListLength(argStream) == 2)
|
|
{
|
|
argType = nl->Second(argStream);
|
|
if ( nl->IsEqual(nl->First(argStream), Symbol::STREAM())
|
|
&& nl->IsEqual(argType, CcInt::BasicType()))
|
|
return nl->SymbolAtom("intset");
|
|
}
|
|
}
|
|
ErrorReporter::ReportError(errMsg);
|
|
return nl->TypeError();
|
|
}
|
|
|
|
ListExpr
|
|
NoComponentsTM( ListExpr args )
|
|
{
|
|
if ( nl->ListLength( args ) == 1 )
|
|
{
|
|
ListExpr arg1 = nl->First( args );
|
|
|
|
if( nl->IsEqual( arg1, "mset" ))
|
|
return nl->SymbolAtom( CcInt::BasicType() );
|
|
}
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
|
|
ListExpr GBoidsTM( ListExpr args )
|
|
{
|
|
string errMsg= "";
|
|
if ( nl->ListLength( args ) != 4 )
|
|
{
|
|
errMsg= "generateboids expects 4 arguments, but got:"
|
|
+ nl->ToString(args);
|
|
ErrorReporter::ReportError(errMsg);
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
ListExpr BoidSizes = nl->First(nl->First( args )),
|
|
Obstacles= nl->First(nl->Second( args )),
|
|
ObstaclesExpr= nl->Second(nl->Second( args )),
|
|
SimulationStartTime= nl->First(nl->Third( args )),
|
|
SimulationDuration= nl->First(nl->Fourth( args ));
|
|
|
|
ListExpr expected= nl->TwoElemList(nl->SymbolAtom(Vector::BasicType()),
|
|
nl->SymbolAtom(CcInt::BasicType()));
|
|
if(!nl->Equal(BoidSizes, expected))
|
|
{
|
|
errMsg= " generateboids expects "+ Vector::BasicType() +
|
|
nl->ToString(expected) +
|
|
" as first argument, but got:" + nl->ToString(BoidSizes);
|
|
ErrorReporter::ReportError(errMsg);
|
|
return nl->SymbolAtom( Symbol::TYPEERROR());
|
|
}
|
|
|
|
expected= nl->TwoElemList(nl->SymbolAtom(Vector::BasicType()),
|
|
nl->SymbolAtom(CcReal::BasicType()) );
|
|
if(! nl->Equal(Obstacles, expected))
|
|
{
|
|
errMsg= " generateboids expects "+
|
|
nl->ToString(expected) +
|
|
" as second argument, but got:" + nl->ToString(BoidSizes);
|
|
ErrorReporter::ReportError(errMsg);
|
|
return nl->SymbolAtom( Symbol::TYPEERROR());
|
|
}
|
|
|
|
if( nl->IsAtom(ObstaclesExpr) ||
|
|
nl->ListLength(ObstaclesExpr) < 4 ||
|
|
((nl->ListLength(ObstaclesExpr) - 1) % 3) != 0)
|
|
{
|
|
errMsg= " generateboids expects as a second argument "
|
|
"a vector of obstacles (circles) in the "
|
|
"format x1, y1, r1, ..., xn, yn, rn, where (xk, yk) are the center of "
|
|
"an obstacle, and rk is its radius in meters. There must be at least "
|
|
"one obstacle representing the world boundaries. "
|
|
"The operator got:" + nl->ToString(ObstaclesExpr);
|
|
ErrorReporter::ReportError(errMsg);
|
|
return nl->SymbolAtom( Symbol::TYPEERROR());
|
|
}
|
|
|
|
if(! nl->IsEqual( SimulationStartTime, DateTime::BasicType()))
|
|
{
|
|
errMsg= " generateboids expects "+ DateTime::BasicType() +
|
|
" as third argument, but got:" + nl->ToString(args);
|
|
ErrorReporter::ReportError(errMsg);
|
|
return nl->SymbolAtom( Symbol::TYPEERROR());
|
|
}
|
|
|
|
if(! nl->IsEqual( SimulationDuration, Duration::BasicType()))
|
|
{
|
|
errMsg= " generateboids expects " + Duration::BasicType() + ""
|
|
" as fourth argument, but got:" + nl->ToString(args);
|
|
ErrorReporter::ReportError(errMsg);
|
|
return nl->SymbolAtom( Symbol::TYPEERROR());
|
|
}
|
|
|
|
NList resTupleType =
|
|
NList(NList("BoidID"), NList(CcInt::BasicType())).enclose();
|
|
resTupleType.append(NList(NList("T"),NList(Instant::BasicType())));
|
|
resTupleType.append(NList(NList("X"),NList(CcReal::BasicType())));
|
|
resTupleType.append(NList(NList("Y"),NList(CcReal::BasicType())));
|
|
NList resType =
|
|
NList(NList(Symbol::STREAM()),
|
|
NList(NList(Tuple::BasicType()),resTupleType));
|
|
|
|
return resType.listExpr();
|
|
}
|
|
/*
|
|
Value map ReportPattern
|
|
|
|
*/
|
|
|
|
int
|
|
ReportPatternVM(Word* args, Word& result,int message, Word& local, Supplier s)
|
|
{
|
|
bool debugme=false;
|
|
if(debugme)
|
|
{
|
|
cout<<" Inside ReportPatternVM\n";
|
|
cout<<" Message = " <<message<<endl;
|
|
// qp->ListOfTree(s, cout);
|
|
cout.flush();
|
|
}
|
|
|
|
switch( message )
|
|
{
|
|
case OPEN: // Construct and Solve the CSP, then store it in the "local"
|
|
{
|
|
Supplier stream, namedpatternoidlist, namedpatternoid,alias, patternoid,
|
|
constraintlist, constraint, alias1, alias2, tvector;
|
|
Word Value;
|
|
string aliasstr, alias1str, alias2str;
|
|
int noofpatternoids, noofconstraints;
|
|
|
|
stream = args[0].addr;
|
|
namedpatternoidlist = args[1].addr;
|
|
constraintlist= args[2].addr;
|
|
//filter= args[3].addr;
|
|
|
|
noofpatternoids= qp->GetNoSons(namedpatternoidlist);
|
|
noofconstraints= qp->GetNoSons(constraintlist);
|
|
|
|
GPSolver.Clear();
|
|
GPSolver.TheStream= stream;
|
|
for(int i=0; i< noofpatternoids; i++)
|
|
{
|
|
namedpatternoid= qp->GetSupplierSon(namedpatternoidlist, i);
|
|
alias= qp->GetSupplierSon(namedpatternoid, 0);
|
|
patternoid = qp->GetSupplierSon(namedpatternoid, 1);
|
|
aliasstr= nl->ToString(qp->GetType(alias));
|
|
GPSolver.AddVariable(aliasstr,patternoid);
|
|
}
|
|
|
|
for(int i=0; i< noofconstraints; i++)
|
|
{
|
|
constraint = qp->GetSupplierSon(constraintlist, i);
|
|
alias1= qp->GetSupplierSon(constraint, 0);
|
|
alias2= qp->GetSupplierSon(constraint, 1);
|
|
tvector= qp->GetSupplierSon(constraint, 2);
|
|
|
|
qp->Request(alias1, Value);
|
|
alias1str= ((CcString*) Value.addr)->GetValue();
|
|
qp->Request(alias2, Value);
|
|
alias2str= ((CcString*) Value.addr)->GetValue();
|
|
GPSolver.AddConstraint(alias1str,alias2str, tvector);
|
|
}
|
|
|
|
GPSolver.Solve();
|
|
return 0;
|
|
}
|
|
case REQUEST: { // return the next stream element
|
|
bool Part2=false;
|
|
Supplier filter= args[3].addr;
|
|
Word Value;
|
|
while(!Part2 && GPSolver.MoveNext())
|
|
{
|
|
qp->Request(filter, Value);
|
|
Part2= ((CcBool*)Value.addr)->GetValue();
|
|
}
|
|
if(Part2)
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
Tuple* tuple=
|
|
new Tuple(static_cast<Tuple*>(result.addr)->GetTupleType() );
|
|
GPSolver.WriteTuple(tuple);
|
|
result.setAddr(tuple);
|
|
return YIELD;
|
|
}
|
|
result.addr = 0;
|
|
return CANCEL;
|
|
}
|
|
case CLOSE: { // free the local storage
|
|
|
|
GPSolver.Clear();
|
|
local.addr = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int GPatternVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
bool debugme= false;
|
|
switch( message )
|
|
{
|
|
case OPEN:
|
|
{
|
|
/*
|
|
Defining local variables
|
|
|
|
*/
|
|
Word t, value;
|
|
Tuple* tup;
|
|
MBool* mbool;
|
|
int id;
|
|
CompressedInMemMSet accumlator;
|
|
vector<InMemMSet*>* resStream = new vector<InMemMSet*>();
|
|
GPatternHelper GPHelper;
|
|
|
|
/*
|
|
Reading the operator arguments
|
|
|
|
*/
|
|
Supplier TheStream= args[0].addr,
|
|
tupleID= args[1].addr,
|
|
liftedPred = args[2].addr;
|
|
ArgVectorPointer tupleIDArgs = qp->Argument(tupleID),
|
|
liftedPredArgs = qp->Argument(liftedPred);
|
|
qp->Request(args[3].addr, value);
|
|
int64_t dMS= static_cast<Instant*>(value.addr)->millisecondsToNull();
|
|
qp->Request(args[4].addr, value);
|
|
int n= static_cast<CcInt*>(value.addr)->GetIntval();
|
|
string qts= nl->ToString(qp->GetType(args[5].addr));
|
|
GPattern::quantifier q= (qts=="exactly")?
|
|
GPattern::exactly : GPattern::atleast;
|
|
|
|
/*
|
|
Evaluating the gpattern results
|
|
|
|
*/
|
|
qp->Open(TheStream);
|
|
qp->Request(TheStream, t);
|
|
while (qp->Received(TheStream))
|
|
{
|
|
tup = static_cast<Tuple*>(t.addr);
|
|
|
|
(*tupleIDArgs)[0] = tup;
|
|
qp->Request(tupleID, value);
|
|
id= static_cast<CcInt*>(value.addr)->GetIntval();
|
|
|
|
(*liftedPredArgs)[0] = tup;
|
|
qp->Request(liftedPred, value);
|
|
mbool = static_cast<MBool*>(value.addr);
|
|
if (mbool->IsDefined())
|
|
{
|
|
accumlator.Buffer(*mbool, id);
|
|
//accumlator2.Union(*mbool, id);
|
|
}
|
|
tup->DeleteIfAllowed();
|
|
qp->Request(TheStream, t);
|
|
}
|
|
|
|
accumlator.ConstructFromBuffer();
|
|
qp->Close(TheStream);
|
|
|
|
if(debugme)
|
|
{
|
|
MSet tmp1(0), tmp2(0);
|
|
accumlator.WriteToMSet(tmp1);
|
|
//accumlator2.WriteToMSet(tmp2);
|
|
if(tmp1 != tmp2)
|
|
{
|
|
tmp1.Print(cerr);
|
|
//tmp2.Print(cerr);
|
|
}
|
|
}
|
|
|
|
bool changed= true;
|
|
while(changed && accumlator.GetNoComponents() > 0)
|
|
{
|
|
//accumlator2.RemoveSmallUnits(n);
|
|
changed= accumlator.RemoveSmallUnits(n);
|
|
|
|
//accumlator2.RemoveShortElemParts(d);
|
|
changed= (accumlator.RemoveShortElemParts(dMS) || changed );
|
|
}
|
|
if(debugme)
|
|
{
|
|
MSet tmp1(0), tmp2(0);
|
|
accumlator.WriteToMSet(tmp1);
|
|
//accumlator2.WriteToMSet(tmp2);
|
|
if(tmp1 != tmp2)
|
|
{
|
|
tmp1.Print(cerr);
|
|
//tmp2.Print(cerr);
|
|
}
|
|
}
|
|
|
|
list<CompressedInMemUSet>::iterator begin=
|
|
accumlator.units.begin(), end, tmp;
|
|
//cast the CompressedInMemMSet into an InMemMSet
|
|
begin != accumlator.units.end();
|
|
while(begin != accumlator.units.end())
|
|
{
|
|
end= accumlator.GetPeriodEndUnit(begin);
|
|
if(debugme)
|
|
{
|
|
(*begin).Print(cerr);
|
|
(*end).Print(cerr);
|
|
}
|
|
if(q == GPattern::atleast)
|
|
{
|
|
InMemMSet* mset= new InMemMSet();
|
|
tmp= end;
|
|
++tmp;
|
|
accumlator.WriteToInMemMSet(*mset, begin, tmp);
|
|
if(debugme)
|
|
{
|
|
MSet tmp1(0);
|
|
mset->WriteToMSet(tmp1);
|
|
tmp1.Print(cerr);
|
|
}
|
|
resStream->push_back(mset);
|
|
}
|
|
else
|
|
{
|
|
InMemMSet* mset= new InMemMSet();
|
|
tmp= end;
|
|
++tmp;
|
|
accumlator.WriteToInMemMSet(*mset, begin, tmp);
|
|
if(debugme)
|
|
{
|
|
MSet tmp1(0);
|
|
mset->WriteToMSet(tmp1);
|
|
tmp1.Print(cerr);
|
|
}
|
|
|
|
list<InMemUSet>::iterator e= mset->units.end();
|
|
--e;
|
|
GPHelper.ComputeAddSubSets(*mset, mset->units.begin(), e,
|
|
n, dMS, resStream);
|
|
}
|
|
begin= ++end;
|
|
}
|
|
local= SetWord(resStream);
|
|
return 0;
|
|
}
|
|
case REQUEST: { // return the next stream element
|
|
|
|
vector<InMemMSet*>* resStream=
|
|
static_cast<vector<InMemMSet*>*>(local.addr);
|
|
InMemMSet* curRes=0;
|
|
if ( resStream->size() != 0)
|
|
{
|
|
MSet* res= new MSet(0);
|
|
curRes= *resStream->begin();
|
|
curRes->WriteToMSet(*res);
|
|
delete curRes;
|
|
resStream->erase(resStream->begin());
|
|
result= SetWord(res);
|
|
return YIELD;
|
|
}
|
|
else
|
|
{
|
|
// you should always set the result to null
|
|
// before you return a CANCEL
|
|
result.addr = 0;
|
|
return CANCEL;
|
|
}
|
|
|
|
}
|
|
case CLOSE: { // free the local storage
|
|
vector<InMemMSet*>* resStream=
|
|
static_cast<vector<InMemMSet*>* >(local.addr);
|
|
while(!resStream->empty())
|
|
{
|
|
delete *resStream->begin();
|
|
resStream->erase(resStream->begin());
|
|
}
|
|
delete resStream;
|
|
local.addr = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
Value map CrossPattern
|
|
|
|
*/
|
|
|
|
int CrossPatternVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
bool debugme= false;
|
|
switch( message )
|
|
{
|
|
case OPEN:
|
|
{
|
|
/*
|
|
Defining local variables
|
|
|
|
*/
|
|
Word t, value;
|
|
Tuple* tup;
|
|
MBool* mbool;
|
|
int id1, id2, tupleCnt=0;
|
|
vector<pair<int, int> > edge2nodesMap(0);
|
|
CompressedInMemMSet accumlator;
|
|
//InMemMSet accumlator2;
|
|
list<CompressedMSet*>* resStream=
|
|
new list<CompressedMSet*>(), *resStreamFinal=0,
|
|
*localResStream=0;
|
|
GPatternHelper GPHelper;
|
|
StopWatch timer;
|
|
/*
|
|
Reading the operator arguments
|
|
|
|
*/
|
|
Supplier TheStream= args[0].addr,
|
|
tupleID1= args[1].addr,
|
|
tupleID2= args[2].addr,
|
|
liftedPred = args[3].addr;
|
|
ArgVectorPointer tupleID1Args = qp->Argument(tupleID1),
|
|
tupleID2Args = qp->Argument(tupleID2),
|
|
liftedPredArgs = qp->Argument(liftedPred);
|
|
qp->Request(args[4].addr, value);
|
|
int64_t dMS= static_cast<Instant*>(value.addr)->millisecondsToNull();
|
|
qp->Request(args[5].addr, value);
|
|
int n= static_cast<CcInt*>(value.addr)->GetIntval();
|
|
string qts= nl->ToString(qp->GetType(args[6].addr));
|
|
|
|
/*
|
|
Evaluating the gpattern results
|
|
|
|
*/
|
|
timer.start();
|
|
qp->Open(TheStream);
|
|
qp->Request(TheStream, t);
|
|
while (qp->Received(TheStream))
|
|
{
|
|
tup = static_cast<Tuple*>(t.addr);
|
|
|
|
(*tupleID1Args)[0] = tup;
|
|
qp->Request(tupleID1, value);
|
|
id1= static_cast<CcInt*>(value.addr)->GetIntval();
|
|
|
|
(*tupleID2Args)[0] = tup;
|
|
qp->Request(tupleID2, value);
|
|
id2= static_cast<CcInt*>(value.addr)->GetIntval();
|
|
|
|
(*liftedPredArgs)[0] = tup;
|
|
qp->Request(liftedPred, value);
|
|
mbool = static_cast<MBool*>(value.addr);
|
|
if (mbool->IsDefined())
|
|
{
|
|
/*
|
|
Using bool inc= accumlator.Buffer(mbool, tupleCnt, d) is wrong. A series of
|
|
short edges might lead that a node is part of a component long enough. The
|
|
correct objective is to filter out short node appearance, which cannot be
|
|
performed in this step.
|
|
|
|
*/
|
|
|
|
//bool inc= accumlator.Buffer(*mbool, tupleCnt, d);
|
|
bool inc= accumlator.Buffer(*mbool, tupleCnt);
|
|
//GPHelper.removeShortUnits(*mbool, d);
|
|
//accumlator2.Union(*mbool, tupleCnt);
|
|
if(inc)
|
|
{
|
|
edge2nodesMap.push_back(make_pair(id1, id2));
|
|
++tupleCnt;
|
|
}
|
|
//accumlator.Buffer(*mbool, tupleCnt);
|
|
}
|
|
tup->DeleteIfAllowed();
|
|
qp->Request(TheStream, t);
|
|
}
|
|
double ReadInputSecondsCPU = timer.diffSecondsCPU();
|
|
double ReadInputSecondsReal = timer.diffSecondsReal();
|
|
cerr<< "\n ########### TIMER ############ \n";
|
|
cerr<<"Reading the input took (CPU/Real) (" << ReadInputSecondsCPU << "/"
|
|
<<ReadInputSecondsReal << ") seconds.\n";
|
|
timer.start();
|
|
|
|
accumlator.ConstructFromBuffer();
|
|
|
|
double ConstructPGSecondsCPU = timer.diffSecondsCPU();
|
|
double ConstructPGSecondsReal = timer.diffSecondsReal();
|
|
cerr<< "\n ########### TIMER ############ \n";
|
|
cerr<<"Constructing the Pattern Graph took (CPU/Real) (" <<
|
|
ConstructPGSecondsCPU << "/" << ConstructPGSecondsReal <<
|
|
") seconds.\n";
|
|
|
|
|
|
qp->Close(TheStream);
|
|
|
|
if(debugme )
|
|
{
|
|
time_t rawtime;
|
|
time ( &rawtime );
|
|
cerr<<"\nAccumlator Constructed "<< ctime (&rawtime);
|
|
|
|
// MSet tmp1(0), tmp2(0);
|
|
// accumlator.WriteToMSet(tmp1);
|
|
// //accumlator2.WriteToMSet(tmp2);
|
|
// if(tmp1 != tmp2)
|
|
// {
|
|
// tmp1.Print(cerr);
|
|
// //tmp2.Print(cerr);
|
|
// }
|
|
}
|
|
|
|
list<CompressedInMemUSet>::iterator begin=
|
|
accumlator.units.begin(), end, tmp;
|
|
//cast the CompressedInMemMSet into an InMemMSet
|
|
while(begin != accumlator.units.end())
|
|
{
|
|
end= accumlator.GetPeriodEndUnit(begin);
|
|
if(debugme && 0)
|
|
{
|
|
accumlator.Print(cerr);
|
|
(*begin).Print(cerr);
|
|
(*end).Print(cerr);
|
|
}
|
|
if((*end).endtime - (*begin).starttime >= dMS)
|
|
{
|
|
++end;
|
|
if(begin != accumlator.units.begin())
|
|
{
|
|
CompressedInMemMSet accumlatorPart(accumlator, begin, end);
|
|
if(debugme && 0)
|
|
{
|
|
MSet tmp1(0);
|
|
//accumlatorPart.WriteToMSet(tmp1);
|
|
//accumlator2.WriteToMSet(tmp2);
|
|
//tmp1.Print(cerr);
|
|
}
|
|
GPHelper.FindLargeDynamicComponents(accumlatorPart,
|
|
accumlatorPart.units.begin(), accumlatorPart.units.end() ,
|
|
edge2nodesMap, dMS, n, qts, localResStream, 0);
|
|
}
|
|
else
|
|
{
|
|
GPHelper.FindLargeDynamicComponents(accumlator, begin, end ,
|
|
edge2nodesMap, dMS, n, qts, localResStream, 0);
|
|
}
|
|
resStream->splice(resStream->end(), *localResStream);
|
|
delete localResStream;
|
|
localResStream= 0;
|
|
}
|
|
else
|
|
++end;
|
|
begin= end;
|
|
}
|
|
resStreamFinal= new list<CompressedMSet*>();
|
|
for(list<CompressedMSet*>::iterator
|
|
it= resStream->begin(); it!= resStream->end(); ++it)
|
|
{
|
|
if(debugme && 0)
|
|
(*it)->Print(cerr);
|
|
resStreamFinal->push_back(GPHelper.EdgeMSet2NodeMSet(*it, edge2nodesMap));
|
|
delete *it;
|
|
*it = 0;
|
|
}
|
|
delete resStream;
|
|
|
|
local= SetWord(resStreamFinal);
|
|
return 0;
|
|
}
|
|
case REQUEST: { // return the next stream element
|
|
|
|
list<CompressedMSet*>* resStream=
|
|
static_cast< list<CompressedMSet*>* >(local.addr);
|
|
CompressedInMemMSet tmp;
|
|
if ( resStream->size() != 0)
|
|
{
|
|
MSet* res= new MSet(0);
|
|
resStream->front()->WriteToCompressedInMemMSet(tmp);
|
|
tmp.WriteToMSet(*res);
|
|
delete resStream->front();
|
|
resStream->pop_front();
|
|
result= SetWord(res);
|
|
return YIELD;
|
|
}
|
|
else
|
|
{
|
|
// you should always set the result to null
|
|
// before you return a CANCEL
|
|
result.addr = 0;
|
|
return CANCEL;
|
|
}
|
|
|
|
}
|
|
case CLOSE: { // free the local storage
|
|
list<CompressedMSet*>* resStream=
|
|
static_cast<list<CompressedMSet*>* >(local.addr);
|
|
for(list<CompressedMSet*>::iterator
|
|
it= resStream->begin(); it!= resStream->end(); ++it)
|
|
{
|
|
delete *it;
|
|
*it = 0;
|
|
}
|
|
resStream->clear();
|
|
delete resStream;
|
|
local.addr = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int EmptyMSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
static_cast<MSet*>(result.addr)->Clear();
|
|
static_cast<MSet*>(result.addr)->SetDefined(true);
|
|
return 0;
|
|
}
|
|
|
|
int MBool2MSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
MSet* res= static_cast<MSet*>(result.addr);
|
|
MBool * arg1= static_cast<MBool*>(args[0].addr);
|
|
CcInt * arg2= static_cast<CcInt*>(args[1].addr);
|
|
res->MBool2MSet(*arg1, arg2->GetIntval());
|
|
return 0;
|
|
}
|
|
|
|
|
|
int UnionMSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
MSet* res= static_cast<MSet*>(result.addr);
|
|
MSet* op1= static_cast<MSet*>(args[0].addr);
|
|
MSet* op2= static_cast<MSet*>(args[1].addr);
|
|
op1->LiftedUnion(*op2, *res);
|
|
return 0;
|
|
}
|
|
|
|
int UnionIntSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
IntSet* res= static_cast<IntSet*>(result.addr);
|
|
IntSet* op1= static_cast<IntSet*>(args[0].addr);
|
|
IntSet* op2= static_cast<IntSet*>(args[1].addr);
|
|
op1->Union(*op2, *res);
|
|
return 0;
|
|
}
|
|
|
|
|
|
ValueMapping UnionVMMap[] = {
|
|
UnionMSetVM,
|
|
UnionIntSetVM
|
|
};
|
|
|
|
template<bool equals>
|
|
int EqualsMSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
CcBool* res= static_cast<CcBool*>(result.addr);
|
|
MSet* op1= static_cast<MSet*>(args[0].addr);
|
|
MSet* op2= static_cast<MSet*>(args[1].addr);
|
|
bool r= ((*op1) == (*op2));
|
|
if(equals)
|
|
res->Set(true, r);
|
|
else
|
|
res->Set(true, !r);
|
|
return 0;
|
|
}
|
|
|
|
template<bool equals>
|
|
int EqualsIntSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
CcBool* res= static_cast<CcBool*>(result.addr);
|
|
IntSet* op1= static_cast<IntSet*>(args[0].addr);
|
|
IntSet* op2= static_cast<IntSet*>(args[1].addr);
|
|
bool r= ((*op1) == (*op2));
|
|
if(equals)
|
|
res->Set(true, r);
|
|
else
|
|
res->Set(true, !r);
|
|
return 0;
|
|
}
|
|
|
|
|
|
ValueMapping NEqualsVMMap[] = {
|
|
EqualsMSetVM<false>,
|
|
EqualsIntSetVM<false>
|
|
};
|
|
|
|
ValueMapping EqualsVMMap[] = {
|
|
EqualsMSetVM<true>,
|
|
EqualsIntSetVM<true>
|
|
};
|
|
|
|
int Union2MSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
MSet* res= static_cast<MSet*>(result.addr);
|
|
MSet* op1= static_cast<MSet*>(args[0].addr);
|
|
MSet* op2= static_cast<MSet*>(args[1].addr);
|
|
op1->LiftedUnion2(*op2, *res);
|
|
return 0;
|
|
}
|
|
|
|
int MinusMSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
MSet* res= static_cast<MSet*>(result.addr);
|
|
MSet* op1= static_cast<MSet*>(args[0].addr);
|
|
MSet* op2= static_cast<MSet*>(args[1].addr);
|
|
op1->LiftedMinus(*op2, *res);
|
|
return 0;
|
|
}
|
|
|
|
int MinusSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
IntSet* res= static_cast<IntSet*>(result.addr);
|
|
IntSet* op1= static_cast<IntSet*>(args[0].addr);
|
|
IntSet* op2= static_cast<IntSet*>(args[1].addr);
|
|
op1->Minus(*op2, *res);
|
|
return 0;
|
|
}
|
|
|
|
ValueMapping MinusVMMap[] = {
|
|
MinusMSetVM,
|
|
MinusSetVM};
|
|
|
|
|
|
int IsSubsetMSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
MBool* res= static_cast<MBool*>(result.addr);
|
|
MSet* op1= static_cast<MSet*>(args[0].addr);
|
|
MSet* op2= static_cast<MSet*>(args[1].addr);
|
|
op1->LiftedIsSubset(*op2, *res);
|
|
return 0;
|
|
}
|
|
|
|
int IsSubsetUSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
MBool* res= static_cast<MBool*>(result.addr);
|
|
USet* op1= static_cast<USet*>(args[0].addr);
|
|
USet* op2= static_cast<USet*>(args[1].addr);
|
|
MSet op1Container(0), op2Container(0);
|
|
op1Container.Add(*op1);
|
|
op2Container.Add(*op2);
|
|
op1Container.LiftedIsSubset(op2Container, *res);
|
|
return 0;
|
|
}
|
|
|
|
int IsSubsetSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
CcBool* res= static_cast<CcBool*>(result.addr);
|
|
IntSet* op1= static_cast<IntSet*>(args[0].addr);
|
|
IntSet* op2= static_cast<IntSet*>(args[1].addr);
|
|
bool r= op1->IsSubset(*op2);
|
|
res->Set(true, r);
|
|
return 0;
|
|
}
|
|
|
|
ValueMapping IsSubsetVMMap[] = {
|
|
IsSubsetMSetVM,
|
|
IsSubsetUSetVM,
|
|
IsSubsetSetVM
|
|
};
|
|
|
|
template<int argIndex>
|
|
int MUSSetSelect( ListExpr args )
|
|
{
|
|
ListExpr arg = nl->Nth(argIndex + 1, args );
|
|
|
|
if (nl->IsAtom( arg ) )
|
|
{
|
|
if( nl->SymbolValue( arg ) == MSet::BasicType() )
|
|
return 0;
|
|
else if( nl->SymbolValue( arg ) == USet::BasicType() )
|
|
return 1;
|
|
else if( nl->SymbolValue( arg ) == IntSet::BasicType() )
|
|
return 2;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
struct UnitsLocalInfo
|
|
{
|
|
Word mWord; // the address of the moving point/int/real value
|
|
int unitIndex; // current item index
|
|
};
|
|
|
|
int UnitsVM(Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
MSet* m;
|
|
USetRef usetref(true);
|
|
USet* uset;
|
|
UnitsLocalInfo* localinfo;
|
|
switch( message )
|
|
{
|
|
case OPEN:
|
|
localinfo = new UnitsLocalInfo;
|
|
m = static_cast<MSet*>(args[0].addr);
|
|
if(m->IsDefined()){
|
|
localinfo->mWord = args[0];
|
|
localinfo->unitIndex = 0;
|
|
local = SetWord(localinfo);
|
|
} else {
|
|
local.setAddr( 0 );
|
|
}
|
|
return 0;
|
|
|
|
case REQUEST:
|
|
|
|
if( local.addr == 0 )
|
|
return CANCEL;
|
|
localinfo = static_cast<UnitsLocalInfo *>(local.addr);
|
|
m = (MSet*)localinfo->mWord.addr;
|
|
while( (0 <= localinfo->unitIndex)
|
|
&& (localinfo->unitIndex < m->GetNoComponents()) )
|
|
{
|
|
m->Get(localinfo->unitIndex, usetref);
|
|
++localinfo->unitIndex;
|
|
if(!usetref.IsDefined() )
|
|
continue;
|
|
|
|
uset= new USet(true);
|
|
usetref.GetUnit(m->data, *uset);
|
|
result.setAddr(uset);
|
|
|
|
return YIELD;
|
|
}
|
|
return CANCEL;
|
|
|
|
case CLOSE:
|
|
|
|
if( local.addr != 0 )
|
|
{
|
|
delete (UnitsLocalInfo *)local.addr;
|
|
local = SetWord(Address(0));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// should not happen
|
|
return -1;
|
|
}
|
|
|
|
|
|
int CardinalityMSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
MInt* res= static_cast<MInt*>(result.addr);
|
|
MSet* arg= static_cast<MSet*>(args[0].addr);
|
|
arg->LiftedCount(*res);
|
|
return 0;
|
|
}
|
|
|
|
int CardinalityUSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
CcInt* res= static_cast<CcInt*>(result.addr);
|
|
USet* arg= static_cast<USet*>(args[0].addr);
|
|
if(!arg->IsDefined())
|
|
res->SetDefined(false);
|
|
else
|
|
res->Set(true, arg->constValue.Count());
|
|
return 0;
|
|
}
|
|
|
|
int CardinalityISetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
CcInt* res= static_cast<CcInt*>(result.addr);
|
|
ISet* arg= static_cast<ISet*>(args[0].addr);
|
|
if(!arg->IsDefined())
|
|
res->SetDefined(false);
|
|
else
|
|
res->Set(true, arg->value.Count());
|
|
return 0;
|
|
}
|
|
|
|
int CardinalitySetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result= qp->ResultStorage(s);
|
|
CcInt* res= static_cast<CcInt*>(result.addr);
|
|
IntSet* arg= static_cast<IntSet*>(args[0].addr);
|
|
if(!arg->IsDefined())
|
|
res->SetDefined(false);
|
|
else
|
|
res->Set(true, arg->Count());
|
|
return 0;
|
|
}
|
|
|
|
ValueMapping CardinalityVMMap[] = {
|
|
CardinalityMSetVM,
|
|
CardinalityUSetVM,
|
|
CardinalityISetVM,
|
|
CardinalitySetVM,
|
|
};
|
|
|
|
template<int argIndex>
|
|
int MSSetSelect( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->Nth(argIndex + 1, args );
|
|
|
|
if (nl->IsAtom( arg1 ) )
|
|
{
|
|
if( nl->SymbolValue( arg1 ) == MSet::BasicType() )
|
|
return 0;
|
|
else if( nl->SymbolValue( arg1 ) == IntSet::BasicType() )
|
|
return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
template<int argIndex>
|
|
int MUISSetSelect( ListExpr args )
|
|
{
|
|
ListExpr arg = nl->Nth(argIndex + 1, args );
|
|
|
|
if (nl->IsAtom( arg ) )
|
|
{
|
|
if( nl->SymbolValue( arg ) == MSet::BasicType() )
|
|
return 0;
|
|
else if( nl->SymbolValue( arg ) == USet::BasicType() )
|
|
return 1;
|
|
else if( nl->SymbolValue( arg ) == ISet::BasicType() )
|
|
return 2;
|
|
else if( nl->SymbolValue( arg ) == IntSet::BasicType() )
|
|
return 3;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
template <class Alfa>
|
|
int CreateAlfaSetVM
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
//bool debugme= false;
|
|
Word t, value;
|
|
Tuple* tup;
|
|
IntSet* res=0;
|
|
int elem;
|
|
|
|
int attrIndex= static_cast<CcInt*>(args[2].addr)->GetIntval();
|
|
//string attrType= static_cast<CcString*>(args[3].addr)->GetValue();
|
|
result = qp->ResultStorage( s );
|
|
res= static_cast< IntSet* > (result.addr);
|
|
res->Clear();
|
|
qp->Open(args[0].addr);
|
|
qp->Request(args[0].addr, t);
|
|
while (qp->Received(args[0].addr))
|
|
{
|
|
tup = (Tuple*)t.addr;
|
|
elem= dynamic_cast< CcInt* > (tup->GetAttribute(attrIndex-1))->GetIntval();
|
|
res->Insert(elem);
|
|
qp->Request(args[0].addr, t);
|
|
res->Print(cerr);
|
|
}
|
|
qp->Close(args[0].addr);
|
|
return 0;
|
|
}
|
|
|
|
template <int initfin>
|
|
int USetInitialFinal( Word* args, Word& result, int message,
|
|
Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
|
|
USet* unit = ((USet*)args[0].addr);
|
|
ISet* res = ((ISet*)result.addr);
|
|
Instant inst(0, 0, instanttype);
|
|
if(initfin == 0)
|
|
inst.CopyFrom(&unit->timeInterval.start);
|
|
else if(initfin == 1)
|
|
inst.CopyFrom(&unit->timeInterval.end);
|
|
else
|
|
assert(false);
|
|
|
|
if( !unit->IsDefined() || !(inst.IsDefined()) )
|
|
res->SetDefined( false );
|
|
else
|
|
{
|
|
unit->TemporalFunction( inst, res->value, true );
|
|
res->instant.CopyFrom( &inst );
|
|
res->SetDefined( true );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int MSetInitial( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
((MSet*)args[0].addr)->Initial( *((ISet*)result.addr) );
|
|
return 0;
|
|
}
|
|
|
|
int MSetFinal( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
((MSet*)args[0].addr)->Final( *((ISet*)result.addr) );
|
|
return 0;
|
|
}
|
|
|
|
ValueMapping InitVMMap[] = {
|
|
MSetInitial,
|
|
USetInitialFinal<0>};
|
|
|
|
ValueMapping FinVMMap[] = {
|
|
MSetFinal,
|
|
USetInitialFinal<1>};
|
|
|
|
int InitFinSelect( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First( args );
|
|
|
|
if (nl->IsAtom( arg1 ) )
|
|
{
|
|
if( nl->SymbolValue( arg1 ) == MSet::BasicType() )
|
|
return 0;
|
|
if( nl->SymbolValue( arg1 ) == USet::BasicType() )
|
|
return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void
|
|
MPointsSample(Instant& curTime, vector<MPoint*>& sourceMPoints, Points& res,
|
|
bool checkDefined)
|
|
{
|
|
bool debugme=false;
|
|
if(debugme)
|
|
curTime.Print(cerr);
|
|
res.Clear();
|
|
Point curPoint(0, 0);
|
|
Intime<Point> pointIntime(curTime, curPoint);
|
|
for(unsigned int i=0; i<sourceMPoints.size(); ++i)
|
|
{
|
|
sourceMPoints[i]->AtInstant(curTime, pointIntime);
|
|
// if(checkDefined)
|
|
assert(pointIntime.IsDefined());
|
|
if(debugme)
|
|
pointIntime.Print(cerr);
|
|
res += pointIntime.value;
|
|
}
|
|
}
|
|
|
|
void
|
|
MPointsSample(Instant& curTime, set<int>& idset,
|
|
map<int, MPoint*>& sourceMPoints, Points& res, bool checkDefined)
|
|
{
|
|
bool debugme=false;
|
|
if(debugme)
|
|
curTime.Print(cerr);
|
|
res.Clear();
|
|
Point curPoint(0, 0);
|
|
Intime<Point> pointIntime(curTime, curPoint);
|
|
set<int>::iterator id= idset.begin();
|
|
for(; id != idset.end(); ++id)
|
|
{
|
|
sourceMPoints[*id]->AtInstant(curTime, pointIntime);
|
|
// if(checkDefined)
|
|
// assert(pointIntime.IsDefined());
|
|
if(debugme)
|
|
pointIntime.Print(cerr);
|
|
if(pointIntime.IsDefined()) res += pointIntime.value;
|
|
}
|
|
}
|
|
|
|
|
|
void AppendMRegionPart(set<int>& idset, map<int, MPoint*>& sourceMPoints,
|
|
Interval<Instant>& unitBoundary,
|
|
Instant& samplingDuration,
|
|
MRegion& res)
|
|
{
|
|
bool debugme=false;
|
|
vector<double> weigths(4);
|
|
weigths[0] = 0.7; // AreaWeight
|
|
weigths[1] = 0.7; // OverlapWeight
|
|
weigths[2] = 0.5; // HausdorffWeight
|
|
weigths[3] = 1.0; // LinearWeight
|
|
|
|
Instant curTime(unitBoundary.start);
|
|
Interval<Instant>
|
|
unitInterval(curTime, unitBoundary.end, unitBoundary.lc, false);
|
|
|
|
Points ps(0);
|
|
Region* reg1=new Region(0), *reg2=new Region(0), *regswap;
|
|
RegionForInterpolation *reginter1, *reginter2, *reginterswap;
|
|
Match *sm;
|
|
mLineRep *lines;
|
|
URegion *resUnit;
|
|
bool firstIteration= true;
|
|
|
|
MPointsSample(curTime, idset, sourceMPoints, ps, true);
|
|
GrahamScan::convexHull(&ps,reg1);
|
|
reginter1=new RegionInterpol::RegionForInterpolation(reg1);
|
|
curTime+= samplingDuration;
|
|
while(curTime < unitBoundary.end)
|
|
{
|
|
if(!firstIteration)
|
|
unitInterval.lc= true;
|
|
firstIteration= false;
|
|
MPointsSample(curTime, idset, sourceMPoints, ps, true);
|
|
GrahamScan::convexHull(&ps, reg2);
|
|
unitInterval.end= curTime;
|
|
reginter2=new RegionInterpol::RegionForInterpolation(reg2);
|
|
sm=new OptimalMatch(reginter1, reginter2, weigths);
|
|
lines=new mLineRep(sm);
|
|
resUnit= new URegion(lines->getTriangles(), unitInterval);
|
|
if(debugme)
|
|
unitInterval.Print(cerr);
|
|
res.AddURegion(*resUnit);
|
|
/*
|
|
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 reginterswap;
|
|
curTime+= samplingDuration;
|
|
}
|
|
/*
|
|
Adding the last instant in the unit
|
|
|
|
*/
|
|
Instant endI(unitBoundary.end);
|
|
if(!unitBoundary.rc)
|
|
{
|
|
Instant milli(0, 1, durationtype);
|
|
endI -= milli;
|
|
}
|
|
MPointsSample(endI, idset, sourceMPoints, ps, false);
|
|
unitInterval.rc= unitBoundary.rc;
|
|
GrahamScan::convexHull(&ps, reg2);
|
|
unitInterval.end= unitBoundary.end;
|
|
reginter2=new RegionInterpol::RegionForInterpolation(reg2);
|
|
sm=new OptimalMatch(reginter1, reginter2, weigths);
|
|
lines=new mLineRep(sm);
|
|
resUnit= new URegion(lines->getTriangles(), unitInterval);
|
|
if(debugme)
|
|
unitInterval.Print(cerr);
|
|
res.AddURegion(*resUnit);
|
|
delete resUnit;
|
|
delete lines;
|
|
delete reg1;
|
|
delete reg2;
|
|
delete reginter1;
|
|
delete reginter2;
|
|
}
|
|
|
|
/*
|
|
Value maps BoundingRegion
|
|
|
|
*/
|
|
void MSet2MRegion(Supplier stream, MSet* mset, Instant* d, MRegion* res)
|
|
{
|
|
bool debugme= false;
|
|
|
|
try{
|
|
res->Clear();
|
|
if(debugme)
|
|
mset->Print(cerr);
|
|
|
|
if(!mset->IsDefined() || mset->GetNoComponents()==0)
|
|
{
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
USetRef usetref;
|
|
USet uset(true);
|
|
set<int> idset;
|
|
set<int>::iterator setIt;
|
|
for(int i=0; i<mset->GetNoComponents(); ++i)
|
|
{
|
|
mset->Get(i, usetref);
|
|
usetref.GetUnit(mset->data, uset);
|
|
if(uset.constValue.Count() > 2)
|
|
{
|
|
for(int k=0; k< uset.constValue.Count(); ++k)
|
|
idset.insert(uset.constValue[k]);
|
|
}
|
|
else
|
|
{
|
|
//Cannot construct a region using less than 3 points
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
}
|
|
|
|
Word Value;
|
|
map<int, MPoint*> mpoints;
|
|
vector<Tuple*> tuplesToDelete(0);
|
|
qp->Open(stream);
|
|
qp->Request(stream, Value);
|
|
while(qp->Received(stream) && (mpoints.size() < idset.size()))
|
|
{
|
|
Tuple* tuple= static_cast<Tuple*>(Value.addr);
|
|
int id= dynamic_cast<CcInt*>(tuple->GetAttribute(0))->GetIntval();
|
|
setIt= idset.find(id);
|
|
if(setIt != idset.end())
|
|
{
|
|
MPoint* elem=dynamic_cast<MPoint*>(
|
|
dynamic_cast<MPoint*>(tuple->GetAttribute(1)));
|
|
mpoints[id]= elem;
|
|
tuplesToDelete.push_back(tuple);
|
|
}
|
|
else
|
|
tuple->DeleteIfAllowed();
|
|
|
|
qp->Request(stream, Value);
|
|
}
|
|
qp->Close(stream);
|
|
if(mpoints.size() != idset.size())
|
|
{
|
|
res->SetDefined(false);
|
|
cerr<<"mset2mregion: not all ids in the mset are "
|
|
"found in the mpoint stream\n";
|
|
for(unsigned int k=0; k<tuplesToDelete.size(); ++k)
|
|
tuplesToDelete[k]->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
for(int i=0; i<mset->GetNoComponents(); ++i)
|
|
{
|
|
mset->Get(i, usetref);
|
|
usetref.GetUnit(mset->data, uset);
|
|
if(uset.constValue.Count()!= 0)
|
|
{
|
|
idset.clear();
|
|
for(int k=0; k< uset.constValue.Count(); ++k)
|
|
idset.insert(uset.constValue[k]);
|
|
AppendMRegionPart(idset, mpoints, usetref.timeInterval, *d , *res);
|
|
}
|
|
}
|
|
for(unsigned int k=0; k<tuplesToDelete.size(); ++k)
|
|
tuplesToDelete[k]->DeleteIfAllowed();
|
|
}
|
|
catch(...)
|
|
{
|
|
cerr<<"\nUnhandeled exception in boundingregion ValueMap. "
|
|
"Yielding undefined result.\n";
|
|
res->Clear();
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
void USet2MRegion(Supplier stream, USet* uset, Instant* d, MRegion* res)
|
|
{
|
|
bool debugme= false;
|
|
|
|
try{
|
|
res->Clear();
|
|
if(debugme)
|
|
uset->Print(cerr);
|
|
|
|
if(!uset->IsDefined())
|
|
{
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
set<int> idset;
|
|
set<int>::iterator setIt;
|
|
if(uset->constValue.Count() > 2)
|
|
{
|
|
for(int k=0; k< uset->constValue.Count(); ++k)
|
|
idset.insert(uset->constValue[k]);
|
|
}
|
|
else
|
|
{
|
|
//Cannot construct a region using less than 3 points
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
Word Value;
|
|
map<int, MPoint*> mpoints;
|
|
vector<Tuple*> tuplesToDelete(0);
|
|
qp->Open(stream);
|
|
qp->Request(stream, Value);
|
|
while(qp->Received(stream) && (mpoints.size() < idset.size()))
|
|
{
|
|
Tuple* tuple= static_cast<Tuple*>(Value.addr);
|
|
int id= dynamic_cast<CcInt*>(tuple->GetAttribute(0))->GetIntval();
|
|
setIt= idset.find(id);
|
|
if(setIt != idset.end())
|
|
{
|
|
MPoint* elem=dynamic_cast<MPoint*>(
|
|
dynamic_cast<MPoint*>(tuple->GetAttribute(1)));
|
|
mpoints[id]= elem;
|
|
tuplesToDelete.push_back(tuple);
|
|
}
|
|
else
|
|
tuple->DeleteIfAllowed();
|
|
|
|
qp->Request(stream, Value);
|
|
}
|
|
qp->Close(stream);
|
|
if(mpoints.size() != idset.size())
|
|
{
|
|
res->SetDefined(false);
|
|
cerr<<"mset2mregion: not all ids in the mset are "
|
|
"found in the mpoint stream\n";
|
|
for(unsigned int k=0; k<tuplesToDelete.size(); ++k)
|
|
tuplesToDelete[k]->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
if(uset->constValue.Count()!= 0)
|
|
{
|
|
idset.clear();
|
|
for(int k=0; k< uset->constValue.Count(); ++k)
|
|
idset.insert(uset->constValue[k]);
|
|
AppendMRegionPart(idset, mpoints, uset->timeInterval, *d , *res);
|
|
}
|
|
|
|
for(unsigned int k=0; k<tuplesToDelete.size(); ++k)
|
|
tuplesToDelete[k]->DeleteIfAllowed();
|
|
}
|
|
catch(...)
|
|
{
|
|
cerr<<"\nUnhandeled exception in boundingregion ValueMap. "
|
|
"Yielding undefined result.\n";
|
|
res->Clear();
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void ISet2Region(Supplier stream, ISet* iset, Region* res)
|
|
{
|
|
bool debugme= false;
|
|
|
|
try{
|
|
res->Clear();
|
|
if(debugme)
|
|
iset->Print(cerr);
|
|
|
|
if(!iset->IsDefined())
|
|
{
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
set<int> idset;
|
|
set<int>::iterator setIt;
|
|
if(iset->value.Count() > 2)
|
|
{
|
|
for(int k=0; k< iset->value.Count(); ++k)
|
|
idset.insert(iset->value[k]);
|
|
}
|
|
else
|
|
{
|
|
//Cannot construct a region using less than 3 points
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
Word Value;
|
|
Intime<Point> pt(0);
|
|
Points pts(0);
|
|
qp->Open(stream);
|
|
qp->Request(stream, Value);
|
|
while(qp->Received(stream))
|
|
{
|
|
Tuple* tuple= static_cast<Tuple*>(Value.addr);
|
|
int id= dynamic_cast<CcInt*>(tuple->GetAttribute(0))->GetIntval();
|
|
setIt= idset.find(id);
|
|
if(setIt != idset.end())
|
|
{
|
|
MPoint* elem=dynamic_cast<MPoint*>(
|
|
dynamic_cast<MPoint*>(tuple->GetAttribute(1)));
|
|
elem->AtInstant(iset->instant, pt);
|
|
if(pt.IsDefined()) pts += pt.value;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
qp->Request(stream, Value);
|
|
}
|
|
qp->Close(stream);
|
|
|
|
if(pts.Size() < 3)
|
|
{
|
|
res->SetDefined(false);
|
|
cerr<<"boundingregion: "
|
|
"Cannot construct a region using less than 3 points \n";
|
|
return;
|
|
}
|
|
GrahamScan::convexHull(&pts, res);
|
|
}
|
|
catch(...)
|
|
{
|
|
cerr<<"\nUnhandeled exception in boundingregion ValueMap. "
|
|
"Yielding undefined result.\n";
|
|
res->Clear();
|
|
res->SetDefined(false);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
int
|
|
MSet2MRegionVM(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result = qp->ResultStorage(s);
|
|
MRegion* res = static_cast<MRegion*>( result.addr);
|
|
Word Value;
|
|
Supplier stream= qp->GetSon(s,0);
|
|
Supplier arg1= qp->GetSon(s,1);
|
|
Supplier arg2= qp->GetSon(s,2);
|
|
|
|
qp->Request(arg1, Value);
|
|
MSet* mset= static_cast<MSet*>(Value.addr);
|
|
qp->Request(arg2, Value);
|
|
Instant* d= static_cast<Instant*>(Value.addr);
|
|
|
|
MSet2MRegion(stream, mset, d, res);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
USet2MRegionVM(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result = qp->ResultStorage(s);
|
|
MRegion* res = static_cast<MRegion*>( result.addr);
|
|
Word Value;
|
|
Supplier stream= qp->GetSon(s,0);
|
|
Supplier arg1= qp->GetSon(s,1);
|
|
Supplier arg2= qp->GetSon(s,2);
|
|
|
|
qp->Request(arg1, Value);
|
|
USet* uset= static_cast<USet*>(Value.addr);
|
|
qp->Request(arg2, Value);
|
|
Instant* d= static_cast<Instant*>(Value.addr);
|
|
|
|
USet2MRegion(stream, uset, d, res);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ISet2RegionVM(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result = qp->ResultStorage(s);
|
|
Region* res = static_cast<Region*>( result.addr);
|
|
Word Value;
|
|
Supplier stream= qp->GetSon(s,0);
|
|
Supplier arg1= qp->GetSon(s,1);
|
|
|
|
qp->Request(arg1, Value);
|
|
ISet* iset= static_cast<ISet*>(Value.addr);
|
|
|
|
|
|
ISet2Region(stream, iset, res);
|
|
return 0;
|
|
}
|
|
/*
|
|
Value map MSet2MPoints
|
|
|
|
*/
|
|
|
|
int
|
|
MSet2MPointsVM(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
|
|
//bool debugme=false;
|
|
|
|
switch( message )
|
|
{
|
|
case OPEN: { // initialize the local storag
|
|
map<int, Periods*>* msetElems= new map<int, Periods*>();
|
|
Word Value;
|
|
Supplier arg1= qp->GetSon(s,1);
|
|
qp->Request(arg1, Value);
|
|
MSet* mset= static_cast<MSet*>(Value.addr);
|
|
int nocomponents= mset->GetNoComponents();
|
|
if(!mset->IsDefined() || nocomponents==0)
|
|
{
|
|
local=SetWord(msetElems);
|
|
return 0;
|
|
}
|
|
Supplier arg2= qp->GetSon(s,2);
|
|
qp->Request(arg2, Value);
|
|
bool restrictMPoints= static_cast<CcBool*>(Value.addr)->GetBoolval();
|
|
|
|
int nounitcomponents=0, idFromMSet=0;
|
|
map<int, Periods*>::iterator msetElemsIt;
|
|
|
|
USetRef usetref;
|
|
USet uset(true);
|
|
for(int i=0; i< nocomponents; ++i)
|
|
{
|
|
mset->Get(i, usetref);
|
|
usetref.GetUnit(mset->data, uset);
|
|
nounitcomponents= uset.constValue.Count();
|
|
for(int e= 0; e<nounitcomponents; ++e)
|
|
{
|
|
idFromMSet= uset.constValue[e];
|
|
msetElemsIt= msetElems->find(idFromMSet);
|
|
if(msetElemsIt == msetElems->end())
|
|
{
|
|
Periods* periods= new Periods(1);
|
|
periods->Add(uset.timeInterval);
|
|
(*msetElems)[idFromMSet]= periods;
|
|
}
|
|
else
|
|
{
|
|
if(!restrictMPoints)
|
|
continue;
|
|
(*msetElemsIt).second->MergeAdd(uset.timeInterval);
|
|
}
|
|
}
|
|
}
|
|
local=SetWord(msetElems);
|
|
qp->Open( args[0].addr );
|
|
return 0;
|
|
}
|
|
case REQUEST: { // return the next stream element
|
|
map<int, Periods*>* msetElems= static_cast<map<int, Periods*>*>(local.addr);
|
|
if(msetElems->size() == 0)
|
|
{
|
|
result.addr = 0;
|
|
return CANCEL;
|
|
}
|
|
//result = qp->ResultStorage(s);
|
|
Word Value;
|
|
map<int, Periods*>::iterator msetElemsIt;
|
|
Supplier arg2= qp->GetSon(s,2);
|
|
qp->Request(arg2, Value);
|
|
bool restrictMPoints= static_cast<CcBool*>(Value.addr)->GetBoolval();
|
|
|
|
qp->Request(args[0].addr, Value);
|
|
while(qp->Received(args[0].addr))
|
|
{
|
|
Tuple* tuple= static_cast<Tuple*>(Value.addr);
|
|
int idFromTuple=
|
|
dynamic_cast<CcInt*>(tuple->GetAttribute(0))->GetIntval();
|
|
msetElemsIt= msetElems->find(idFromTuple);
|
|
if(msetElemsIt != msetElems->end())
|
|
{
|
|
MPoint* res= new MPoint(0);
|
|
if(restrictMPoints)
|
|
{
|
|
MPoint* tmp = dynamic_cast<MPoint*>(tuple->GetAttribute(1));
|
|
tmp->AtPeriods(*((*msetElemsIt).second), *res);
|
|
}
|
|
else
|
|
{
|
|
MPoint* tmp = dynamic_cast<MPoint*>(tuple->GetAttribute(1));
|
|
res->CopyFrom(tmp);
|
|
}
|
|
msetElems->erase(msetElemsIt);
|
|
tuple->DeleteIfAllowed();
|
|
result= SetWord(res);
|
|
return YIELD;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
qp->Request(args[0].addr, Value);
|
|
}
|
|
cerr<<"operator mset2mpoints: some mset elements are not found in "
|
|
"the stream";
|
|
return FAILURE;
|
|
}
|
|
case CLOSE: { // free the local storage
|
|
|
|
map<int, Periods*>* msetElems= static_cast<map<int, Periods*>*>(local.addr);
|
|
map<int, Periods*>::iterator msetElemsIt= msetElems->begin();
|
|
for(; msetElemsIt != msetElems->end(); ++msetElemsIt)
|
|
delete (*msetElemsIt).second;
|
|
delete msetElems;
|
|
result.addr=0;
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct USet2MPointsLocalInfo
|
|
{
|
|
public:
|
|
Periods usetPeriods;
|
|
set<int> ids;
|
|
bool restrictMPoints;
|
|
USet2MPointsLocalInfo(USet* uset, bool r):usetPeriods(0), restrictMPoints(r)
|
|
{
|
|
usetPeriods.Add(uset->timeInterval);
|
|
for(int i=0; i<uset->constValue.Count(); ++i)
|
|
ids.insert(uset->constValue[i]);
|
|
}
|
|
};
|
|
|
|
int
|
|
USet2MPointsVM(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
|
|
//bool debugme=false;
|
|
|
|
switch( message )
|
|
{
|
|
case OPEN: {
|
|
Word Value;
|
|
Supplier arg1= qp->GetSon(s,1);
|
|
Supplier arg2= qp->GetSon(s,2);
|
|
qp->Request(arg1, Value);
|
|
USet* uset= static_cast<USet*>(Value.addr);
|
|
qp->Request(arg2, Value);
|
|
bool restrictMPoints= static_cast<CcBool*>(Value.addr)->GetBoolval();
|
|
USet2MPointsLocalInfo* localinfo=
|
|
new USet2MPointsLocalInfo(uset, restrictMPoints);
|
|
local.setAddr(localinfo);
|
|
qp->Open( args[0].addr );
|
|
return 0;
|
|
}
|
|
case REQUEST: { // return the next stream element
|
|
Word Value;
|
|
USet2MPointsLocalInfo* localinfo=
|
|
static_cast<USet2MPointsLocalInfo*>(local.addr);
|
|
if(localinfo->ids.empty())
|
|
return CANCEL;
|
|
|
|
qp->Request(args[0].addr, Value);
|
|
while(qp->Received(args[0].addr))
|
|
{
|
|
Tuple* tuple= static_cast<Tuple*>(Value.addr);
|
|
int idFromTuple=
|
|
dynamic_cast<CcInt*>(tuple->GetAttribute(0))->GetIntval();
|
|
if(localinfo->ids.find(idFromTuple) != localinfo->ids.end())
|
|
{
|
|
MPoint* res= new MPoint(0);
|
|
if(localinfo->restrictMPoints)
|
|
{
|
|
MPoint* tmp = dynamic_cast<MPoint*>(tuple->GetAttribute(1));
|
|
tmp->AtPeriods(localinfo->usetPeriods, *res);
|
|
}
|
|
else
|
|
{
|
|
MPoint* tmp = dynamic_cast<MPoint*>(tuple->GetAttribute(1));
|
|
res->CopyFrom(tmp);
|
|
}
|
|
localinfo->ids.erase(idFromTuple);
|
|
result= SetWord(res);
|
|
return YIELD;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
qp->Request(args[0].addr, Value);
|
|
}
|
|
|
|
cerr<<"operator members: some uset elements are not found in "
|
|
"the stream";
|
|
return FAILURE;
|
|
}
|
|
case CLOSE: { // free the local storage
|
|
USet2MPointsLocalInfo* localinfo=
|
|
static_cast<USet2MPointsLocalInfo*>(local.addr);
|
|
delete localinfo;
|
|
qp->Close(args[0].addr);
|
|
result.addr=0;
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ISet2PointsVM(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
Word Value;
|
|
Supplier arg1= qp->GetSon(s,1);
|
|
qp->Request(arg1, Value);
|
|
ISet* iset= static_cast<ISet*>(Value.addr);
|
|
set<int> ids;
|
|
for(int i=0; i<iset->value.Count(); ++i)
|
|
ids.insert(iset->value[i]);
|
|
Intime<Point> pt(0);
|
|
result = qp->ResultStorage(s);
|
|
Points* res = static_cast<Points*>( result.addr);
|
|
res->Clear();
|
|
qp->Request(args[0].addr, Value);
|
|
while(qp->Received(args[0].addr))
|
|
{
|
|
Tuple* tuple= static_cast<Tuple*>(Value.addr);
|
|
int idFromTuple=
|
|
dynamic_cast<CcInt*>(tuple->GetAttribute(0))->GetIntval();
|
|
if(ids.find(idFromTuple) != ids.end())
|
|
{
|
|
MPoint* tmp = dynamic_cast<MPoint*>(tuple->GetAttribute(1));
|
|
tmp->AtInstant(iset->instant, pt);
|
|
if(pt.IsDefined())
|
|
(*res) +=pt.value;
|
|
ids.erase(idFromTuple);
|
|
tuple->DeleteIfAllowed();
|
|
qp->Request(args[0].addr, Value);
|
|
}
|
|
}
|
|
qp->Close(args[0].addr);
|
|
if(! ids.empty())
|
|
{
|
|
cerr<<"operator members: some iset elements are not found in the stream";
|
|
return FAILURE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
ValueMapping BoundingRegionVMMap[] = {
|
|
MSet2MRegionVM,
|
|
USet2MRegionVM,
|
|
ISet2RegionVM};
|
|
|
|
ValueMapping MembersVMMap[] = {
|
|
MSet2MPointsVM,
|
|
USet2MPointsVM,
|
|
ISet2PointsVM
|
|
};
|
|
|
|
template<int argIndex>
|
|
int MUISetSelect( ListExpr args )
|
|
{
|
|
ListExpr arg = nl->Nth(argIndex + 1, args );
|
|
|
|
if (nl->IsAtom( arg ) )
|
|
{
|
|
if( nl->SymbolValue( arg ) == MSet::BasicType() )
|
|
return 0;
|
|
else if( nl->SymbolValue( arg ) == USet::BasicType() )
|
|
return 1;
|
|
else if( nl->SymbolValue( arg ) == ISet::BasicType() )
|
|
return 2;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
int
|
|
ConvexHullVM(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
//bool debugme= false;
|
|
Word Value;
|
|
MPoint* mp=0;
|
|
Instant* instant=0;
|
|
vector<MPoint*> stream(0);
|
|
result = qp->ResultStorage(s);
|
|
|
|
qp->Open(args[0].addr);
|
|
qp->Request(args[0].addr,Value);
|
|
while (qp->Received(args[0].addr))
|
|
{
|
|
mp = static_cast<MPoint*>(Value.addr);
|
|
stream.push_back(mp);
|
|
qp->Request(args[0].addr, Value);
|
|
}
|
|
Supplier arg1= qp->GetSon(s,1);
|
|
qp->Request(arg1, Value);
|
|
instant= static_cast<Instant*>(Value.addr);
|
|
|
|
Points ps(0);
|
|
MPointsSample(*instant, stream, ps, true);
|
|
Region* reg=static_cast<Region*>(result.addr);
|
|
reg->Clear();
|
|
GrahamScan::convexHull(&ps, reg);
|
|
qp->Close(args[0].addr);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
IntersectsVM(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
bool debugme= false;
|
|
Word Value;
|
|
IntSet *arg1= static_cast<IntSet*>(args[0].addr),
|
|
*arg2= static_cast<IntSet*>(args[1].addr);
|
|
result = qp->ResultStorage(s);
|
|
CcBool* res= static_cast<CcBool*>(result.addr);
|
|
|
|
bool intersects = arg1->Intersects(*arg2);
|
|
if(debugme)
|
|
{
|
|
cerr<< "\nInside intersects\n arg1:";
|
|
arg1->Print(cerr);
|
|
cerr<<"\narg2:";
|
|
arg2->Print(cerr);
|
|
cerr<<"\nresult: "<<intersects;
|
|
}
|
|
res->Set(true, intersects);
|
|
return 0;
|
|
}
|
|
|
|
// the_unit for uset:
|
|
// intset instant instant bool bool -> uT
|
|
int TheUnitVM(Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
result = (qp->ResultStorage( s ));
|
|
USet *res = static_cast<USet *>(result.addr);
|
|
IntSet *value = static_cast<IntSet*>(args[0].addr);
|
|
Instant *i1 = static_cast<DateTime*>(args[1].addr);
|
|
Instant *i2 = static_cast<DateTime*>(args[2].addr);
|
|
CcBool *cl = static_cast<CcBool*>(args[3].addr);
|
|
CcBool *cr = static_cast<CcBool*>(args[4].addr);
|
|
bool clb, crb;
|
|
|
|
// Test arguments for definedness
|
|
if ( !value->IsDefined() ||
|
|
!i1->IsDefined() || !i2->IsDefined() ||
|
|
!cl->IsDefined() || !cr->IsDefined() ) {
|
|
res->SetDefined( false );
|
|
return 0;
|
|
}
|
|
|
|
clb = cl->GetBoolval();
|
|
crb = cr->GetBoolval();
|
|
|
|
if ( ( (*i1 == *i2) && (!clb || !crb) ) ||
|
|
( i1->Adjacent(i2) && !(clb || crb) ) ) { // illegal interval setting
|
|
res->SetDefined( false );
|
|
return 0;
|
|
}
|
|
if ( *i1 < *i2 ) {// sort instants
|
|
Interval<Instant> interval( *i1, *i2, clb, crb );
|
|
res = new USet( interval, *value );
|
|
result= SetWord(res);
|
|
} else {
|
|
Interval<Instant> interval( *i2, *i1, clb, crb );
|
|
res = new USet( interval, *value );
|
|
result= SetWord(res);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int TheMValueVM(Word* args,Word& result,int message,
|
|
Word& local,Supplier s)
|
|
{
|
|
Word currentUnit;
|
|
USet* unit;
|
|
|
|
qp->Open(args[0].addr);
|
|
qp->Request(args[0].addr, currentUnit);
|
|
|
|
result = qp->ResultStorage(s);
|
|
MSet* m = static_cast<MSet*>(result.addr);
|
|
m->Clear();
|
|
m->SetDefined( true );
|
|
|
|
m->StartBulkLoad();
|
|
|
|
while ( qp->Received(args[0].addr) ) { // get all tuples
|
|
unit = static_cast<USet*>(currentUnit.addr);
|
|
if(unit == 0) {
|
|
cout << endl << __PRETTY_FUNCTION__ << ": Received Nullpointer!"
|
|
<< endl;
|
|
assert( false );
|
|
} else if(unit->IsDefined()) {
|
|
m->MergeAdd( *unit );
|
|
} else {
|
|
cerr << endl << __PRETTY_FUNCTION__ << ": Dropping undef unit "
|
|
<< endl;
|
|
}
|
|
unit->DeleteIfAllowed();
|
|
qp->Request(args[0].addr, currentUnit);
|
|
}
|
|
m->EndBulkLoad( true, true ); // force Mapping to sort the units
|
|
qp->Close(args[0].addr); // and mark invalid Mapping as undefined
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int CollectIntSetValueMap(
|
|
Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
result = qp->ResultStorage(s);
|
|
IntSet* resColl = static_cast<IntSet*>(result.addr);
|
|
resColl->Clear();
|
|
resColl->SetDefined(true);
|
|
CcInt* elemToInsert;
|
|
Word elem = SetWord(Address(0));
|
|
|
|
qp->Open(args[0].addr);
|
|
qp->Request(args[0].addr, elem);
|
|
|
|
while ( qp->Received(args[0].addr) )
|
|
{
|
|
elemToInsert = static_cast<CcInt*>(elem.addr);
|
|
resColl->Insert(elemToInsert->GetIntval());
|
|
//elemToInsert->DeleteIfAllowed();
|
|
qp->Request(args[0].addr, elem);
|
|
}
|
|
qp->Close(args[0].addr);
|
|
return 0;
|
|
}
|
|
|
|
int NoComponentsVM(
|
|
Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
MSet* m = ((MSet*)args[0].addr);
|
|
if( m->IsDefined() ){
|
|
((CcInt*)result.addr)->Set( true,
|
|
((MSet*)args[0].addr)->GetNoComponents() );
|
|
} else {
|
|
((CcInt*)result.addr)->Set( false, 0 );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int SmoothVM(
|
|
Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
MBool* m = static_cast<MBool*>(args[0].addr);
|
|
Instant* d= static_cast<Instant*>(args[1].addr);
|
|
MBool* res = static_cast<MBool*>(result.addr);
|
|
UBool ubool(0);
|
|
res->Clear();
|
|
if( !m->IsDefined() || !d->IsDefined() )
|
|
res->SetDefined(false);
|
|
else
|
|
{
|
|
for(int i=0; i < m->GetNoComponents(); ++i)
|
|
{
|
|
m->Get(i, ubool);
|
|
if(! ubool.constValue.GetValue() &&
|
|
(ubool.timeInterval.end - ubool.timeInterval.start) < (*d))
|
|
ubool.constValue.Set(true, true);
|
|
res->MergeAdd(ubool);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct GBoidLocalInfo
|
|
{
|
|
GBoidLocalInfo(BoidGenerator* bg, TupleType* tt):
|
|
BGenerator(bg), resType(tt){}
|
|
BoidGenerator* BGenerator;
|
|
TupleType* resType;
|
|
};
|
|
|
|
int GBoidsVM(
|
|
Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
//bool debugme= false;
|
|
switch( message )
|
|
{
|
|
case OPEN:
|
|
{
|
|
Word value;
|
|
collection::Collection* BoidSizes=
|
|
static_cast<collection::Collection*>(args[0].addr);
|
|
collection::Collection* Obstacles=
|
|
static_cast<collection::Collection*>(args[1].addr);
|
|
Instant* SimulationStartTime= static_cast<Instant*>(args[2].addr);
|
|
Instant* SimulationDuration= static_cast<Instant*>(args[3].addr);
|
|
|
|
vector<int> boidSizes;
|
|
for(int i=0; i< BoidSizes->GetNoComponents(); ++i)
|
|
{
|
|
CcInt* elem= static_cast<CcInt*>(BoidSizes->GetComponent(i));
|
|
boidSizes.push_back(elem->GetIntval());
|
|
delete elem;
|
|
}
|
|
vector<double> obstacles;
|
|
for(int i=0; i< Obstacles->GetNoComponents(); ++i)
|
|
{
|
|
CcReal* elem= static_cast<CcReal*>(Obstacles->GetComponent(i));
|
|
obstacles.push_back(elem->GetRealval());
|
|
delete elem;
|
|
}
|
|
|
|
BoidGenerator* BGenerator= new BoidGenerator( boidSizes,
|
|
obstacles, SimulationStartTime, SimulationDuration);
|
|
|
|
TupleType* resType = new TupleType(nl->Second(GetTupleResultType(s)));
|
|
GBoidLocalInfo* li= new GBoidLocalInfo(BGenerator, resType);
|
|
local.setAddr(li);
|
|
return 0;
|
|
}
|
|
case REQUEST:
|
|
{ // return the next stream element
|
|
GBoidLocalInfo* li= static_cast<GBoidLocalInfo*>(local.addr);
|
|
BoidGenerator* BGenerator= li->BGenerator;
|
|
result = qp->ResultStorage( s );
|
|
CcInt* BoidID;
|
|
CcReal* X, *Y;
|
|
int boidID;
|
|
double x, y;
|
|
DateTime SampleTime(0, 0, durationtype);
|
|
if ( BGenerator->GetNext(boidID, SampleTime, x, y) != -1)
|
|
{
|
|
DateTime* sampleTime= new DateTime(SampleTime);
|
|
BoidID= new CcInt(true, boidID);
|
|
X= new CcReal(true, x);
|
|
Y= new CcReal(true, y);
|
|
Tuple* res= new Tuple(li->resType);
|
|
res->PutAttribute(0, (Attribute*)BoidID);
|
|
res->PutAttribute(1, (Attribute*)sampleTime);
|
|
res->PutAttribute(2, (Attribute*)X);
|
|
res->PutAttribute(3, (Attribute*)Y);
|
|
result= SetWord(res);
|
|
return YIELD;
|
|
}
|
|
else
|
|
{
|
|
// you should always set the result to null
|
|
// before you return a CANCEL
|
|
result.addr = 0;
|
|
return CANCEL;
|
|
}
|
|
|
|
}
|
|
case CLOSE: { // free the local storage
|
|
GBoidLocalInfo* li= static_cast<GBoidLocalInfo*>(local.addr);
|
|
delete li->BGenerator;
|
|
delete li->resType;
|
|
delete li;
|
|
local.addr = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int DefTimeUSet( Word* args, Word& result, int message,
|
|
Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
Periods* r = ((Periods*) result.addr);
|
|
USet* m = ((USet*) args[0].addr);
|
|
|
|
r->Clear();
|
|
if ( !m->IsDefined() )
|
|
r->SetDefined( false );
|
|
else
|
|
{
|
|
r->SetDefined( true );
|
|
r->StartBulkLoad();
|
|
r->Add( m->timeInterval );
|
|
r->EndBulkLoad( false );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
ValueMapping DeftimeVMMap[] = {
|
|
MappingDefTime<MSet>,
|
|
DefTimeUSet};
|
|
|
|
template<int argIndex>
|
|
int MUSetSelect( ListExpr args )
|
|
{
|
|
ListExpr arg = nl->Nth(argIndex + 1, args );
|
|
|
|
if (nl->IsAtom( arg ) )
|
|
{
|
|
if( nl->SymbolValue( arg ) == MSet::BasicType() )
|
|
return 0;
|
|
else if( nl->SymbolValue( arg ) == USet::BasicType() )
|
|
return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
struct ComponentsLocalInfo
|
|
{
|
|
IntSet* theset; // the address of the moving point/int/real value
|
|
int elemIndex; // current item index
|
|
};
|
|
|
|
int ComponentsVM(Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
ComponentsLocalInfo* localinfo;
|
|
switch( message )
|
|
{
|
|
case OPEN:
|
|
localinfo = new ComponentsLocalInfo();
|
|
localinfo->theset = static_cast<IntSet*>(args[0].addr);
|
|
if(localinfo->theset->IsDefined()){
|
|
localinfo->elemIndex = 0;
|
|
local = SetWord(localinfo);
|
|
} else {
|
|
local.setAddr( 0 );
|
|
}
|
|
return 0;
|
|
|
|
case REQUEST:
|
|
|
|
if( local.addr == 0 )
|
|
return CANCEL;
|
|
localinfo = static_cast<ComponentsLocalInfo *>(local.addr);
|
|
int elem;
|
|
if( (0 <= localinfo->elemIndex)
|
|
&& (localinfo->elemIndex < localinfo->theset->Count()) )
|
|
{
|
|
elem= (*(localinfo->theset))[localinfo->elemIndex];
|
|
++localinfo->elemIndex;
|
|
CcInt* res= new CcInt(true, elem);
|
|
result.setAddr(res);
|
|
return YIELD;
|
|
}
|
|
return CANCEL;
|
|
|
|
case CLOSE:
|
|
if( local.addr != 0 )
|
|
{
|
|
delete (ComponentsLocalInfo *)local.addr;
|
|
local = SetWord(Address(0));
|
|
}
|
|
return 0;
|
|
}
|
|
// should not happen
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
Operator properties
|
|
|
|
*/
|
|
|
|
const string RowColSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text>tuple(x) X namedFunlist X constraintList X bool -> bool</text--->"
|
|
"<text>_ reportpattern[ namedFunlist; constraintList; bool ]</text--->"
|
|
"<text>The operator implements the Extended Spatiotemporal Pattern "
|
|
"Predicate.</text--->"
|
|
"<text>query Trains feed filter[. reportpattern[a: .Trip inside msnow, "
|
|
"b: distance(.Trip, mehringdamm)<10.0, c: speed(.Trip)>8.0 ; "
|
|
"stconstraint(\"a\",\"b\",vec(\"aabb\")), "
|
|
"stconstraint(\"b\",\"c\",vec(\"bbaa\")); (end(\"b\") - start(\"a\")) < "
|
|
"[const duration value (1 0)] ]] count </text--->"
|
|
") )";
|
|
|
|
const string CrossPatternSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text>tuple(x) X namedFunlist X constraintList X bool -> bool</text--->"
|
|
"<text>_ reportpattern[ namedFunlist; constraintList; bool ]</text--->"
|
|
"<text>The operator implements the Extended Spatiotemporal Pattern "
|
|
"Predicate.</text--->"
|
|
"<text>query Trains feed filter[. reportpattern[a: .Trip inside msnow, "
|
|
"b: distance(.Trip, mehringdamm)<10.0, c: speed(.Trip)>8.0 ; "
|
|
"stconstraint(\"a\",\"b\",vec(\"aabb\")), "
|
|
"stconstraint(\"b\",\"c\",vec(\"bbaa\")); (end(\"b\") - start(\"a\")) < "
|
|
"[const duration value (1 0)] ]] count </text--->"
|
|
") )";
|
|
|
|
const string GPatternSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text>tuple(x) X namedFunlist X constraintList X bool -> bool</text--->"
|
|
"<text>_ reportpattern[ namedFunlist; constraintList; bool ]</text--->"
|
|
"<text>The operator implements the Extended Spatiotemporal Pattern "
|
|
"Predicate.</text--->"
|
|
"<text>query Trains feed filter[. reportpattern[a: .Trip inside msnow, "
|
|
"b: distance(.Trip, mehringdamm)<10.0, c: speed(.Trip)>8.0 ; "
|
|
"stconstraint(\"a\",\"b\",vec(\"aabb\")), "
|
|
"stconstraint(\"b\",\"c\",vec(\"bbaa\")); (end(\"b\") - start(\"a\")) < "
|
|
"[const duration value (1 0)] ]] count </text--->"
|
|
") )";
|
|
|
|
const string ReportPatternSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text>tuple(x) X namedFunlist X constraintList X bool -> bool</text--->"
|
|
"<text>_ reportpattern[ namedFunlist; constraintList; bool ]</text--->"
|
|
"<text>The operator implements the Extended Spatiotemporal Pattern "
|
|
"Predicate.</text--->"
|
|
"<text>query Trains feed filter[. reportpattern[a: .Trip inside msnow, "
|
|
"b: distance(.Trip, mehringdamm)<10.0, c: speed(.Trip)>8.0 ; "
|
|
"stconstraint(\"a\",\"b\",vec(\"aabb\")), "
|
|
"stconstraint(\"b\",\"c\",vec(\"bbaa\")); (end(\"b\") - start(\"a\")) < "
|
|
"[const duration value (1 0)] ]] count </text--->"
|
|
") )";
|
|
|
|
const string CreateIntSetSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text>stream(tuple(.)) X symbol -> elemset</text--->"
|
|
"<text>_ intstream2set(_)</text--->"
|
|
"<text>The operator collects the values of a stream int attribute into "
|
|
"a set.</text--->"
|
|
"<text>query ten feed intstream2set[no] consume</text--->"
|
|
") )";
|
|
|
|
const string EmptyMSetSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> -> mset</text--->"
|
|
"<text>_ emptymset()</text--->"
|
|
"<text>The operator creates an empty mset (i.e. an mset with zero units)."
|
|
"</text--->"
|
|
"<text>query emptymset()"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string MBool2MSetSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mbool x int -> mset</text--->"
|
|
"<text>_ mbool2mset(_)</text--->"
|
|
"<text>The operator creates an mset representation for the given mbool. "
|
|
"For every true unit in the mbool argument, a corresponding uset is added "
|
|
"to the result. The set within the uset will have one element, the int "
|
|
"argument. The operator is used within the GPattern operator."
|
|
"</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) nocomponents"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string UnionSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset x mset -> mset, intset x intset -> intset</text--->"
|
|
"<text>_ union _</text--->"
|
|
"<text>The operator is a lifted union for msets."
|
|
"</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) union emptymset() nocomponents"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string IntersectsIntSetSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> intset x intset -> bool</text--->"
|
|
"<text>_ intersects _</text--->"
|
|
"<text>The predicate yields true of the intersection of the two sets is "
|
|
"non-empty.</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) union emptymset() nocomponents"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string Union2MSetSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset x mset -> mset</text--->"
|
|
"<text>_ union2 _</text--->"
|
|
"<text>The operator is a lifted union for msets. Unlike union, this operator "
|
|
"treats undefined intervals as empty msets."
|
|
"</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) union emptymset() nocomponents"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string MinusSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset x mset -> mset, intset x intset -> intset</text--->"
|
|
"<text>_ - _</text--->"
|
|
"<text>Computes the set difference.</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) union emptymset() nocomponents"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string EqualsSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset x mset -> bool, intset x intset -> bool</text--->"
|
|
"<text>_ = _, _ # _</text--->"
|
|
"<text>Checks the two operands for equality.</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) union emptymset() nocomponents"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string IsSubsetSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset x mset -> mbool</text--->"
|
|
"<text>_ issubset _</text--->"
|
|
"<text>The operator is a lifted issubset for msets. It yields an mbool which "
|
|
"is undefined whenever any of the two operands is undefined, true whenever "
|
|
"the first operand is a subset of the second operand, and flase otherwise."
|
|
"</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) issubset emptymset() nocomponents"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string ValSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
|
"( <text>iT -> x</text--->"
|
|
"<text>val ( _ )</text--->"
|
|
"<text>Return an intime value's value.</text--->"
|
|
"<text>val ( i1 )</text--->"
|
|
") )";
|
|
|
|
const string InstSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
|
"( <text>iT -> instant</text--->"
|
|
"<text>inst ( _ )</text--->"
|
|
"<text>Return an intime instant's value.</text--->"
|
|
"<text>inst ( i1 )</text--->"
|
|
") )";
|
|
|
|
const string UnitsSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset -> stream(uset)</text--->"
|
|
"<text> units(_) </text--->"
|
|
"<text>The operator create the stream of all usets contained in the mset."
|
|
"</text---> <text>query units(speed(train7)>15 mbool2mset(7)) count"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string InitFinSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
|
"( <text>(uset) -> iset, (mset) -> iset</text--->"
|
|
"<text>initial( _ ), final( _ )</text--->"
|
|
"<text>From an mset or uset, get the intime value corresponding to the "
|
|
"(overall) initial/final instant.</text--->"
|
|
"<text>initial( uset1 )</text---> ) )";
|
|
|
|
const string CardinalitySpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset -> mint</text--->"
|
|
"<text>_ cardinality</text--->"
|
|
"<text>The operator is the lifted count/cardinality for the msets."
|
|
"</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) cardinality max"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string MembersSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset -> mint</text--->"
|
|
"<text>_ cardinality</text--->"
|
|
"<text>The operator is the lifted count/cardinality for the msets."
|
|
"</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) cardinality max"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string ConvexHullSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> mset -> mint</text--->"
|
|
"<text>_ cardinality</text--->"
|
|
"<text>The operator is the lifted count/cardinality for the msets."
|
|
"</text--->"
|
|
"<text>query speed(train7)>15 mbool2mset(7) cardinality max"
|
|
"</text--->"
|
|
") )";
|
|
|
|
|
|
const string BoundingRegionSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( <text> stream(tuple(int mpoint)) x mset x duration -> mregion,\n"
|
|
"stream(tuple(int mpoint)) x uset x duration -> mregion,\n"
|
|
"stream(tuple(int mpoint)) x iset -> region</text--->"
|
|
"<text>Trains feed addcounter[Cnt, 1] project[Cnt, Trip] Flocks feed "
|
|
"boundingregion[create_duration(0, 10000)]</text--->"
|
|
"<text>Creates the bounding region/mregion of the group of moving points "
|
|
"whoes identifiers are within the mset/uset/iset. The resulting "
|
|
"region/mregion is the interpolation of the convex hulls of mpoint positions "
|
|
"sampled at time intervals of 'duration'. The initial and final time "
|
|
"instants of the mset/uset are included in the samples. If the number of "
|
|
"elems in the mset/uset/iset is ever below 3, the result is undefined. If "
|
|
"the mset contains definition gaps, the result is undefined.</text--->"
|
|
"<text>query Trains feed addcounter[Cnt, 1] project[Cnt, Trip] Flocks feed "
|
|
"mflocks2mregions[create_duration(0, 10000)] consume</text--->"
|
|
") )";
|
|
|
|
|
|
const string TheUnitSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"("
|
|
"<text>intset x instant x instant x bool x bool --> uset\n</text--->"
|
|
"<text>the_unit( set, tstart, tend, cl, cr )\n </text--->"
|
|
"<text>Creates a unit value from the argument list. The instants/ipoints"
|
|
"/(point/instant)-pairs will be sorted automatically.</text--->"
|
|
"<text>query the_unit(intstream(1,5) collectintset, create_instant(10,10), "
|
|
"create_instant(100, 100), FALSE, TRUE)</text--->) )";
|
|
|
|
const string TheMValueSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
|
"( <text>(stream uset) -> mset\n</text--->"
|
|
"<text>_ the_mvalue</text--->"
|
|
"<text>Create a moving object from a (not necessarily sorted) "
|
|
"object stream containing units. "
|
|
"No two unit timeintervals may overlap. Undefined units are "
|
|
"allowed and will be ignored. A stream with less than 1 defined "
|
|
"unit will result in an 'empty' moving object, not in an 'undef'.</text--->"
|
|
"<text>query units(zug5) the_mvalue</text---> ) )";
|
|
|
|
const string NoComponentsSpec =
|
|
"( ( \"Signature\" \"Syntax\"\"Meaning\" \"Example\" ) "
|
|
"( <text>mset -> int</text--->"
|
|
"<text>no_components ( _ )</text--->"
|
|
"<text>Number of units inside a moving object value. "
|
|
"UNDEFINED argument yields an UNDEFINED result.</text--->"
|
|
"<text>no_components ( mset1 )</text--->"
|
|
") )";
|
|
|
|
const string SmoothSpec =
|
|
"( ( \"Signature\" \"Syntax\"\"Meaning\" \"Example\" ) "
|
|
"( <text>mbool x duration -> mbool</text--->"
|
|
"<text>smooth ( _ , _ )</text--->"
|
|
"<text>Convert all false units that are shorter than the givien duration "
|
|
"into true. This function is helpful to smooth short non-fulfillments of "
|
|
"time-dependent predicates.</text--->"
|
|
"<text>smooth ( speed(train7) > 22.0, duration(0, 300000) )</text--->"
|
|
") )";
|
|
|
|
const string GBoidsSpec =
|
|
"( ( \"Signature\" \"Syntax\"\"Meaning\" \"Example\" ) "
|
|
"( <text>(vector int) x (vector real) x instant x duration"
|
|
" -> stream(tuple((BoidID int)(T instant)(X real)(Y real)))</text--->"
|
|
"<text>generateboids(group sizes, number of freely moving boids, "
|
|
"obstacles, the rect defining the world, simulation start time, "
|
|
"simulation period)</text--->"
|
|
"<text>The operator uses the source code provided by Christopher John Kline "
|
|
"for creating boids. Boids are bird-like objects. "
|
|
"Originally the code generates "
|
|
"3D coordinates. The operator, however, yields the X, Y only. You can create "
|
|
"several groups of boids, where every group try to flock together. The "
|
|
"first argument is a vector that specifies the sizes of these groups. The "
|
|
"first entry in this vector is mandatory, and it specifies the number of "
|
|
"freely moving boids (i.e., boids that move in the background without "
|
|
"flocking). The second argument is a vector that specifies the obstacles "
|
|
"that boids are required to avoid. Obstacles are described as circles, "
|
|
"where every circle is described as x-coord of the center, y-coord of the "
|
|
"center, raduis in meters. The number of reals within this vector must be "
|
|
"a multiple of 3. The first three reals are mandatory and they describe the "
|
|
"world. Boids will respect this world while flying, and should never cross "
|
|
"its boundaries. The third argument is used as the initial time instant in "
|
|
"the generated samples. There is one sample per boids per 5 seconds. The "
|
|
"last argument specifies the simulation duration. The operator return a "
|
|
"stream of (BoidID, T, X, Y) tuples, each of which is representing a single "
|
|
"boid observation. This can be used in combination with other SECONDO "
|
|
"operators to generate the boid trajectories.</text--->"
|
|
"<text>query generateboids("
|
|
"create_vector(40, 15, 15), "
|
|
"create_vector(1000.0,-3000.0, 20000.0), "
|
|
"now(), "
|
|
"create_duration(0, 1000000)) "
|
|
"count</text--->) )";
|
|
|
|
const string DeftimeSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
|
"( <text>moving(x) -> periods</text--->"
|
|
"<text>deftime( _ )</text--->"
|
|
"<text>Get the defined time of the corresponding moving data "
|
|
"objects.</text--->"
|
|
"<text>deftime( mp1 )</text--->"
|
|
") )";
|
|
|
|
|
|
const string ComponentsSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
|
"( <text>components(x) -> stream(int)</text--->"
|
|
"<text>components( _ )</text--->"
|
|
"<text>Stream the components of an intset.</text--->"
|
|
"<text>components( iset1 )</text--->"
|
|
") )";
|
|
|
|
struct collectIntSetInfo : OperatorInfo {
|
|
|
|
collectIntSetInfo()
|
|
{
|
|
name = "collectintset";
|
|
signature = "stream(int) -> intset";
|
|
syntax = "_ collectintset";
|
|
meaning = "Collects the stream if integers into a new intset";
|
|
}
|
|
|
|
};
|
|
|
|
Operator crosspattern (
|
|
"crosspattern", //name
|
|
CrossPatternSpec, //specification
|
|
CrossPatternVM, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
CrossPatternTM //type mapping
|
|
);
|
|
|
|
Operator gpattern (
|
|
"gpattern", //name
|
|
GPatternSpec, //specification
|
|
GPatternVM, //value mapping
|
|
Operator::SimpleSelect,
|
|
GPatternTM //type mapping
|
|
);
|
|
|
|
Operator reportpattern (
|
|
"reportpattern", //name
|
|
ReportPatternSpec, //specification
|
|
ReportPatternVM, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
ReportPatternTM //type mapping
|
|
);
|
|
|
|
Operator emptymset (
|
|
"emptymset", //name
|
|
EmptyMSetSpec, //specification
|
|
EmptyMSetVM, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
EmptyMSetTM //type mapping
|
|
);
|
|
|
|
Operator mbool2mset (
|
|
"mbool2mset", //name
|
|
MBool2MSetSpec, //specification
|
|
MBool2MSetVM, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
MBool2MSetTM //type mapping
|
|
);
|
|
|
|
Operator unionmset (
|
|
"union", //name
|
|
UnionSpec, //specification
|
|
2,
|
|
UnionVMMap, //value mapping
|
|
MSSetSelect<0>, //trivial selection function
|
|
UnionTM //type mapping
|
|
);
|
|
|
|
Operator intersects (
|
|
"intersects", //name
|
|
IntersectsIntSetSpec, //specification
|
|
IntersectsVM, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
IntersectsTM //type mapping
|
|
);
|
|
|
|
Operator union2mset (
|
|
"union2", //name
|
|
Union2MSetSpec, //specification
|
|
Union2MSetVM, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
Union2MSetTM //type mapping
|
|
);
|
|
|
|
Operator equals (
|
|
"=", //name
|
|
EqualsSpec, //specification
|
|
2,
|
|
EqualsVMMap, //value mapping
|
|
MSSetSelect<0>, //trivial selection function
|
|
EqualsTM //type mapping
|
|
);
|
|
|
|
Operator nequals (
|
|
"#", //name
|
|
EqualsSpec, //specification
|
|
2,
|
|
NEqualsVMMap, //value mapping
|
|
MSSetSelect<0>, //trivial selection function
|
|
EqualsTM //type mapping
|
|
);
|
|
|
|
Operator minus (
|
|
"-", //name
|
|
MinusSpec, //specification
|
|
2,
|
|
MinusVMMap, //value mapping
|
|
MSSetSelect<0>, //trivial selection function
|
|
MinusTM //type mapping
|
|
);
|
|
|
|
Operator cardinality (
|
|
"cardinality", //name
|
|
CardinalitySpec, //specification
|
|
4,
|
|
CardinalityVMMap, //value mapping
|
|
MUISSetSelect<0>,
|
|
CardinalityTM //type mapping
|
|
);
|
|
|
|
Operator intstream2set (
|
|
"intstream2set", //name
|
|
CreateIntSetSpec, //specification
|
|
CreateAlfaSetVM<CcInt>, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
CreateAlfaSetTM<0> //type mapping
|
|
);
|
|
|
|
|
|
Operator boundingregion (
|
|
"boundingregion", // name
|
|
BoundingRegionSpec, // specification
|
|
3,
|
|
BoundingRegionVMMap, // value mapping
|
|
MUISetSelect<1>, // trivial selection function
|
|
BoundingRegionTM // type mapping
|
|
);
|
|
|
|
Operator members (
|
|
"members", // name
|
|
MembersSpec, // specification
|
|
3,
|
|
MembersVMMap, // value mapping
|
|
MUISetSelect<1>, // trivial selection function
|
|
MembersTM // type mapping
|
|
);
|
|
|
|
Operator convexhull (
|
|
"convexhull2", // name
|
|
ConvexHullSpec, // specification
|
|
ConvexHullVM, // value mapping
|
|
Operator::SimpleSelect, // trivial selection function
|
|
ConvexHullTM // type mapping
|
|
);
|
|
|
|
Operator theunit(
|
|
"the_unit",
|
|
TheUnitSpec,
|
|
TheUnitVM,
|
|
Operator::SimpleSelect,
|
|
TheUnitTM);
|
|
|
|
Operator themvalue(
|
|
"the_mvalue",
|
|
TheMValueSpec,
|
|
TheMValueVM,
|
|
Operator::SimpleSelect,
|
|
TheMValueTM);
|
|
|
|
Operator nocomponents( "no_components",
|
|
NoComponentsSpec,
|
|
NoComponentsVM,
|
|
Operator::SimpleSelect,
|
|
NoComponentsTM);
|
|
|
|
Operator generateboids( "generateboids",
|
|
GBoidsSpec,
|
|
GBoidsVM,
|
|
Operator::SimpleSelect,
|
|
GBoidsTM);
|
|
|
|
Operator issubset ( "issubset", //name
|
|
IsSubsetSpec, //specification
|
|
3,
|
|
IsSubsetVMMap, //value mapping
|
|
MUSSetSelect<0>, //trivial selection function
|
|
IsSubsetTM //type mapping
|
|
);
|
|
|
|
Operator val( "val",
|
|
ValSpec, //specification
|
|
IntimeVal<IntSet>, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
ValTM //type mapping
|
|
);
|
|
|
|
Operator inst( "inst",
|
|
InstSpec, //specification
|
|
IntimeInst<IntSet>, //value mapping
|
|
Operator::SimpleSelect, //trivial selection function
|
|
InstTM //type mapping
|
|
);
|
|
|
|
Operator msetunits("units",
|
|
UnitsSpec,
|
|
UnitsVM,
|
|
Operator::SimpleSelect,
|
|
UnitsTM);
|
|
|
|
Operator init( "initial",
|
|
InitFinSpec,
|
|
2,
|
|
InitVMMap,
|
|
InitFinSelect,
|
|
InitFinTM );
|
|
|
|
Operator final( "final",
|
|
InitFinSpec,
|
|
2,
|
|
FinVMMap,
|
|
InitFinSelect,
|
|
InitFinTM );
|
|
|
|
Operator deftime( "deftime",
|
|
DeftimeSpec,
|
|
2,
|
|
DeftimeVMMap,
|
|
MUSetSelect<0>,
|
|
DeftimeTM );
|
|
|
|
Operator components( "components",
|
|
ComponentsSpec,
|
|
ComponentsVM,
|
|
Operator::SimpleSelect,
|
|
ComponentsTM );
|
|
|
|
Operator smooth( "smooth",
|
|
SmoothSpec,
|
|
SmoothVM,
|
|
Operator::SimpleSelect,
|
|
SmoothTM );
|
|
|
|
|
|
TypeConstructor intSetTC(
|
|
IntSet::BasicType(), //name
|
|
IntSet::Property, //property function describing signature
|
|
IntSet::Out,
|
|
IntSet::In, //Out and In functions
|
|
0, 0, //SaveToList and RestoreFromList functions
|
|
IntSet::Create,
|
|
IntSet::Delete, //object creation and deletion
|
|
0, 0,
|
|
IntSet::Close,
|
|
IntSet::Clone, //object close and clone
|
|
IntSet::Cast, //cast function
|
|
IntSet::SizeOfObj, //sizeof function
|
|
IntSet::KindCheck );
|
|
|
|
TypeConstructor isetTC(
|
|
ISet::BasicType(), //name
|
|
ISet::Property, //property function describing signature
|
|
OutIntime<IntSet, IntSet::Out>,
|
|
InIntime<IntSet, IntSet::In>, //Out and In functions
|
|
0,
|
|
0, //SaveToList and RestoreFromList functions
|
|
ISet::Create,
|
|
ISet::Delete, //object creation and deletion
|
|
0, 0,
|
|
ISet::Close,
|
|
ISet::Clone, //object close and clone
|
|
ISet::Cast, //cast function
|
|
ISet::SizeOf, //sizeof function
|
|
ISet::KindCheck); //kind checking function
|
|
|
|
|
|
TypeConstructor usetTC(
|
|
"uset", //name
|
|
mset::USet::USetProperty, //property function describing signature
|
|
mset::USet::OutUSet,
|
|
mset::USet::InUSet, //Out and In functions
|
|
0, 0, //SaveToList and RestoreFromList functions
|
|
mset::USet::CreateUSet,
|
|
mset::USet::DeleteUSet, //object creation and deletion
|
|
0,0,
|
|
// OpenAttribute<USet>,
|
|
// SaveAttribute<USet>, // object open and save
|
|
mset::USet::CloseUSet,
|
|
mset::USet::CloneUSet, //object close and clone
|
|
mset::USet::CastUSet, //cast function
|
|
mset::USet::SizeOfUSet, //sizeof function
|
|
mset::USet::CheckUSet );
|
|
|
|
TypeConstructor msetTC(
|
|
"mset", //name
|
|
MSet::Property, //property function describing signature
|
|
MSet::OutMSet,
|
|
MSet::InMSet,
|
|
//Out and In functions
|
|
0,
|
|
0, //SaveToList and RestoreFromList functions
|
|
MSet::CreateMSet,
|
|
MSet::DeleteMSet, //object creation and deletion
|
|
0,
|
|
0, // object open and save
|
|
MSet::CloseMSet,
|
|
MSet::CloneMSet, //object close and clone
|
|
MSet::CastMSet, //cast function
|
|
MSet::SizeOfMSet, //sizeof function
|
|
MSet::KindCheck );
|
|
|
|
|
|
|
|
class GPatternAlgebra : public Algebra
|
|
{
|
|
public:
|
|
GPatternAlgebra() : Algebra()
|
|
{
|
|
|
|
AddTypeConstructor( &intSetTC );
|
|
AddTypeConstructor( &isetTC );
|
|
AddTypeConstructor( &usetTC );
|
|
AddTypeConstructor( &msetTC );
|
|
|
|
intSetTC.AssociateKind( Kind::DATA() );
|
|
isetTC.AssociateKind( Kind::TEMPORAL() );
|
|
isetTC.AssociateKind( Kind::DATA() );
|
|
usetTC.AssociateKind( Kind::TEMPORAL() );
|
|
usetTC.AssociateKind( Kind::DATA() );
|
|
msetTC.AssociateKind( Kind::TEMPORAL() );
|
|
msetTC.AssociateKind( Kind::DATA() );
|
|
/*
|
|
The spattern and reportpattern operators are registered as lazy variables.
|
|
|
|
*/
|
|
reportpattern.SetRequestsArguments();
|
|
gpattern.SetRequestsArguments();
|
|
crosspattern.SetRequestsArguments();
|
|
generateboids.SetUsesArgsInTypeMapping();
|
|
|
|
AddOperator(&GPattern::reportpattern);
|
|
AddOperator(&GPattern::emptymset);
|
|
AddOperator(&GPattern::gpattern);
|
|
AddOperator(&GPattern::crosspattern);
|
|
//AddOperator(&intstream2set);
|
|
AddOperator(&emptymset);
|
|
AddOperator(&mbool2mset);
|
|
AddOperator(&unionmset);
|
|
AddOperator(&union2mset);
|
|
AddOperator(&cardinality);
|
|
AddOperator(&boundingregion);
|
|
AddOperator(&members);
|
|
AddOperator(&convexhull);
|
|
AddOperator(&theunit);
|
|
AddOperator(&themvalue );
|
|
AddOperator(collectIntSetInfo(), CollectIntSetValueMap,
|
|
CollectIntSetTypeMap);
|
|
AddOperator(&intersects);
|
|
AddOperator(&nocomponents);
|
|
AddOperator(&generateboids);
|
|
AddOperator(&issubset);
|
|
AddOperator(&msetunits);
|
|
AddOperator(&val);
|
|
AddOperator(&inst);
|
|
AddOperator(&init);
|
|
AddOperator(&final);
|
|
AddOperator(&minus);
|
|
AddOperator(&equals);
|
|
AddOperator(&nequals);
|
|
AddOperator(&deftime);
|
|
AddOperator(&components);
|
|
AddOperator(&smooth);
|
|
|
|
}
|
|
~GPatternAlgebra() {};
|
|
};
|
|
|
|
};
|
|
|
|
/*
|
|
5 Initialization
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern "C"
|
|
Algebra*
|
|
InitializeGPatternAlgebra( NestedList* nlRef,
|
|
QueryProcessor* qpRef )
|
|
{
|
|
// The C++ scope-operator :: must be used to qualify the full name
|
|
return new GPattern::GPatternAlgebra;
|
|
}
|