Files
secondo/Algebras/SymbolicTrajectoryBasic/SymbolicTrajectoryBasicAlgebra.cpp

4997 lines
129 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
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 Symbolic Trajectory Algebra
Started March 2012, Fabio Vald\'{e}s
[TOC]
\section{Overview}
This algebra contains basic types and operations for symbolic trajectories and
has been split from the SymbolicTrajectoryAlgebra in April 2020.
*/
#include "SymbolicTrajectoryBasicAlgebra.h"
#ifdef RECODE
#include <recode.h>
#endif
using namespace std;
using namespace temporalalgebra;
using namespace datetime;
namespace stj {
double BasicDistanceFuns::distance(const string& str1, const string& str2,
const LabelFunction lf /* = TRIVIAL */) {
if (lf == TRIVIAL) {
return (str1 == str2 ? 0.0 : 1.0);
}
if (str1.empty() && str2.empty()) {
return 0.0;
}
if (str1.empty() || str2.empty()) {
return 1.0;
}
double ld = 1.0;
if (lf == EDIT) {
ld = stringutils::ld(str1, str2);
}
return ld / max(str1.length(), str2.length());
}
double BasicDistanceFuns::distance(const pair<string, unsigned int>& val1,
const pair<string, unsigned int>& val2,
const LabelFunction lf /* = TRIVIAL */) {
double ld = BasicDistanceFuns::distance(val1.first, val2.first, lf);
return ld / 2 + (val1.second == val2.second ? 0 : 0.5);
}
double BasicDistanceFuns::distance(const set<string>& values1,
const set<string>& values2, const LabelFunction lf) {
if (values1.empty() && values2.empty()) {
return 0;
}
if (values1.empty() || values2.empty()) {
return 1;
}
set<string>::iterator i1(values1.begin()), i2(values2.begin());
int m(values1.size()), n(values2.size());
double distsum = 0.0;
double dist;
int i1count(0), i2count(0);
while (i1 != values1.end() && i2 != values2.end()) {
dist = BasicDistanceFuns::distance(*i1, *i2, lf);
if (dist < 1) {
// cout << " " << *i1 << " = " << *i2 << endl;
i1++;
i1count++;
i2++;
i2count++;
distsum += dist;
}
else {
if (*i1 < *i2) {
// cout << " " << *i1 << " < " << *i2 << endl;
i1++;
i1count++;
}
else {
// cout << " " << *i1 << " > " << *i2 << endl;
i2++;
i2count++;
}
distsum += 1.0;
}
}
distsum += std::max(m - i1count, n - i2count);
// cout << "distsum = " << distsum << " ";
return distsum / (m + n);
}
double BasicDistanceFuns::distance(set<pair<string, unsigned int> >& values1,
set<pair<string, unsigned int> >& values2,
const LabelFunction lf /* = TRIVIAL */) {
if (values1.empty() && values2.empty()) {
return 0;
}
if (values1.empty() || values2.empty()) {
return 1;
}
set<pair<string, unsigned int> >::iterator i1, i2;
double distsum = 0;
for (i1 = values1.begin(); i1 != values1.end(); i1++) {
for (i2 = values2.begin(); i2 != values2.end(); i2++) {
double dist = BasicDistanceFuns::distance(i1->first, i2->first, lf);
distsum += dist / 2 + (i1->second == i2->second ? 0 : 0.5);
}
}
return distsum / (values1.size() * values2.size());
}
/*
\subsection{Function ~recode~}
*/
#ifdef RECODE
bool RecodeFun::recode(const string &src, const string &from, const string &to,
string &result) {
string rs = trim(from)+".."+trim(to);
// use recode lib
RECODE_OUTER outer = recode_new_outer(true);
RECODE_REQUEST request = recode_new_request(outer);
bool success = recode_scan_request(request, rs.c_str());
if (!success) {
recode_delete_request(request);
recode_delete_outer(outer);
result.clear();
return false;
}
char* recoded = recode_string(request, src.c_str());
// make clean
recode_delete_request(request);
recode_delete_outer(outer);
if (recoded == 0) {
result.clear();
return false;
}
result = recoded;
free(recoded);
return true;
}
#endif
/*
\section{Implementation of class ~Label~}
\subsection{Constructor}
*/
Label::Label(const Label& rhs) : Attribute(rhs.IsDefined()),
value(rhs.value.getSize()) {
CopyFrom(&rhs);
}
/*
\subsection{Function ~GetValue~}
*/
void Label::GetValue(string& text) const {
assert(IsDefined());
if (value.getSize() > 0) {
char *bytes = new char[value.getSize()];
value.read(bytes, value.getSize());
string text2(bytes, value.getSize());
delete[] bytes;
text = text2;
}
else {
text.clear();
}
}
string Label::GetValue() const {
assert(IsDefined());
string result;
GetValue(result);
return result;
}
/*
\subsection{Function ~GetValues~}
*/
void Label::GetValues(set<string>& values) const {
assert(IsDefined());
string value;
GetValue(value);
values.clear();
values.insert(value);
}
/*
\subsection{Function ~buildValue~}
*/
void Label::buildValue(const string& text, const unitelem& unit, base& result) {
result = text;
}
/*
\subsection{Function ~SetValue~}
*/
void Label::SetValue(const string &text) {
Clean();
if (text.length() > 0) {
const char *bytes = text.c_str();
value.write(bytes, text.length());
}
}
/*
\subsection{Operator ~==~}
*/
bool Label::operator==(const Label& lb) const {
if (!IsDefined() && !lb.IsDefined()) {
return true;
}
if (IsDefined() != lb.IsDefined()) {
return false;
}
string str1, str2;
GetValue(str1);
lb.GetValue(str2);
return (str1 == str2);
}
/*
\subsection{Operator ~==~}
*/
bool Label::operator==(const string& text) const {
if (!IsDefined()) {
return false;
}
string str;
GetValue(str);
return (str == text);
}
/*
\subsection{Function ~Distance~}
*/
double Label::Distance(const Label& lb, const LabelFunction lf /* = EDIT */)
const {
if (!IsDefined() && !lb.IsDefined()) {
return 0;
}
string str1, str2;
if (!IsDefined() || !lb.IsDefined()) {
return 1;
}
GetValue(str1);
lb.GetValue(str2);
return BasicDistanceFuns::distance(str1, str2, lf);
}
/*
\subsection{Function ~InsertLabels~}
*/
void Label::InsertLabels(vector<string>& result) const {
if (IsDefined()) {
result.push_back(GetLabel());
}
}
void Label::InsertLabels(set<string>& result) const {
if (IsDefined()) {
result.insert(GetLabel());
}
}
/*
\subsection{Function ~UpdateFrequencies~}
*/
void Label::UpdateFrequencies(InvertedFile& inv, vector<double>& fv) const {
if (IsDefined()) {
InvertedFile::exactIterator* eit = 0;
TupleId id;
uint32_t wc, cc;
eit = inv.getExactIterator(GetLabel(), 16777216);
if (eit->next(id, wc, cc)) {
fv[id] += 1.0;
}
delete eit;
}
}
/*
\subsection{Function ~readValueFrom~}
*/
bool Label::readValueFrom(ListExpr LE, string& text, unitelem& unit) {
if (nl->IsAtom(LE)) {
nl->WriteToString(text, LE);
if (text.length() == 0) {
unit.pos = UINT_MAX;
}
return true;
}
return false;
}
/*
\subsection{Function ~ReadFrom~}
*/
bool Label::ReadFrom(ListExpr LE, ListExpr typeInfo) {
if (listutils::isSymbolUndefined(LE)) {
SetDefined(false);
return true;
}
if (nl->IsAtom(LE)) {
string text;
nl->WriteToString(text, LE);
Set(true, text.substr(1, text.length() - 2));
return true;
}
SetDefined(false);
return false;
}
/*
\subsection{Function ~ToListExpr~}
*/
ListExpr Label::ToListExpr(ListExpr typeInfo) {
if (!IsDefined()) {
return nl->SymbolAtom(Symbol::UNDEFINED());
}
string text;
GetValue(text);
return nl->TextAtom(text);
}
/*
\subsection{Function ~CheckKind~}
*/
bool Label::CheckKind(ListExpr type, ListExpr& errorInfo) {
return (nl->IsEqual(type, Label::BasicType()));
}
/*
\subsection{Function ~Property~}
*/
ListExpr Label::Property() {
return gentc::GenProperty("-> DATA", BasicType(), "(<text>)", "\'Dortmund\'");
}
/*
\subsection{Function ~checkType~}
*/
const bool Label::checkType(const ListExpr type) {
return listutils::isSymbol(type, BasicType());
}
/*
\subsection{Function ~CopyFrom~}
*/
void Label::CopyFrom(const Attribute* right) {
SetDefined(right->IsDefined());
if (IsDefined()) {
string text;
((Label*)right)->GetValue(text);
SetValue(text);
}
}
/*
\subsection{Function ~Compare~}
*/
int Label::Compare(const Attribute* arg) const {
string str1, str2;
GetValue(str1);
((Label*)arg)->GetValue(str2);
return str1.compare(str2);
}
/*
\subsection{Function ~Print~}
*/
ostream& Label::Print(ostream& os) const {
string text;
GetValue(text);
return os << text;
}
/*
\subsection{Operator ~<<~}
*/
ostream& operator<<(ostream& os, const Label& lb) {
string text;
lb.GetValue(text);
os << "\'" << text << "\'";
return os;
}
/*
\section{Implementation of class ~Labels~}
\subsection{Constructors}
*/
Labels::Labels(const Labels& src, const bool sort /* = false */) :
Attribute(src.IsDefined()), values(src.GetLength()), pos(src.GetNoValues()) {
if (sort) {
set<string> labels;
for (int i = 0; i < src.GetNoValues(); i++) {
string text;
src.GetValue(i, text);
labels.insert(text); // automatic sorting
}
for (set<string>::iterator it = labels.begin(); it != labels.end(); it++) {
Append(*it); // append in alphabetical order
}
}
else {
CopyFrom(&src); // keep original order
}
}
/*
\subsection{Operator ~=~}
*/
Labels& Labels::operator=(const Labels& src) {
Attribute::operator=(src);
values.copyFrom(src.values);
pos.copyFrom(src.pos);
return *this;
}
/*
\subsection{Operator ~==~}
*/
bool Labels::operator==(const Labels& src) const {
if (!IsDefined() && !src.IsDefined()) {
return true;
}
if (IsDefined() != src.IsDefined()) {
return false;
}
if ((GetNoValues() != src.GetNoValues()) || (GetLength() != src.GetLength())){
return false;
}
set<string> strings1, strings2;
string str;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, str);
strings1.insert(str);
src.GetValue(i, str);
strings2.insert(str);
}
return strings1 == strings2;
}
/*
\subsection{Functions ~Append~}
*/
void Labels::Append(const Label& lb) {
string text;
lb.GetValue(text);
Append(text);
}
void Labels::Append(const string& text) {
if (!Contains(text)) {
if (text.length() > 0) {
pos.Append(values.getSize());
const char *bytes = text.c_str();
values.write(bytes, text.length(), values.getSize());
}
else {
pos.Append(UINT_MAX);
}
}
}
void Labels::Append(const set<string>& values) {
for (set<string>::iterator it = values.begin(); it != values.end(); it++) {
Append(*it);
}
}
/*
\subsection{Function ~Get~}
*/
void Labels::Get(int i, Label& lb) const {
lb.SetDefined(IsDefined());
assert((0 <= i) && (i < GetNoValues()));
if (IsDefined()) {
string text;
GetValue(i, text);
lb.Set(true, text);
}
}
/*
\subsection{Function ~GetValue~}
*/
void Labels::GetValue(int i, string& text) const {
assert((0 <= i) && (i < GetNoValues()) && IsDefined());
unsigned int cur(-1), next(-1);
pos.Get(i, cur);
if (cur != UINT_MAX) {
int j = i + 1;
bool finished = false;
while (!finished && (j < GetNoValues())) {
pos.Get(j, next);
if (next != UINT_MAX) {
finished = true;
}
j++;
}
if (!finished) {
next = GetLength();
}
char *bytes = new char[next - cur];
values.read(bytes, next - cur, cur);
string text2(bytes, next - cur);
delete[] bytes;
text = text2;
}
else {
text.clear();
}
}
/*
\subsection{Function ~GetValues~}
*/
void Labels::GetValues(set<string>& values) const {
values.clear();
string value;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, value);
values.insert(value);
}
}
/*
\subsection{Function ~getRefToLastElem~}
*/
void Labels::getRefToLastElem(const int size, unsigned int& result) {
result = size;
}
/*
\subsection{Function ~getFlobPos~}
*/
unsigned int Labels::getFlobPos(const arrayelem elem) {
return elem;
}
/*
\subsection{Function ~valuesToListExpr~}
*/
void Labels::valuesToListExpr(const set<string>& values, ListExpr& result) {
if (values.empty()) {
result = nl->Empty();
return;
}
set<string>::iterator it = values.begin();
result = nl->OneElemList(nl->TextAtom(*it));
it++;
ListExpr last = result;
while (it != values.end()) {
last = nl->Append(last, nl->TextAtom(*it));
it++;
}
}
/*
\subsection{Function ~getString~}
*/
void Labels::getString(const ListExpr& list, string& result) {
nl->WriteToString(result, list);
}
/*
\subsection{Function ~getElemFromList~}
*/
void Labels::getElemFromList(const ListExpr& list, const unsigned int size,
unsigned int& result) {
result = size;
}
/*
\subsection{Function ~buildValue~}
*/
void Labels::buildValue(const string& text, const unsigned int pos,
string& result) {
result = text;
}
/*
\subsection{Function ~Contains~}
*/
bool Labels::Contains(const string& text) const {
string str;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, str);
if (str == text) {
return true;
}
}
return false;
}
/*
\subsection{Function ~Intersects~}
*/
bool Labels::Intersects(const Labels &lbs) const {
set<std::string> values1, values2;
GetValues(values1);
lbs.GetValues(values2);
Labels res(true);
res.Intersection(values1, values2);
return !res.IsEmpty();
}
/*
\subsection{Function ~Union~}
*/
void Labels::Union(const set<string>& values1, const set<string>& values2) {
SetDefined(true);
Clean();
Append(values1);
Append(values2);
}
/*
\subsection{Function ~Intersection~}
*/
void Labels::Intersection(const set<string>& values1,
const set<string>& values2) {
SetDefined(true);
Clean();
set<string> intersection;
set_intersection(values1.begin(), values1.end(), values2.begin(),
values2.end(), std::inserter(intersection, intersection.begin()));
Append(intersection);
}
/*
\subsection{Function ~Minus~}
*/
void Labels::Minus(const set<string>& values1, const set<string>& values2) {
SetDefined(true);
Clean();
set<string> difference;
set_difference(values1.begin(), values1.end(), values2.begin(),
values2.end(), std::inserter(difference, difference.begin()));
Append(difference);
}
#ifdef RECODE
/*
\subsection{Function ~Recode~}
*/
bool Labels::Recode(const std::string& from, const std::string& to,
Labels& result) {
result.SetDefined(IsDefined());
if (!IsDefined()) {
return true;
}
result.Clean();
string value, recoded;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, value);
if (!RecodeFun::recode(value, from, to, recoded)) {
result.SetDefined(false);
return false;
}
result.Append(recoded);
}
return true;
}
#endif
/*
\subsection{Operator ~<<~}
*/
ostream& operator<<(ostream& os, const Labels& lbs) {
Label lb(true);
string text;
for (int i = 0; i < lbs.GetNoValues() - 1; i++) {
lbs.GetValue(i, text);
os << text << " ";
}
lbs.GetValue(lbs.GetNoValues() - 1, text);
os << text;
return os;
}
/*
\subsection{Function ~Distance~}
*/
double Labels::Distance(const Labels& lbs, const LabelFunction lf /* = EDIT */)
const {
if (!IsDefined() && !lbs.IsDefined()) {
return 0;
}
set<string> values1, values2;
if (IsDefined()) {
GetValues(values1);
}
if (lbs.IsDefined()) {
lbs.GetValues(values1);
}
return BasicDistanceFuns::distance(values1, values2, lf);
}
/*
\subsection{Function ~InsertLabels~}
*/
void Labels::InsertLabels(vector<string>& result) const {
if (IsDefined()) {
set<std::string> values;
GetValues(values);
for (auto it : values) {
result.push_back(it);
}
}
}
void Labels::InsertLabels(set<string>& result) const {
if (IsDefined()) {
set<std::string> values;
GetValues(values);
result.insert(values.begin(), values.end());
}
}
/*
\subsection{Function ~UpdateFrequencies~}
*/
void Labels::UpdateFrequencies(InvertedFile& inv, vector<double>& fv) const {
if (IsDefined()) {
set<string> values;
GetValues(values);
InvertedFile::exactIterator* eit = 0;
TupleId id;
uint32_t wc, cc;
for (auto label : values) {
eit = inv.getExactIterator(label, 16777216);
if (eit->next(id, wc, cc)) {
fv[id] += 1.0;
}
}
delete eit;
}
}
/*
\subsection{Function ~GetFLOB~}
*/
Flob *Labels::GetFLOB(const int i) {
assert(i >= 0 && i < NumOfFLOBs());
return (i == 0 ? &values : &pos);
}
/*
\subsection{Function ~Compare~}
*/
int Labels::Compare(const Attribute* arg) const {
if (GetNoValues() > ((Labels*)arg)->GetNoValues()) {
return 1;
}
if (GetNoValues() < ((Labels*)arg)->GetNoValues()) {
return -1;
}
string str1, str2;
for (int i = 0; i < GetNoValues(); i++) { // equal size; compare labels
GetValue(i, str1);
((Labels*)arg)->GetValue(i, str2);
int comp = str1.compare(str2);
if (comp != 0) {
return comp;
}
}
return 0;
}
/*
\subsection{Function ~Property~}
*/
ListExpr Labels::Property() {
return gentc::GenProperty("-> DATA", BasicType(), "(<label> <label> ...)",
"(\'Dortmund\' \'Mailand\')");
}
/*
\subsection{Function ~CheckKind~}
*/
bool Labels::CheckKind(ListExpr type, ListExpr& errorInfo) {
return nl->IsEqual(type, Labels::BasicType());
}
/*
\subsection{Function ~ToListExpr~}
*/
ListExpr Labels::ToListExpr(ListExpr typeInfo) {
if (!IsDefined()) {
return nl->SymbolAtom(Symbol::UNDEFINED());
}
if (IsEmpty()) {
return nl->Empty();
}
else {
string text;
GetValue(0, text);
ListExpr res = nl->OneElemList(nl->TextAtom(text));
ListExpr last = res;
for (int i = 1; i < GetNoValues(); i++) {
GetValue(i, text);
last = nl->Append(last, nl->TextAtom(text));
}
return res;
}
}
/*
\subsection{Function ~ReadFrom~}
*/
bool Labels::ReadFrom(ListExpr LE, ListExpr typeInfo) {
Clean();
if (listutils::isSymbolUndefined(LE)) {
SetDefined(false);
return true;
}
SetDefined(true);
string text;
if (nl->IsAtom(LE)) {
text = nl->ToString(LE);
Append(text.substr(1, text.length() - 2));
return true;
}
ListExpr rest = LE;
while (!nl->IsEmpty(rest)) {
if (!nl->IsAtom(nl->First(rest))) {
SetDefined(false);
return false;
}
nl->WriteToString(text, nl->First(rest));
Append(text.substr(1, text.length() - 2));
rest = nl->Rest(rest);
}
return true;
}
/*
\subsection{Function ~HashValue~}
*/
size_t Labels::HashValue() const {
if (IsEmpty()) {
return 0;
}
size_t result = 1;
for (int i = 1; i < pos.Size(); i++) {
unsigned int factor;
pos.Get(i, factor);
result *= factor;
}
return GetNoValues() * result;
}
/*
\section{Implementation of class ~Place~}
\subsection{Function ~Set~}
*/
void Place::Set(const bool defined, const pair<string, unsigned int>& value) {
Label::Set(defined, value.first);
SetRef(value.second);
}
/*
\subsection{Function ~SetValue~}
*/
void Place::SetValue(const pair<string, unsigned int>& value) {
Label::SetValue(value.first);
SetRef(value.second);
}
/*
\subsection{Function ~GetValue~}
*/
void Place::GetValue(pair<string, unsigned int>& value) const {
Label::GetValue(value.first);
value.second = GetRef();
}
/*
\subsection{Function ~GetValues~}
*/
void Place::GetValues(set<pair<string, unsigned int> >& values) const {
assert(IsDefined());
pair<string, unsigned int> value;
GetValue(value);
values.clear();
values.insert(value);
}
/*
\subsection{Function ~buildValue~}
*/
void Place::buildValue(const string& text, const unitelem& unit, base& result) {
result.first = text;
result.second = unit.ref;
}
/*
\subsection{Function ~getList~}
*/
ListExpr Place::getList(const base& value) {
return nl->TwoElemList(nl->TextAtom(value.first), nl->IntAtom(value.second));
}
/*
\subsection{Operator ~=~}
*/
Place& Place::operator=(const Place& p) {
pair<string, unsigned int> value;
p.GetValue(value);
Set(p.IsDefined(), value);
return *this;
}
/*
\subsection{Operator ~==~}
*/
bool Place::operator==(const Place& p) const {
if (!IsDefined() && !p.IsDefined()) { // both undefined
return true;
}
if (IsDefined() != p.IsDefined()) { // one defined, one undefined
return false;
}
pair<string, unsigned int> value;
p.GetValue(value);
return operator==(value);
}
bool Place::operator==(const pair<string, unsigned int>& value) const {
if (!IsDefined()) {
return false;
}
pair<string, unsigned int> val;
GetValue(val);
return (val == value);
}
/*
\subsection{Function ~Distance~}
*/
double Place::Distance(const Place& p, const LabelFunction lf) const {
if (!IsDefined() && !p.IsDefined()) {
return 0;
}
if (!IsDefined() || !p.IsDefined()) {
return Label::Distance(p, lf);
}
pair<string, unsigned int> val1, val2;
GetValue(val1);
p.GetValue(val2);
return BasicDistanceFuns::distance(val1, val2, lf);
}
/*
\subsection{Operator ~<<~}
*/
ostream& operator<<(ostream& os, const Place& pl) {
std::pair<std::string, unsigned int> p;
pl.GetValue(p);
os << "(\'" << p.first << "\'," << p.second << ")";
return os;
}
/*
\subsection{Function ~Property~}
*/
ListExpr Place::Property() {
return gentc::GenProperty("-> DATA", BasicType(), "(<label> <int>)",
"(\'Dortmund\' 1909)");
}
/*
\subsection{Function ~CheckKind~}
*/
bool Place::CheckKind(ListExpr type, ListExpr& errorInfo) {
return nl->IsEqual(type, Place::BasicType());
}
/*
\subsection{Function ~Compare~}
*/
int Place::Compare(const Attribute* arg) const {
int cmp = Label::Compare(arg);
if (cmp != 0) {
return cmp;
}
if (ref > ((Place*)arg)->GetRef()) {
return 1;
}
if (ref < ((Place*)arg)->GetRef()) {
return -1;
}
return 0;
}
/*
\subsection{Function ~ToListExpr~}
*/
ListExpr Place::ToListExpr(ListExpr typeInfo) {
if (!IsDefined()) {
return nl->SymbolAtom(Symbol::UNDEFINED());
}
base val;
GetValue(val);
return nl->TwoElemList(nl->TextAtom(val.first), nl->IntAtom(val.second));
}
/*
\subsection{Function ~readValueFrom~}
*/
bool Place::readValueFrom(ListExpr LE, string& text, unitelem& unit) {
if (nl->HasLength(LE, 2)) {
if (nl->IsAtom(nl->First(LE)) && nl->IsAtom(nl->Second(LE))) {
nl->WriteToString(text, nl->First(LE));
if (text.length() == 0) {
unit.pos = UINT_MAX;
}
unit.ref = nl->IntValue(nl->Second(LE));
return true;
}
}
return false;
}
/*
\subsection{Function ~ReadFrom~}
*/
bool Place::ReadFrom(ListExpr LE, ListExpr typeInfo) {
if (listutils::isSymbolUndefined(LE)) {
SetDefined(false);
return true;
}
if (!nl->HasLength(LE, 2)) {
SetDefined(false);
return false;
}
string text;
nl->WriteToString(text, nl->First(LE));
Set(true, make_pair(text.substr(1, text.length() - 2),
nl->IntValue(nl->Second(LE))));
return true;
}
/*
\section{Implementation of class ~Places~}
\subsection{Constructor}
*/
Places::Places(const Places& rhs, const bool sort /* = false */) :
Attribute(rhs.IsDefined()), values(rhs.GetLength()), posref(rhs.GetNoValues()) {
if (sort) {
set<base> vals;
for (int i = 0; i < rhs.GetNoValues(); i++) {
base val;
rhs.GetValue(i, val);
vals.insert(val); // automatic sorting
}
set<base>::iterator it;
for (it = vals.begin(); it != vals.end(); it++) {
Append(*it); // append in automatic order
}
}
else {
CopyFrom(&rhs); // keep original order
}
}
/*
\subsection{Function ~Append~}
*/
void Places::Append(const base& val) {
if (!Contains(val)) {
NewPair<unsigned int, unsigned int> pr;
pr.first = (val.first.length() > 0 ? values.getSize() : UINT_MAX);
pr.second = val.second;
posref.Append(pr);
if (val.first.length() > 0) {
const char *bytes = val.first.c_str();
values.write(bytes, val.first.length(), values.getSize());
}
}
}
void Places::Append(const Place& pl) {
pair<string, unsigned int> val;
pl.GetValue(val);
Append(val);
}
void Places::Append(const set<base>& values) {
for (set<base>::iterator it = values.begin(); it != values.end(); it++) {
Append(*it);
}
}
/*
\subsection{Function ~GetPlace~}
*/
void Places::Get(const int i, Place& result) const {
assert((0 <= i) && (i < GetNoValues()));
base val;
GetValue(i, val);
result.Set(true, val);
}
/*
\subsection{Function ~GetValue~}
*/
void Places::GetValue(const int i, base& result) const {
assert(IsDefined() && (0 <= i) && (i < GetNoValues()));
NewPair<unsigned int, unsigned int> cur, next;
posref.Get(i, cur);
result.second = cur.second;
if (cur.first != UINT_MAX) {
int j = i + 1;
bool finished = false;
while (!finished && (j < GetNoValues())) {
posref.Get(j, next);
if (next.first != UINT_MAX) {
finished = true;
}
j++;
}
if (!finished) {
next.first = GetLength();
}
char *bytes = new char[next.first - cur.first];
values.read(bytes, next.first - cur.first, cur.first);
string text(bytes, next.first - cur.first);
result.first = text;
delete[] bytes;
}
else {
result.first.clear();
}
}
/*
\subsection{Function ~GetValues~}
*/
void Places::GetValues(set<base>& values) const {
values.clear();
base value;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, value);
values.insert(value);
}
}
/*
\subsection{Function ~Contains~}
*/
bool Places::Contains(const base& val) const {
base value;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, value);
if (value == val) {
return true;
}
}
return false;
}
/*
\subsection{Function ~Intersects~}
*/
bool Places::Intersects(const Places &lbs) const {
set<base> values1, values2;
GetValues(values1);
lbs.GetValues(values2);
Places res(true);
res.Intersection(values1, values2);
return !res.IsEmpty();
}
/*
\subsection{Function ~Union~}
*/
void Places::Union(const set<base>& values1, const set<base>& values2) {
SetDefined(true);
Clean();
Append(values1);
Append(values2);
}
/*
\subsection{Function ~Intersection~}
*/
void Places::Intersection(const set<base>& values1, const set<base>& values2) {
SetDefined(true);
Clean();
set<base> intersection;
set_intersection(values1.begin(), values1.end(), values2.begin(),
values2.end(), std::inserter(intersection, intersection.begin()));
Append(intersection);
}
/*
\subsection{Function ~Minus~}
*/
void Places::Minus(const set<base>& values1, const set<base>& values2) {
SetDefined(true);
Clean();
set<base> difference;
set_difference(values1.begin(), values1.end(), values2.begin(),
values2.end(), std::inserter(difference, difference.begin()));
Append(difference);
}
/*
\subsection{Function ~getRefToLastElem~}
*/
void Places::getRefToLastElem(const int size, arrayelem& result) {
result.first = size;
}
/*
\subsection{Function ~getFlobPos~}
*/
unsigned int Places::getFlobPos(const arrayelem elem) {
return elem.first;
}
/*
\subsection{Function ~valuesToListExpr~}
*/
void Places::valuesToListExpr(const set<base>& values, ListExpr& result) {
if (values.empty()) {
result = nl->Empty();
return;
}
set<base>::iterator it = values.begin();
result = nl->OneElemList(nl->TwoElemList(nl->TextAtom(it->first),
nl->IntAtom(it->second)));
it++;
ListExpr last = result;
while (it != values.end()) {
last = nl->Append(last, nl->TwoElemList(nl->TextAtom(it->first),
nl->IntAtom(it->second)));
it++;
}
}
/*
\subsection{Function ~getString~}
*/
void Places::getString(const ListExpr& list, string& result) {
nl->WriteToString(result, nl->First(list));
}
/*
\subsection{Function ~getElemFromList~}
*/
void Places::getElemFromList(const ListExpr& list, const unsigned int size,
arrayelem& result) {
result.first = size;
result.second = nl->IntValue(nl->Second(list));
}
/*
\subsection{Function ~buildValue~}
*/
void Places::buildValue(const string& text, const arrayelem pos, base& result) {
result.first = text;
result.second = pos.second;
}
/*
\subsection{Operator ~=~}
*/
void Places::operator=(const Places& p) {
SetDefined(p.IsDefined());
if (IsDefined()) {
values.copyFrom(p.values);
posref.copyFrom(p.posref);
}
}
/*
\subsection{Operator ~==~}
*/
bool Places::operator==(const Places& p) const {
if (!IsDefined() && !p.IsDefined()) {
return true;
}
if (IsDefined() != p.IsDefined()) {
return false;
}
if ((GetNoValues() == p.GetNoValues()) && (GetLength() == p.GetLength())) {
base val1, val2;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, val1);
p.GetValue(i, val2);
if (val1 != val2) {
return false;
}
}
return true;
}
return false;
}
/*
\subsection{Function ~Distance~}
*/
double Places::Distance(const Places& p, const LabelFunction lf /* = EDIT */)
const {
if (!IsDefined() && !p.IsDefined()) {
return 0;
}
if (!IsDefined() || !p.IsDefined()) {
return 1;
}
set<pair<string, unsigned int> > values1, values2;
GetValues(values1);
p.GetValues(values2);
// TODO: return Tools::distance(values1, values2) and delete remainder
if (values1.empty() && values2.empty()) {
return 0;
}
if (values1.empty() || values2.empty()) {
return 1;
}
set<pair<string, unsigned int> >::iterator i1, i2;
multiset<double> dist;
for (i1 = values1.begin(); i1 != values1.end(); i1++) {
for (i2 = values2.begin(); i2 != values2.end(); i2++) {
double labelDist = double(stringutils::ld(i1->first, i2->first)) /
max(i1->first.length(), i2->first.length());
dist.insert(labelDist + (i1->second == i2->second ? 0 : 0.5));
}
}
int limit = min(values1.size(), values2.size());
multiset<double>::iterator it = dist.begin();
double sum = 0;
for (int k = 0; k < limit; k++) {
sum += *it;
it++;
}
return (sum / limit + abs((int64_t)values1.size() - (int64_t)values2.size())/
max(values1.size(), values2.size())) / 2;
}
/*
\subsection{Function ~InsertLabels~}
*/
void Places::InsertLabels(vector<string>& result) const {
if (IsDefined()) {
set<base> values;
GetValues(values);
for (auto it : values) {
result.push_back(it.first);
}
}
}
void Places::InsertLabels(set<string>& result) const {
if (IsDefined()) {
set<base> values;
GetValues(values);
for (auto it : values) {
result.insert(it.first);
}
}
}
/*
\subsection{Function ~UpdateFrequencies~}
*/
void Places::UpdateFrequencies(InvertedFile& inv, vector<double>& fv) const {
if (IsDefined()) {
InvertedFile::exactIterator* eit = 0;
TupleId id;
uint32_t wc, cc;
set<base> values;
GetValues(values);
for (auto place : values) {
eit = inv.getExactIterator(place.first, 16777216);
if (eit->next(id, wc, cc)) {
fv[id] += 1.0;
}
}
delete eit;
}
}
/*
\subsection{Function ~Property~}
*/
ListExpr Places::Property() {
return gentc::GenProperty("-> DATA", BasicType(),
"((<label> <int>) (<label> <int>) ...)",
"((\'Dortmund\' 1909) (\'Mailand\' 1899))");
}
/*
\subsection{Function ~CheckKind~}
*/
bool Places::CheckKind(ListExpr type, ListExpr& errorInfo) {
return nl->IsEqual(type, Places::BasicType());
}
/*
\subsection{Function ~GetFLOB~}
*/
Flob* Places::GetFLOB(const int i) {
assert((i >= 0) && (i < 2));
return (i == 0 ? &values : &posref);
}
/*
\subsection{Function ~Compare~}
*/
int Places::Compare(const Attribute* arg) const {
if (GetNoValues() == ((Places*)arg)->GetNoValues()) {
base val1, val2;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, val1);
((Places*)arg)->GetValue(i, val2);
int comp = val1.first.compare(val2.first);
if (comp == 0) { // equal strings
if (val1.second > val2.second) {
return 1;
}
if (val1.second < val2.second) {
return -1;
}
}
return (comp > 0 ? 1 : -1);
}
return 0;
}
if (GetNoValues() > ((Places*)arg)->GetNoValues()) {
return 1;
}
return -1;
}
/*
\subsection{Function ~HashValue~}
*/
size_t Places::HashValue() const {
if (IsEmpty() || !IsDefined()) {
return 0;
}
size_t result = 1;
base value;
for (int i = 0; i < GetNoValues(); i++) {
GetValue(i, value);
result *= value.first.length() * value.second;
}
return result;
}
/*
\subsection{Function ~ToListExpr~}
*/
ListExpr Places::ToListExpr(ListExpr typeInfo) {
if (!IsDefined()) {
return nl->SymbolAtom(Symbol::UNDEFINED());
}
if (IsEmpty()) {
return nl->Empty();
}
base val;
GetValue(0, val);
ListExpr res = nl->OneElemList(nl->TwoElemList(nl->TextAtom(val.first),
nl->IntAtom(val.second)));
ListExpr last = res;
for (int i = 1; i < GetNoValues(); i++) {
GetValue(i, val);
last = nl->Append(last, nl->TwoElemList(nl->TextAtom(val.first),
nl->IntAtom(val.second)));
}
return res;
}
/*
\subsection{Function ~ReadFrom~}
*/
bool Places::ReadFrom(ListExpr LE, ListExpr typeInfo) {
Clean();
if (listutils::isSymbolUndefined(LE)) {
SetDefined(false);
return true;
}
SetDefined(true);
ListExpr rest = LE;
while (!nl->IsEmpty(rest)) {
if (!nl->HasLength(nl->First(rest), 2)) {
SetDefined(false);
return false;
}
string text;
nl->WriteToString(text, nl->First(nl->First(rest)));
Append(make_pair(text.substr(1, text.length() - 2),
nl->IntValue(nl->Second(nl->First(rest)))));
rest = nl->Rest(rest);
}
return true;
}
/*
\section{Implementation of class ~MLabels~}
\subsection{Function ~createML~}
*/
void MLabel::createML(const int size, const int number, vector<string>& labels){
if (size > 0) {
ULabel ul(1);
Instant start(1.0);
start.Set(2015, 1, 1);
time_t t;
time(&t);
srand((unsigned int)t);
Instant end(start);
SecInterval iv(true);
int labelStartPos = size * number;
for (int i = 0; i < size; i++) {
datetime::DateTime dur(0, rand() % 86400000 + 3600000,
datetime::durationtype);
end.Add(&dur);
ul.constValue.Set(true, labels[labelStartPos + i]);
iv.Set(start, end, true, false);
ul.timeInterval = iv;
Add(ul);
start = end;
}
units.TrimToSize();
}
else {
cout << "Invalid parameters for creation." << endl;
SetDefined(false);
}
}
/*
\subsection{Function ~convertFromMString~}
*/
void MLabel::convertFromMString(const MString& source) {
Clear();
if (!IsDefined()) {
return;
}
SetDefined(true);
UString us(true);
for (int i = 0; i < source.GetNoComponents(); i++) {
source.Get(i, us);
ULabel ul(us.timeInterval, us.constValue.GetValue());
Add(ul);
}
units.TrimToSize();
}
int getTypeNo(ListExpr typeList) {
if (MLabel::checkType(typeList)) {
return 0;
}
if (MLabels::checkType(typeList)) {
return 1;
}
if (MPlace::checkType(typeList)) {
return 2;
}
if (MPlaces::checkType(typeList)) {
return 3;
}
return -1;
}
bool isSymbolicType(ListExpr type) {
return ((nl->ToString(type) == "mlabel") || (nl->ToString(type) == "mlabels")
|| (nl->ToString(type) == "mplace") || (nl->ToString(type) == "mplaces"));
}
double scalarProduct(collection::Collection& v1, collection::Collection& v2) {
assert(v1.GetMyCollType() == collection::vector &&
v2.GetMyCollType() == collection::vector);
assert(v1.GetNoComponents() == v2.GetNoComponents());
double result = 0.0;
CcReal *elem1(0), *elem2(0);
for (int i = 0; i < v1.GetNoComponents(); i++) {
elem1 = (CcReal*)(v1.GetComponent(i));
elem2 = (CcReal*)(v2.GetComponent(i));
assert(elem1->IsDefined() && elem2->IsDefined());
result += elem1->GetValue() * elem2->GetValue();
elem1->DeleteIfAllowed();
elem2->DeleteIfAllowed();
}
return result;
}
double vLength(collection::Collection& v) {
double result = 0.0;
CcReal *elem(0);
for (int i = 0; i < v.GetNoComponents(); i++) {
elem = (CcReal*)(v.GetComponent(i));
assert(elem->IsDefined());
result += pow(elem->GetValue(), 2.0);
elem->DeleteIfAllowed();
}
return sqrt(result);
}
double cosineSimilarity(collection::Collection& v1, collection::Collection& v2){
assert(v1.GetMyCollType() == collection::vector &&
v2.GetMyCollType() == collection::vector);
assert(v1.GetNoComponents() == v2.GetNoComponents());
return scalarProduct(v1, v2) / (vLength(v1) * vLength(v2));
}
double jaccardSimilarity(collection::Collection& v1,
collection::Collection& v2) {
assert(v1.GetMyCollType() == collection::vector &&
v2.GetMyCollType() == collection::vector);
assert(v1.GetNoComponents() == v2.GetNoComponents());
CcReal *elem1(0), *elem2(0);
unsigned int intersection(0), un(0);
for (int i = 0; i < v1.GetNoComponents(); i++) {
elem1 = (CcReal*)(v1.GetComponent(i));
elem2 = (CcReal*)(v2.GetComponent(i));
assert(elem1->IsDefined() && elem2->IsDefined());
if (elem1->GetValue() > 0 && elem2->GetValue() > 0) {
intersection++;
un++;
}
else if (elem1->GetValue() > 0 || elem2->GetValue() > 0) {
un++;
}
}
if (un == 0) {
return 0.0;
}
return (double)intersection / un;
}
double jaccardSimilarity(set<string>& s1, set<string>& s2) {
if (s1.empty() && s2.empty()) {
return 1.0;
}
set<string> in, un;
set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),
std::inserter(in, in.begin()));
set_union(s1.begin(), s1.end(), s2.begin(), s2.end(),
std::inserter(un, un.begin()));
if (un.size() == 0) {
return 0.0;
}
return (double)(in.size()) / un.size();
}
/*
\subsection{Type Constructors}
*/
GenTC<Label> label;
GenTC<Labels> labels;
GenTC<Place> place;
GenTC<Places> places;
GenTC<IBasic<Label> > ilabel;
GenTC<IBasic<Place> > iplace;
GenTC<IBasics<Labels> > ilabels;
GenTC<IBasics<Places> > iplaces;
GenTC<UBasic<Label> > ulabel;
GenTC<UBasic<Place> > uplace;
GenTC<UBasics<Labels> > ulabels;
GenTC<UBasics<Places> > uplaces;
GenTC<MBasics<Labels> > mlabels;
GenTC<MBasics<Places> > mplaces;
GenTC<MLabel> mlabel;
GenTC<MBasic<Place> > mplace;
/*
\section{Operator ~tolabel~}
\subsection{Type Mapping}
*/
ListExpr tolabelTM(ListExpr args) {
if (nl->ListLength(args) == 1) {
if (FText::checkType(nl->First(args)) ||
CcString::checkType(nl->First(args))) {
return nl->SymbolAtom(Label::BasicType());
}
}
return NList::typeError("Expecting a text or a string.");
}
/*
\subsection{Selection Function}
*/
int tolabelSelect(ListExpr args) {
return (FText::checkType(nl->First(args)) ? 0 : 1);
}
/*
\subsection{Value Mapping}
*/
template<class T>
int tolabelVM(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
T* src = static_cast<T*>(args[0].addr);
Label* res = static_cast<Label*>(result.addr);
if (src->IsDefined()) {
res->Set(true, src->GetValue());
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct tolabelInfo : OperatorInfo {
tolabelInfo() {
name = "tolabel";
signature = "text -> label";
appendSignature("string -> label");
syntax = "tolabel( _ );";
meaning = "Creates a label from a text or string.";
}
};
/*
\section{Operator ~tostring~}
\subsection{Type Mapping}
*/
ListExpr tostringTM(ListExpr args) {
if (nl->ListLength(args) == 1) {
if (Label::checkType(nl->First(args))) {
return nl->SymbolAtom(CcString::BasicType());
}
}
return NList::typeError("Expecting a label.");
}
/*
\subsection{Value Mapping}
*/
int tostringVM(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
Label* source = static_cast<Label*>(args[0].addr);
CcString* res = static_cast<CcString*>(result.addr);
if (source->IsDefined()) {
string text;
source->GetValue(text),
res->Set(true, text);
}
result.addr = res;
return 0;
}
/*
\subsection{Operator Info}
*/
struct tostringInfo : OperatorInfo {
tostringInfo() {
name = "tostring";
signature = "label -> string";
syntax = "tostring ( _ )";
meaning = "Converts a label into a string.";
}
};
/*
\section{Operator ~totext~}
\subsection{Type Mapping}
*/
ListExpr totextTM(ListExpr args) {
if (nl->ListLength(args) == 1) {
if (Label::checkType(nl->First(args))) {
return nl->SymbolAtom(FText::BasicType());
}
}
return NList::typeError("Expecting a label.");
}
/*
\subsection{Value Mapping}
*/
int totextVM(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
Label* source = static_cast<Label*>(args[0].addr);
FText* res = static_cast<FText*>(result.addr);
if (source->IsDefined()) {
string text;
source->GetValue(text);
res->Set(true, text);
}
result.addr = res;
return 0;
}
/*
\subsection{Operator Info}
*/
struct totextInfo : OperatorInfo {
totextInfo() {
name = "totext";
signature = "label -> text";
syntax = "totext ( _ )";
meaning = "Converts a label into a text.";
}
};
/*
\section{Operator ~mstringtomlabel~}
\subsection{Type Mapping}
*/
ListExpr mstringtomlabelTM(ListExpr args) {
if (nl->ListLength(args) == 1) {
if (MString::checkType(nl->First(args))) {
return nl->SymbolAtom(MLabel::BasicType());
}
}
return NList::typeError("Expecting a mstring.");
}
/*
\subsection{Value Mapping}
*/
int mstringtomlabelVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
MString *source = static_cast<MString*>(args[0].addr);
MLabel* res = static_cast<MLabel*>(result.addr);
res->convertFromMString(*source);
result.addr = res;
return 0;
}
/*
\subsection{Operator Info}
*/
struct mstringtomlabelInfo : OperatorInfo {
mstringtomlabelInfo() {
name = "mstringtomlabel";
signature = "mstring -> mlabel";
syntax = "mstringtomlabel(_)";
meaning = "Converts a mstring into a mlabel.";
}
};
/*
\section{Operator ~tolabels~}
tolabels: (text)+ -> labels
\subsection{Type Mapping}
*/
ListExpr tolabelsTM(ListExpr args) {
ListExpr rest = args;
string firstType;
while (!nl->IsEmpty(rest)) {
if (rest == args) { // first value
firstType = nl->ToString(nl->First(rest));
if (!FText::checkType(nl->First(rest)) &&
!CcString::checkType(nl->First(rest))) {
return NList::typeError("Expecting only text or string elements.");
}
}
else {
if (nl->ToString(nl->First(rest)) != firstType) {
return NList::typeError("Expecting only text or only string elements.");
}
}
rest = nl->Rest(rest);
}
return nl->SymbolAtom(Labels::BasicType());
}
/*
\subsection{Selection Function}
*/
int tolabelsSelect(ListExpr args) {
if (nl->IsEmpty(args)) return 0;
if (FText::checkType(nl->First(args))) return 0;
if (CcString::checkType(nl->First(args))) return 1;
return -1;
}
/*
\subsection{Value Mapping}
*/
template <class T>
int tolabelsVM(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
Labels* res = static_cast<Labels*>(result.addr);
res->Clean();
for (int i = 0; i < qp->GetNoSons(s); i++) {
T* src = static_cast<T*>(args[i].addr);
if (src->IsDefined()) {
if (!src->GetValue().empty()) {
res->Append(src->GetValue());
}
}
}
res->SetDefined(true);
return 0;
}
/*
\subsection{Operator Info}
*/
struct tolabelsInfo : OperatorInfo {
tolabelsInfo() {
name = "tolabels";
signature = "T x ... x T -> labels, where T in {text, string}";
syntax = "tolabels( _ , ..., _ );";
meaning = "Creates a labels from a text or string list.";
}
};
/*
\section{Operator ~toplaces~}
toplaces: text x int x ... x text x int -> places
toplaces: place x ... x place -> places
\subsection{Type Mapping}
*/
ListExpr toplacesTM(ListExpr args) {
ListExpr rest = args;
bool place;
if (!nl->IsEmpty(rest)) {
place = Place::checkType(nl->First(rest));
}
while (!nl->IsEmpty(rest)) {
if (place) {
if (!Place::checkType(nl->First(rest))) {
return NList::typeError("Expecting a list of places.");
}
}
else {
if (!FText::checkType(nl->First(rest))) {
return NList::typeError("Expecting a list of text x int pairs.");
}
rest = nl->Rest(rest);
if (nl->IsEmpty(rest)) {
return NList::typeError("Expecting a list of text x int pairs.");
}
if (!CcInt::checkType(nl->First(rest))) {
return NList::typeError("Expecting a list of text x int pairs.");
}
}
rest = nl->Rest(rest);
}
return nl->SymbolAtom(Places::BasicType());
}
/*
\subsection{Selection Function}
*/
int toplacesSelect(ListExpr args) {
if (nl->IsEmpty(args)) {
return 0;
}
return (Place::checkType(nl->First(args)) ? 0 : 1);
}
/*
\subsection{Value Mapping}
*/
int toplacesVM_P(Word* args, Word& result, int message, Word& local,Supplier s){
result = qp->ResultStorage(s);
Places* res = static_cast<Places*>(result.addr);
res->Clean();
for (int i = 0; i < qp->GetNoSons(s); i++) {
Place* src = static_cast<Place*>(args[i].addr);
if (src->IsDefined()) {
res->Append(*src);
}
}
res->SetDefined(true);
return 0;
}
int toplacesVM_T(Word* args, Word& result, int message, Word& local,Supplier s){
result = qp->ResultStorage(s);
Places* res = static_cast<Places*>(result.addr);
res->Clean();
for (int i = 0; i < qp->GetNoSons(s); i = i + 2) {
FText *src1 = static_cast<FText*>(args[i].addr);
CcInt *src2 = static_cast<CcInt*>(args[i + 1].addr);
if (src1->IsDefined() && src2->IsDefined()) {
res->Append(make_pair(src1->GetValue(), src2->GetIntval()));
}
}
res->SetDefined(true);
return 0;
}
/*
\subsection{Operator Info}
*/
struct toplacesInfo : OperatorInfo {
toplacesInfo() {
name = "toplaces";
signature = "((text x int) ... (text x int)) -> places";
appendSignature("place x ... x place -> places");
syntax = "toplaces( _, ..., _ );";
meaning = "Creates a places from a list of (text, int) pairs or places.";
}
};
/*
\section{Operator ~collect\_labels~}
stream(T) x bool -> labels, where T in {label, string, text}
\subsection{Type Mapping}
*/
ListExpr collect_labelsTM(ListExpr args) {
if (!nl->HasLength(args, 2)) {
return listutils::typeError("Two arguments expected");
}
if (!Stream<Label>::checkType(nl->First(args)) &&
!Stream<CcString>::checkType(nl->First(args)) &&
!Stream<FText>::checkType(nl->First(args))) {
return listutils::typeError("First argument must be a stream of label, "
"string, or text");
}
if (!CcBool::checkType(nl->Second(args))) {
return listutils::typeError("Second argument must be a bool");
}
return nl->SymbolAtom(Labels::BasicType());
}
/*
\subsection{Selection Function}
*/
int collect_labelsSelect(ListExpr args) {
if (Label::checkType(nl->Second(nl->First(args)))) return 0;
if (CcString::checkType(nl->Second(nl->First(args)))) return 1;
if (FText::checkType(nl->Second(nl->First(args)))) return 2;
return -1;
}
/*
\subsection{Value Mapping}
*/
template <class T>
int collect_labelsVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Labels* res = static_cast<Labels*>(result.addr);
res->Clean();
Stream<T> stream = static_cast<Stream<T> >(args[0].addr);
CcBool *ccignoreundef = static_cast<CcBool*>(args[1].addr);
if (!ccignoreundef->IsDefined()) {
res->SetDefined(false);
return 0;
}
bool ignoreundef = ccignoreundef->GetValue();
res->SetDefined(true);
stream.open();
T *elem = stream.request();
while (elem != 0) {
if (!elem->IsDefined() && !ignoreundef) {
res->SetDefined(false);
return 0;
}
else {
string elemstr = elem->GetValue();
res->Append(elemstr);
}
elem = stream.request();
}
stream.close();
return 0;
}
/*
\subsection{Operator Info}
*/
struct collect_labelsInfo : OperatorInfo {
collect_labelsInfo() {
name = "collect_labels";
signature = "stream(T) x bool -> labels, where T in {label, string, text}";
syntax = "_ collect_labels[ _ ];";
meaning = "Collects the stream elements into a labels value. If the "
"boolean parameter is true, undefined values are ignored. "
"Otherwise, the result is defined only if all elements are.";
}
};
/*
\section{Operator ~contains~}
contains: labels x {label(s), string, text} -> bool
contains: places x place(s) -> bool
\subsection{Type Mapping}
*/
ListExpr containsTM(ListExpr args) {
const string errMsg = "Expecting labels x label(s) or places x place(s).";
if (nl->ListLength(args) != 2) {
return listutils::typeError("Two arguments expected.");
}
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
if (Labels::checkType(first)) {
if (Label::checkType(second) || Labels::checkType(second) ||
CcString::checkType(second) || FText::checkType(second)) {
return nl->SymbolAtom(CcBool::BasicType());
}
}
if (Places::checkType(first)) {
if (Place::checkType(second) || Places::checkType(second)) {
return nl->SymbolAtom(CcBool::BasicType());
}
}
return NList::typeError(errMsg);
}
/*
\subsection{Selection Function}
*/
int containsSelect(ListExpr args) {
if (Labels::checkType(nl->First(args))) {
if (Label::checkType(nl->Second(args))) {
return 0;
}
if (Labels::checkType(nl->Second(args))) {
return 2;
}
if (CcString::checkType(nl->Second(args))) {
return 4;
}
if (FText::checkType(nl->Second(args))) {
return 5;
}
}
if (Places::checkType(nl->First(args))) {
return Place::checkType(nl->Second(args)) ? 1 : 3;
}
return -1;
}
/*
\subsection{Value Mapping}
*/
template<class Collection, class Value>
int containsSingleVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
Collection *coll = static_cast<Collection*>(args[0].addr);
Value* val = static_cast<Value*>(args[1].addr);
result = qp->ResultStorage(s);
CcBool* res = static_cast<CcBool*>(result.addr);
if (coll->IsDefined() && val->IsDefined()) {
typename Value::base value;
val->GetValue(value);
res->Set(true, coll->Contains(value));
}
else {
res->SetDefined(false);
}
return 0;
}
template<class Value>
int containsBasicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
Labels *lbs = static_cast<Labels*>(args[0].addr);
Value* val = static_cast<Value*>(args[1].addr);
result = qp->ResultStorage(s);
CcBool* res = static_cast<CcBool*>(result.addr);
if (lbs->IsDefined() && val->IsDefined()) {
std::string value = val->GetValue();
res->Set(true, lbs->Contains(value));
}
else {
res->SetDefined(false);
}
return 0;
}
template<class Collection, class Values>
int containsMultiVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
Collection *coll = static_cast<Collection*>(args[0].addr);
Values* vals = static_cast<Values*>(args[1].addr);
result = qp->ResultStorage(s);
CcBool* res = static_cast<CcBool*>(result.addr);
if (coll->IsDefined() && vals->IsDefined()) {
res->Set(true, true);
for (int i = 0; i < vals->GetNoValues(); i++) {
typename Values::base value;
vals->GetValue(i, value);
if (!coll->Contains(value)) {
res->Set(true, false);
return 0;
}
}
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct containsInfo : OperatorInfo {
containsInfo() {
name = "contains";
signature = "labels x {label(s), string, text} -> bool";
appendSignature("places x place(s) -> bool");
syntax = "_ contains _;";
meaning = "Checks whether a labels/places object contains a label/place.";
}
};
/*
\section{Operator ~intersects~}
intersects: T x T -> bool, where T in \{labels, places\}
\subsection{Type Mapping}
*/
ListExpr intersectsTM(ListExpr args) {
const string errMsg = "Expecting labels x labels or places x places.";
if (!nl->HasLength(args, 2)) {
return listutils::typeError(errMsg);
}
if ((Labels::checkType(nl->First(args)) &&
Labels::checkType(nl->Second(args))) ||
(Places::checkType(nl->First(args)) &&
Places::checkType(nl->Second(args)))) {
return nl->SymbolAtom(CcBool::BasicType());
}
return listutils::typeError(errMsg);
}
/*
\subsection{Selection Function}
*/
int intersectsSelect(ListExpr args) {
return Labels::checkType(nl->First(args)) ? 0 : 1;
}
/*
\subsection{Value Mapping}
*/
template<class T>
int intersectsVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
T *first = static_cast<T*>(args[0].addr);
T *second = static_cast<T*>(args[1].addr);
result = qp->ResultStorage(s);
CcBool* res = static_cast<CcBool*>(result.addr);
if (first->IsDefined() && second->IsDefined()) {
res->Set(true, first->Intersects(*second));
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct intersectsInfo : OperatorInfo {
intersectsInfo() {
name = "intersects";
signature = "labels x labels -> bool";
appendSignature("places x places -> bool");
syntax = "_ intersects _;";
meaning = "Checks whether two labels/places values have a non-empty "
"intersection";
}
};
/*
\section{Operator ~toplace~}
toplace: (string | text) x int -> place
\subsection{Type Mapping}
*/
ListExpr toplaceTM(ListExpr args) {
if (nl->ListLength(args) == 2) {
if ((CcString::checkType(nl->First(args)) ||
FText::checkType(nl->First(args))) &&
CcInt::checkType(nl->Second(args))) {
return nl->SymbolAtom(Place::BasicType());
}
}
return NList::typeError("Expecting (string | text) x int.");
}
/*
\subsection{Selection Function}
*/
int toplaceSelect(ListExpr args) {
if (CcString::checkType(nl->First(args))) return 0;
if (FText::checkType(nl->First(args))) return 1;
return -1;
}
/*
\subsection{Value Mapping}
*/
template<class T>
int toplaceVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T *name = static_cast<T*>(args[0].addr);
CcInt *ref = static_cast<CcInt*>(args[1].addr);
result = qp->ResultStorage(s);
Place *res = static_cast<Place*>(result.addr);
if (name->IsDefined() && ref->IsDefined()) {
res->Set(true, make_pair(name->GetValue(), ref->GetIntval()));
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct toplaceInfo : OperatorInfo {
toplaceInfo() {
name = "toplace";
signature = "[string | text] x int -> place";
syntax = "toplace( _ );";
meaning = "Converts a string/text and an int into a place.";
}
};
/*
\section{Operator ~name~}
\subsection{Type Mapping}
*/
ListExpr nameTM(ListExpr args) {
if (nl->ListLength(args) != 1) {
return listutils::typeError("One argument expected.");
}
if (Place::checkType(nl->First(args))) {
return nl->SymbolAtom(FText::BasicType());
}
return NList::typeError("Expecting a place.");
}
/*
\subsection{Value Mapping}
*/
int nameVM(Word* args, Word& result, int message, Word& local, Supplier s) {
Place *src = static_cast<Place*>(args[0].addr);
result = qp->ResultStorage(s);
FText* res = static_cast<FText*>(result.addr);
if (src->IsDefined()) {
pair<string, unsigned int> value;
src->GetValue(value);
res->Set(true, value.first);
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct nameInfo : OperatorInfo {
nameInfo() {
name = "name";
signature = "place -> text";
syntax = "name( _ );";
meaning = "Returns the name from a place object.";
}
};
/*
\section{Operator ~ref~}
\subsection{Type Mapping}
*/
ListExpr refTM(ListExpr args) {
if (nl->ListLength(args) != 1) {
return listutils::typeError("One argument expected.");
}
if (Place::checkType(nl->First(args))) {
return nl->SymbolAtom(CcInt::BasicType());
}
return NList::typeError("Expecting a place.");
}
/*
\subsection{Value Mapping}
*/
int refVM(Word* args, Word& result, int message, Word& local, Supplier s) {
Place *src = static_cast<Place*>(args[0].addr);
result = qp->ResultStorage(s);
CcInt* res = static_cast<CcInt*>(result.addr);
if (src->IsDefined()) {
res->Set(true, src->GetRef());
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct refInfo : OperatorInfo {
refInfo() {
name = "ref";
signature = "place -> int";
syntax = "ref( _ );";
meaning = "Returns the reference from a place object.";
}
};
/*
\section{Operator ~=~}
=: T x T -> bool, where T in {place(s), label(s)}
\subsection{Type Mapping}
*/
ListExpr equalsUnequalsTM(ListExpr args) {
if (nl->ListLength(args) != 2) {
return NList::typeError("Expecting two arguments.");
}
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if ((Label::checkType(arg1) && (Label::checkType(arg2) ||
CcString::checkType(arg2) || FText::checkType(arg2))) ||
(Label::checkType(arg2) && (Label::checkType(arg1) ||
CcString::checkType(arg1) || FText::checkType(arg1))) ||
(Labels::checkType(arg1) && Labels::checkType(arg2)) ||
(Place::checkType(arg1) && Place::checkType(arg2)) ||
(Places::checkType(arg1) && Places::checkType(arg2))) {
return nl->SymbolAtom(CcBool::BasicType());
}
return NList::typeError("Expecting T x T, where T in {place(s), label(s)}");
}
/*
\subsection{Selection Function}
*/
int equalsUnequalsSelect(ListExpr args) {
if (Label::checkType(nl->First(args))) {
if (Label::checkType(nl->Second(args))) return 0;
if (CcString::checkType(nl->Second(args))) return 4;
if (FText::checkType(nl->Second(args))) return 5;
}
if (Label::checkType(nl->Second(args))) {
if (CcString::checkType(nl->First(args))) return 6;
if (FText::checkType(nl->First(args))) return 7;
}
if (Labels::checkType(nl->First(args))) return 1;
if (Place::checkType(nl->First(args))) return 2;
if (Places::checkType(nl->First(args))) return 3;
return -1;
}
/*
\subsection{Value Mapping}
*/
template<class T>
int equalsVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T *first = static_cast<T*>(args[0].addr);
T *second = static_cast<T*>(args[1].addr);
result = qp->ResultStorage(s);
CcBool *res = static_cast<CcBool*>(result.addr);
if (first->IsDefined() && second->IsDefined()) {
res->Set(true, *first == *second);
}
else {
res->SetDefined(false);
}
return 0;
}
template<class T, class U>
int equalsVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T *first = static_cast<T*>(args[0].addr);
U *second = static_cast<U*>(args[1].addr);
result = qp->ResultStorage(s);
CcBool *res = static_cast<CcBool*>(result.addr);
cout << T::BasicType() << " " << U::BasicType() << endl;
cout << second->IsDefined() << endl;
cout << first->IsDefined() << endl;
if (first->IsDefined() && second->IsDefined()) {
cout << second->GetValue() << endl;
cout << first->GetValue() << endl;
res->Set(true, first->GetValue() == second->GetValue());
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct equalsInfo : OperatorInfo {
equalsInfo() {
name = "=";
signature = "T x T -> bool, where T in {label(s), place(s)}";
syntax = "_ = _;";
meaning = "Checks whether both objects are equal.";
}
};
/*
\section{Operator ~\#~}
\#: T x T -> bool, where T in {place(s), label(s)}
\subsection{Value Mapping}
*/
template<class T>
int unequalsVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T *first = static_cast<T*>(args[0].addr);
T *second = static_cast<T*>(args[1].addr);
result = qp->ResultStorage(s);
CcBool *res = static_cast<CcBool*>(result.addr);
if (first->IsDefined() && second->IsDefined()) {
res->Set(true, !(*first == *second));
}
else {
res->SetDefined(false);
}
return 0;
}
template<class T, class U>
int unequalsVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T *first = static_cast<T*>(args[0].addr);
U *second = static_cast<U*>(args[1].addr);
result = qp->ResultStorage(s);
CcBool *res = static_cast<CcBool*>(result.addr);
if (first->IsDefined() && second->IsDefined()) {
res->Set(true, !(first->GetValue() == second->GetValue()));
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct unequalsInfo : OperatorInfo {
unequalsInfo() {
name = "#";
signature = "T x T -> bool, where T in {label(s), place(s)}";
syntax = "_ = _;";
meaning = "Checks whether both objects are unequal.";
}
};
/*
\section{Operator ~union~}
union: T x T -> (labels|places), where T in {place(s), label(s)}
\subsection{Type Mapping}
*/
ListExpr unionTM(ListExpr args) {
if (nl->ListLength(args) != 2) {
return NList::typeError("Expecting two arguments.");
}
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if ((Label::checkType(arg1) && Label::checkType(arg2)) ||
(Labels::checkType(arg1) && Label::checkType(arg2)) ||
(Label::checkType(arg1) && Labels::checkType(arg2)) ||
(Labels::checkType(arg1) && Labels::checkType(arg2))) {
return nl->SymbolAtom(Labels::BasicType());
}
if ((Place::checkType(arg1) && Place::checkType(arg2)) ||
(Places::checkType(arg1) && Place::checkType(arg2)) ||
(Place::checkType(arg1) && Places::checkType(arg2)) ||
(Places::checkType(arg1) && Places::checkType(arg2))) {
return nl->SymbolAtom(Places::BasicType());
}
return NList::typeError("Expecting T x T, where T in {place(s), label(s)}");
}
/*
\subsection{Selection Function}
*/
int unionSelect(ListExpr args) {
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if (Label::checkType(arg1) && Label::checkType(arg2)) return 0;
if (Labels::checkType(arg1) && Label::checkType(arg2)) return 1;
if (Label::checkType(arg1) && Labels::checkType(arg2)) return 2;
if (Labels::checkType(arg1) && Labels::checkType(arg2)) return 3;
if (Place::checkType(arg1) && Place::checkType(arg2)) return 4;
if (Places::checkType(arg1) && Place::checkType(arg2)) return 5;
if (Place::checkType(arg1) && Places::checkType(arg2)) return 6;
if (Places::checkType(arg1) && Places::checkType(arg2)) return 7;
return -1;
}
/*
\subsection{Value Mapping}
*/
template<class T, class U, class V>
int unionVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T *first = static_cast<T*>(args[0].addr);
U *second = static_cast<U*>(args[1].addr);
result = qp->ResultStorage(s);
V *res = static_cast<V*>(result.addr);
if (first->IsDefined() && second->IsDefined()) {
set<typename V::base> values1, values2;
first->GetValues(values1);
second->GetValues(values2);
res->Union(values1, values2);
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct unionInfo : OperatorInfo {
unionInfo() {
name = "union";
signature = "T x T -> (labels|places), where T in {label(s), place(s)}";
syntax = "_ union _;";
meaning = "Computes the union of both arguments.";
}
};
/*
\section{Operator ~intersection~}
intersection: T x T -> T, where T in {places, labels}
\subsection{Type Mapping}
*/
ListExpr intersectionTM(ListExpr args) {
if (nl->ListLength(args) != 2) {
return NList::typeError("Expecting two arguments.");
}
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if (Labels::checkType(arg1) && Labels::checkType(arg2)) {
return nl->SymbolAtom(Labels::BasicType());
}
if (Places::checkType(arg1) && Places::checkType(arg2)) {
return nl->SymbolAtom(Places::BasicType());
}
return NList::typeError("Expecting T x T, where T in {places, labels}");
}
/*
\subsection{Selection Function}
*/
int intersectionSelect(ListExpr args) {
if (Labels::checkType(nl->First(args))) return 0;
if (Places::checkType(nl->First(args))) return 1;
return -1;
}
/*
\subsection{Value Mapping}
*/
template<class T>
int intersectionVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
T *first = static_cast<T*>(args[0].addr);
T *second = static_cast<T*>(args[1].addr);
result = qp->ResultStorage(s);
T *res = static_cast<T*>(result.addr);
if (first->IsDefined() && second->IsDefined()) {
set<typename T::base> values1, values2;
first->GetValues(values1);
second->GetValues(values2);
res->Intersection(values1, values2);
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct intersectionInfo : OperatorInfo {
intersectionInfo() {
name = "intersection";
signature = "T x T -> T, where T in {labels, places}";
syntax = "intersection(_ , _);";
meaning = "Computes the intersection of both arguments.";
}
};
/*
\section{Operator ~minus~}
minus: T x U -> T, where T in {places, labels}, U in {place(s), label(s)}
\subsection{Type Mapping}
*/
ListExpr minusTM(ListExpr args) {
if (nl->ListLength(args) != 2) {
return NList::typeError("Expecting two arguments.");
}
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if (Labels::checkType(arg1) &&
(Label::checkType(arg2) || Labels::checkType(arg2))) {
return nl->SymbolAtom(Labels::BasicType());
}
if (Places::checkType(arg1) &&
(Place::checkType(arg2) || Places::checkType(arg2))) {
return nl->SymbolAtom(Places::BasicType());
}
return NList::typeError("Expecting T x U, where T in {places, labels} and "
"U in {place(s), label(s)}");
}
/*
\subsection{Selection Function}
*/
int minusSelect(ListExpr args) {
if (Labels::checkType(nl->First(args))) {
if (Label::checkType(nl->Second(args))) return 0;
if (Labels::checkType(nl->Second(args))) return 1;
}
if (Places::checkType(nl->First(args))) {
if (Place::checkType(nl->Second(args))) return 2;
if (Places::checkType(nl->Second(args))) return 3;
}
return -1;
}
/*
\subsection{Value Mapping}
*/
template<class T, class U>
int minusVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T *first = static_cast<T*>(args[0].addr);
U *second = static_cast<U*>(args[1].addr);
result = qp->ResultStorage(s);
T *res = static_cast<T*>(result.addr);
if (first->IsDefined() && second->IsDefined()) {
set<typename T::base> values1, values2;
first->GetValues(values1);
second->GetValues(values2);
res->Minus(values1, values2);
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct minusInfo : OperatorInfo {
minusInfo() {
name = "minus";
signature = "T x U -> T, where T in {labels, places}, "
"U in {label(s), place(s)";
syntax = "_ minus _;";
meaning = "Computes the difference of both arguments.";
}
};
#ifdef RECODE
/*
\section{Operator ~recode~}
recode: T x string x string -> T, where T in {mlabel, mlabels}
\subsection{Type Mapping}
*/
ListExpr recodeTM(ListExpr args){
string err = " T x string x string -> T, T in {mlabel, mlabels} expected";
if (!nl->HasLength(args, 3)) {
return listutils::typeError(err);
}
if (!MLabel::checkType(nl->First(args)) &&
!MLabels::checkType(nl->First(args))) {
return listutils::typeError(err);
}
if (!CcString::checkType(nl->Second(args)) ||
!CcString::checkType(nl->Third(args))) {
return listutils::typeError(err);
}
return nl->First(args);
}
/*
\subsection{Selection Function}
*/
int recodeSelect(ListExpr args) {
if (MLabel::checkType(nl->First(args))) return 0;
if (MLabels::checkType(nl->First(args))) return 1;
return -1;
}
/*
\subsection{Value Mapping}
*/
template<class T>
int recodeVM(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
T *src = static_cast<T*>(args[0].addr);
CcString *from = static_cast<CcString*>(args[1].addr);
CcString *to = static_cast<CcString*>(args[2].addr);
T *res = static_cast<T*>(result.addr);
if (!src->IsDefined() || !from->IsDefined() || !to->IsDefined()) {
res->SetDefined(false);
return 0;
}
else {
src->Recode(from->GetValue(), to->GetValue(), *res);
}
return 0;
}
/*
\subsection{Operator Info}
*/
struct recodeInfo : OperatorInfo {
recodeInfo() {
name = "recode";
signature = "T x string x string -> T, where T in {mlabel, mlabels}";
syntax = "_ recode [ _, _ ];";
meaning = "Recodes an mlabel(s) from one charset to another one.";
}
};
#endif
/*
\section{Generic operators for ~[i|m|u] [label|place] [s]?~}
\subsection{Operator ~the\_unit~}
the\_unit: T x instant x instant x bool x bool -> uT,
T x interval -> uT,
with T in {label, labels, place, places}
\subsubsection{Type Mapping}
*/
ListExpr the_unitSymbolicTM(ListExpr args) {
if(!(nl->HasMinLength(args,1)))
return listutils::typeError("Operator requires 1 argument at least!");
if (nl->Equal(nl->Rest(args), nl->FourElemList(
nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(Instant::BasicType()),
nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))
|| nl->Equal(nl->Rest(args),
nl->OneElemList(nl->SymbolAtom(SecInterval::BasicType())))) {
if (Label::checkType(nl->First(args))) {
return nl->SymbolAtom(ULabel::BasicType());
}
if (Labels::checkType(nl->First(args))) {
return nl->SymbolAtom(ULabels::BasicType());
}
if (Place::checkType(nl->First(args))) {
return nl->SymbolAtom(UPlace::BasicType());
}
if (Places::checkType(nl->First(args))) {
return nl->SymbolAtom(UPlaces::BasicType());
}
}
return listutils::typeError(
"Operator 'the_unit' expects a list with structure\n"
"'(T instant instant bool bool)', or \n"
"'(T interval)'\n for T in {label, labels, place, places}.");
}
/*
\subsubsection{Selection Function}
*/
int the_unitSymbolicSelect(ListExpr args) {
if (!SecInterval::checkType(nl->Second(args))) {
if (Label::checkType(nl->First(args))) return 0;
if (Labels::checkType(nl->First(args))) return 1;
if (Place::checkType(nl->First(args))) return 2;
if (Places::checkType(nl->First(args))) return 3;
}
if (Label::checkType(nl->First(args))) return 4;
if (Labels::checkType(nl->First(args))) return 5;
if (Place::checkType(nl->First(args))) return 6;
if (Places::checkType(nl->First(args))) return 7;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class Value, class Unit>
int the_unitSymbolicVM(Word* args, Word& result,
int message, Word& local, Supplier s) {
result = (qp->ResultStorage(s));
Unit *res = static_cast<Unit*>(result.addr);
Value *value = static_cast<Value*>(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;
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))) {
res->SetDefined(false); // illegal interval setting
return 0;
}
res->SetDefined(true);
if (*i1 < *i2) { // sorted instants
Interval<Instant> iv(*i1, *i2, clb, crb);
res->timeInterval = iv;
}
else {
Interval<Instant> iv(*i2, *i1, clb, crb);
res->timeInterval = iv;
}
res->constValue = *value;
return 0;
}
template<class Value, class Unit>
int the_unitIvSymbolicVM(Word* args, Word& result,
int message, Word& local, Supplier s) {
result = (qp->ResultStorage(s));
Unit *res = static_cast<Unit*>(result.addr);
Value *value = static_cast<Value*>(args[0].addr);
SecInterval *iv = static_cast<SecInterval*>(args[1].addr);
if (!value->IsDefined() || !iv->IsDefined()) {
res->SetDefined(false);
return 0;
}
res->SetDefined(true);
res->timeInterval = *iv;
res->constValue = *value;
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct the_unitSymbolicInfo : OperatorInfo {
the_unitSymbolicInfo() {
name = "the_unit";
signature = "label x instant x instant x bool x bool -> ulabel";
appendSignature("labels x instant x instant x bool x bool -> ulabels");
appendSignature("place x instant x instant x bool x bool -> uplace");
appendSignature("places x instant x instant x bool x bool -> uplaces");
appendSignature("label x interval -> ulabel");
appendSignature("labels x interval -> ulabels");
appendSignature("place x interval -> uplace");
appendSignature("places x interval -> uplaces");
syntax = "the_unit( _ _ _ _ _ ); the_unit( _ _ )";
meaning = "Creates a ulabel(s) / uplace(s) from its components.";
}
};
/*
\subsection{Operator ~makemvalue~}
makemvalue: stream (tuple ((x1 t1)...(xi uT)...(xn tn))) xi -> mT, with T in
{label, labels, place, places}
\subsubsection{Type Mapping}
*/
ListExpr makemvalueSymbolic_TM(ListExpr args) {
ListExpr first, second, rest, listn,
lastlistn, first2, second2, firstr, listfull, attrtype;
int j;
string argstr, argstr2, attrname, inputtype, inputname, fulllist;
if (nl->ListLength(args) != 2) {
return listutils::typeError("two arguments expected");
}
first = nl->First(args);
nl->WriteToString(argstr, first);
if (!listutils::isTupleStream(first)) {
ErrorReporter::ReportError("Operator makemvalue expects a tuplestream as "
"first argument, but gets '" + argstr + "'.");
return nl->TypeError();
}
second = nl->Second(args);
nl->WriteToString(argstr, second);
if(argstr == Symbol::TYPEERROR()){
return listutils::typeError("invalid attrname" + argstr);
}
nl->WriteToString(inputname, second);
rest = nl->Second(nl->Second(first));
listn = nl->OneElemList(nl->First(rest));
lastlistn = listn;
firstr = nl->First(rest);
rest = nl->Rest(rest);
first2 = nl->First(firstr);
second2 = nl->Second(firstr);
nl->WriteToString(attrname, first2);
nl->WriteToString(argstr2, second2);
if (attrname == inputname) {
inputtype = argstr2;
}
while (!(nl->IsEmpty(rest))) {
lastlistn = nl->Append(lastlistn,nl->First(rest));
firstr = nl->First(rest);
rest = nl->Rest(rest);
first2 = nl->First(firstr);
second2 = nl->Second(firstr);
nl->WriteToString(attrname, first2);
nl->WriteToString(argstr2, second2);
if (attrname == inputname) {
inputtype = argstr2;
}
}
rest = second;
listfull = listn;
nl->WriteToString(fulllist, listfull);
if (inputtype == "") {
return listutils::typeError("attribute not found");
}
if ((inputtype != ULabel::BasicType()) && (inputtype != ULabels::BasicType())
&& (inputtype != UPlace::BasicType()) && (inputtype != UPlaces::BasicType())){
return listutils::typeError("attribute type not in {ulabel, ulabels, uplace"
", uplaces}");
}
attrname = nl->SymbolValue(second);
j = FindAttribute(nl->Second(nl->Second(first)), attrname, attrtype);
assert(j != 0);
if (inputtype == ULabel::BasicType()) {
attrtype = nl->SymbolAtom(MLabel::BasicType());
}
else if (inputtype == ULabels::BasicType()) {
attrtype = nl->SymbolAtom(MLabels::BasicType());
}
else if (inputtype == UPlace::BasicType()) {
attrtype = nl->SymbolAtom(MPlace::BasicType());
}
else if (inputtype == UPlaces::BasicType()) {
attrtype = nl->SymbolAtom(MPlaces::BasicType());
}
return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
nl->TwoElemList(nl->IntAtom(j),
nl->StringAtom(nl->SymbolValue(attrtype))),
attrtype);
}
/*
\subsubsection{Selection Function}
*/
int makemvalueSymbolicSelect(ListExpr args) {
ListExpr first, second, rest, listn, lastlistn, first2, second2, firstr;
string argstr, argstr2, attrname, inputtype, inputname;
first = nl->First(args);
second = nl->Second(args);
nl->WriteToString(argstr, first);
nl->WriteToString(inputname, second);
rest = nl->Second(nl->Second(first));
listn = nl->OneElemList(nl->First(rest));
lastlistn = listn;
firstr = nl->First(rest);
rest = nl->Rest(rest);
first2 = nl->First(firstr);
second2 = nl->Second(firstr);
nl->WriteToString(attrname, first2);
nl->WriteToString(argstr2, second2);
if (attrname == inputname) {
inputtype = argstr2;
}
while (!(nl->IsEmpty(rest))) {
lastlistn = nl->Append(lastlistn,nl->First(rest));
firstr = nl->First(rest);
rest = nl->Rest(rest);
first2 = nl->First(firstr);
second2 = nl->Second(firstr);
nl->WriteToString(attrname, first2);
nl->WriteToString(argstr2, second2);
if (attrname == inputname) {
inputtype = argstr2;
}
}
if (inputtype == ULabel::BasicType()) return 0;
if (inputtype == ULabels::BasicType()) return 1;
if (inputtype == UPlace::BasicType()) return 2;
if (inputtype == UPlaces::BasicType()) return 3;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class Unit, class Mapping>
int makemvalueSymbolicVM(Word* args, Word& result, int message,
Word& local, Supplier s) {
Mapping* m;
Unit* unit;
Word curTupleWord;
assert(args[2].addr != 0);
assert(args[3].addr != 0);
int attrIndex = ((CcInt*)args[2].addr)->GetIntval() - 1;
qp->Open(args[0].addr);
qp->Request(args[0].addr, curTupleWord);
result = qp->ResultStorage(s);
m = (Mapping*)result.addr;
m->Clear();
m->SetDefined(true);
// m->StartBulkLoad();
while (qp->Received(args[0].addr)) { // get all tuples
Tuple* curTuple = (Tuple*)curTupleWord.addr;
Attribute* curAttr = (Attribute*)curTuple->GetAttribute(attrIndex);
if (curAttr == 0) {
cout << endl << "ERROR in " << __PRETTY_FUNCTION__
<< ": received Nullpointer!" << endl;
assert(false);
}
else if (curAttr->IsDefined()) {
unit = static_cast<Unit*>(curAttr);
// Unit unit(*((Unit*)curAttr));
m->MergeAdd(*unit); // in contrast to makemvalue2
}
// else {
// cerr << endl << __PRETTY_FUNCTION__ << ": Dropping undef unit. " << endl;
// }
curTuple->DeleteIfAllowed();
qp->Request(args[0].addr, curTupleWord);
}
m->EndBulkLoad(true, true);
qp->Close(args[0].addr);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct makemvalueSymbolicInfo : OperatorInfo {
makemvalueSymbolicInfo() {
name = "makemvalue";
signature = "stream (tuple ((x1 t1)...(xi uT)...(xn tn))) xi -> mT, with"
"T in {label, labels, place, places}";
syntax = "_ makemvalue[ _ ]";
meaning = "Creates a moving object from a (not necessarily sorted) tuple "
"stream containing a ulabel(s) or uplace(s) attribute. No two "
"unit time intervals may overlap. Undefined units are allowed "
"and will be ignored. A stream without defined units will "
"result in an \'empty\' moving object, not in an \'undef\'."
"Consecutive units with equal values are compressed.";
}
};
/*
\subsection{Operator ~makemvalue2~}
makemvalue: stream (tuple ((x1 t1)...(xi uT)...(xn tn))) xi -> mT, with T in
{label, labels, place, places}
*/
/*
\subsubsection{Value Mapping}
*/
template<class Unit, class Mapping>
int makemvalue2SymbolicVM(Word* args, Word& result, int message,
Word& local, Supplier s) {
Mapping* m;
Word curTupleWord;
assert(args[2].addr != 0);
assert(args[3].addr != 0);
int attrIndex = ((CcInt*)args[2].addr)->GetIntval() - 1;
qp->Open(args[0].addr);
qp->Request(args[0].addr, curTupleWord);
result = qp->ResultStorage(s);
m = (Mapping*)result.addr;
m->Clear();
m->SetDefined(true);
m->StartBulkLoad();
while (qp->Received(args[0].addr)) { // get all tuples
Tuple* curTuple = (Tuple*)curTupleWord.addr;
Attribute* curAttr = (Attribute*)curTuple->GetAttribute(attrIndex);
if (curAttr == 0) {
cout << endl << "ERROR in " << __PRETTY_FUNCTION__
<< ": received Nullpointer!" << endl;
assert(false);
}
else if (curAttr->IsDefined()) {
Unit unit(*((Unit*)curAttr));
m->Add(unit); // in contrast to makemvalue
}
else {
cerr << endl << __PRETTY_FUNCTION__ << ": Dropping undef unit. " << endl;
}
curTuple->DeleteIfAllowed();
qp->Request(args[0].addr, curTupleWord);
}
m->EndBulkLoad(true, true); // force Mapping to sort the units
qp->Close(args[0].addr); // and mark invalid Mapping as undefined
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct makemvalue2SymbolicInfo : OperatorInfo {
makemvalue2SymbolicInfo() {
name = "makemvalue2";
signature = "stream (tuple ((x1 t1)...(xi uT)...(xn tn))) xi -> mT, with"
"T in {label, labels, place, places}";
syntax = "_ makemvalue2[ _ ]";
meaning = "Creates a moving object from a (not necessarily sorted) tuple "
"stream containing a ulabel(s) or uplace(s) attribute. No two "
"unit time intervals may overlap. Undefined units are allowed "
"and will be ignored. A stream without defined units will "
"result in an \'empty\' moving object, not in an \'undef\'. "
"Consecutive units with equal values are NOT compressed.";
}
};
/*
\subsection{Operator ~passes~}
passes: mlabel x label -> bool
passes: mlabels x label -> bool
passes: mlabels x labels -> bool
passes: mplace x place -> bool
passes: mplaces x place -> bool
passes: mplaces x places -> bool
\subsubsection{Type Mapping}
*/
ListExpr passesSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 2)) {
ListExpr first(nl->First(args)), second(nl->Second(args));
if ((MLabel::checkType(first) && Label::checkType(second)) ||
(MLabel::checkType(first) && CcString::checkType(second)) ||
(MLabel::checkType(first) && FText::checkType(second)) ||
(MLabels::checkType(first) && Label::checkType(second)) ||
(MLabels::checkType(first) && Labels::checkType(second)) ||
(MLabels::checkType(first) && CcString::checkType(second)) ||
(MLabels::checkType(first) && FText::checkType(second)) ||
(MPlace::checkType(first) && Place::checkType(second)) ||
(MPlaces::checkType(first) && Place::checkType(second)) ||
(MPlaces::checkType(first) && Places::checkType(second))) {
return nl->SymbolAtom(CcBool::BasicType());
}
}
return listutils::typeError("Correct signatures: mlabel x label -> bool, "
"mlabel x string -> bool, mlabel x text -> bool, mlabels x label -> bool,"
" mlabels x labels -> bool, mlabels x string -> bool, mlabels x text -> "
"bool, mplace x place -> bool, mplaces x place -> bool, "
"mplaces x places -> bool");
}
/*
\subsubsection{Selection Function}
*/
int atPassesSymbolicSelect(ListExpr args) {
if (MLabel::checkType(nl->First(args))) {
if (Label::checkType(nl->Second(args))) return 0;
if (CcString::checkType(nl->Second(args))) return 1;
if (FText::checkType(nl->Second(args))) return 2;
}
if (MLabels::checkType(nl->First(args))) {
if (Label::checkType(nl->Second(args))) return 3;
if (Labels::checkType(nl->Second(args))) return 4;
if (CcString::checkType(nl->Second(args))) return 5;
if (FText::checkType(nl->Second(args))) return 6;
}
if (MPlace::checkType(nl->First(args))) return 7;
if (Place::checkType(nl->Second(args))) return 8;
if (Places::checkType(nl->Second(args))) return 9;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class Mapping, class Value>
int passesSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
CcBool* res = static_cast<CcBool*>(result.addr);
Mapping *m = static_cast<Mapping*>(args[0].addr);
Value *val = static_cast<Value*>(args[1].addr);
if (m->IsDefined() && val->IsDefined()) {
res->Set(true, m->Passes(*val));
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct passesSymbolicInfo : OperatorInfo {
passesSymbolicInfo() {
name = "passes";
signature = "mlabel x label -> bool";
appendSignature("mlabels x label -> bool");
appendSignature("mlabels x labels -> bool");
appendSignature("mplace x place -> bool");
appendSignature("mplaces x place -> bool");
appendSignature("mplaces x places -> bool");
syntax = "_ passes _ ";
meaning = "Returns TRUE if and only if the label(s) / place(s) occur(s) "
"at least once in the mlabel(s) / mplace(s).";
}
};
/*
\subsection{Operator ~at~}
at: mlabel x label -> mlabel
at: mlabels x label -> mlabels
at: mlabels x labels -> mlabels
at: mplace x place -> mplace
at: mplaces x place -> mplaces
at: mplaces x places -> mplace
\subsubsection{Type Mapping}
*/
ListExpr atSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 2)) {
ListExpr first(nl->First(args)), second(nl->Second(args));
if ((MLabel::checkType(first) && Label::checkType(second)) ||
(MLabel::checkType(first) && CcString::checkType(second)) ||
(MLabel::checkType(first) && FText::checkType(second))) {
return nl->SymbolAtom(MLabel::BasicType());
}
if ((MLabels::checkType(first) && Label::checkType(second)) ||
(MLabels::checkType(first) && Labels::checkType(second)) ||
(MLabels::checkType(first) && CcString::checkType(second)) ||
(MLabels::checkType(first) && FText::checkType(second))) {
return nl->SymbolAtom(MLabels::BasicType());
}
if (MPlace::checkType(first) && Place::checkType(second)) {
return nl->SymbolAtom(MPlace::BasicType());
}
if ((MPlaces::checkType(first) && Place::checkType(second)) ||
(MPlaces::checkType(first) && Places::checkType(second))) {
return nl->SymbolAtom(MPlaces::BasicType());
}
}
return listutils::typeError("Correct signatures: mlabel x label -> mlabel, "
"mlabel x string -> mlabel, mlabel x text -> mlabel, mlabels x label -> "
"mlabels, mlabels x labels -> mlabels, mlabels x string -> mlabel, "
"mlabels x text -> mlabel, mplace x place -> mplace, mplaces x place -> "
"mplaces, mplaces x places -> mplaces");
}
/*
\subsubsection{Value Mapping}
*/
template<class Mapping, class Value>
int atSymbolicVM(Word* args, Word& result, int message, Word& local,Supplier s){
result = qp->ResultStorage(s);
Mapping *src = static_cast<Mapping*>(args[0].addr);
Value *val = static_cast<Value*>(args[1].addr);
Mapping *res = static_cast<Mapping*>(result.addr);
src->At(*val, *res);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct atSymbolicInfo : OperatorInfo {
atSymbolicInfo() {
name = "at";
signature = "mlabel x label -> mlabel";
appendSignature("mlabels x label -> mlabels");
appendSignature("mlabels x labels -> mlabels");
appendSignature("mplace x place -> mplace");
appendSignature("mplaces x place -> mplace");
appendSignature("mplaces x places -> mplaces");
syntax = "_ at _ ";
meaning = "Reduces the mlabel(s) / mplace(s) to those units whose "
"label(s) / place(s) equals the label(s) / place(s).";
}
};
/*
\subsection{Operator ~deftime~}
deftime: mlabel -> periods
deftime: mlabels -> periods
deftime: mplace -> periods
deftime: mplaces -> periods
\subsubsection{Type Mapping}
*/
ListExpr deftimeSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 1)) {
ListExpr first = nl->First(args);
if (MLabel::checkType(first) || MLabels::checkType(first) ||
MPlace::checkType(first) || MPlaces::checkType(first)) {
return nl->SymbolAtom(Periods::BasicType());
}
}
return listutils::typeError("Correct signature: mlabel -> periods, "
"mlabels -> periods, mplace -> periods, mplaces -> periods");
}
/*
\subsubsection{Selection Function}
*/
int symbolicSimpleSelect(ListExpr args) {
if (MLabel::checkType(nl->First(args))) return 0;
if (MLabels::checkType(nl->First(args))) return 1;
if (MPlace::checkType(nl->First(args))) return 2;
if (MPlaces::checkType(nl->First(args))) return 3;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class Mapping>
int deftimeSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Periods* res = static_cast<Periods*>(result.addr);
Mapping *src = static_cast<Mapping*>(args[0].addr);
src->DefTime(*res);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct deftimeSymbolicInfo : OperatorInfo {
deftimeSymbolicInfo() {
name = "deftime";
signature = "mlabel -> periods";
appendSignature("mlabels -> periods");
appendSignature("mplace -> periods");
appendSignature("mplaces -> periods");
syntax = "deftime ( _ )";
meaning = "Returns the periods containing the time intervals during which"
"the mlabel(s) / mplace(s) is defined.";
}
};
/*
\subsection{Operator ~atinstant~}
atinstant: mlabel x instant -> ilabel
atinstant: mlabels x instant -> ilabels
atinstant: mplace x instant -> iplace
atinstant: mplaces x instant -> iplaces
\subsubsection{Type Mapping}
*/
ListExpr atinstantSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 2)) {
if (Instant::checkType(nl->Second(args))) {
if (MLabel::checkType(nl->First(args))) {
return nl->SymbolAtom(ILabel::BasicType());
}
if (MLabels::checkType(nl->First(args))) {
return nl->SymbolAtom(ILabels::BasicType());
}
if (MPlace::checkType(nl->First(args))) {
return nl->SymbolAtom(IPlace::BasicType());
}
if (MPlaces::checkType(nl->First(args))) {
return nl->SymbolAtom(IPlaces::BasicType());
}
}
}
return listutils::typeError("Correct signature: mT x instant -> iT, with "
"T in {label(s), place(s)}");
}
/*
\subsubsection{Value Mapping}
*/
template<class Mapping, class Intime>
int atinstantSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Mapping *src = static_cast<Mapping*>(args[0].addr);
Instant *inst = static_cast<Instant*>(args[1].addr);
Intime *res = static_cast<Intime*>(result.addr);
src->AtInstant(*inst, *res);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct atinstantSymbolicInfo : OperatorInfo {
atinstantSymbolicInfo() {
name = "atinstant";
signature = "mlabel x instant -> ilabel";
appendSignature("mlabels x instant -> ilabels");
appendSignature("mplace x instant -> iplace");
appendSignature("mplaces x instant -> iplaces");
syntax = "_ atinstant _";
meaning = "Gets the intime value from a moving object corresponding to "
"the temporal value at the given instant.";
}
};
/*
\subsection{Operator ~atperiods~}
atperiods: mlabel x periods -> mlabel
atperiods: mlabels x periods -> mlabels
atperiods: mplace x periods -> mplace
atperiods: mplaces x periods -> mplaces
\subsubsection{Type Mapping}
*/
ListExpr atperiodsSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 2)) {
if (Periods::checkType(nl->Second(args))) {
ListExpr first = nl->First(args);
if (MLabel::checkType(first) || MLabels::checkType(first) ||
MPlace::checkType(first) || MPlaces::checkType(first)) {
return nl->First(args);
}
}
}
return listutils::typeError("Correct signature: mT x periods -> mT, with "
"T in {label(s), place(s)}");
}
/*
\subsubsection{Value Mapping}
*/
template<class M>
int atperiodsSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
M *src = static_cast<M*>(args[0].addr);
Periods *per = static_cast<Periods*>(args[1].addr);
M *res = static_cast<M*>(result.addr);
src->AtPeriods(*per, *res);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct atperiodsSymbolicInfo : OperatorInfo {
atperiodsSymbolicInfo() {
name = "atperiods";
signature = "mlabel x periods -> mlabel";
appendSignature("mlabels x periods -> mlabels");
appendSignature("mplace x periods -> mplace");
appendSignature("mplaces x periods -> mplaces");
syntax = "_ atperiods _";
meaning = "Restrict the moving object to the given periods.";
}
};
/*
\subsection{Operator ~no\_components~}
no\_components: mlabel -> int
no\_components: mlabels -> int
no\_components: mplace -> int
no\_components: mplaces -> int
no\_components: labels -> int
no\_components: places -> int
\subsubsection{Type Mapping}
*/
ListExpr nocomponentsSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 1)) {
ListExpr first = nl->First(args);
if (MLabel::checkType(first) || MLabels::checkType(first) ||
MPlace::checkType(first) || MPlaces::checkType(first) ||
Labels::checkType(first) || Places::checkType(first)) {
return nl->SymbolAtom(CcInt::BasicType());
}
}
return listutils::typeError("Expects a symbolic trajectory or a labels/places"
"object.");
}
/*
\subsubsection{Selection Function}
*/
int nocomponentsSymbolicSelect(ListExpr args) {
if (MLabel::checkType(nl->First(args))) return 0;
if (MLabels::checkType(nl->First(args))) return 1;
if (MPlace::checkType(nl->First(args))) return 2;
if (MPlaces::checkType(nl->First(args))) return 3;
if (Labels::checkType(nl->First(args))) return 4;
if (Places::checkType(nl->First(args))) return 5;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class Coll>
int nocomponentsSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
CcInt* res = static_cast<CcInt*>(result.addr);
Coll *src = static_cast<Coll*>(args[0].addr);
if (src->IsDefined()) {
res->Set(true, src->GetNoComponents());
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct nocomponentsSymbolicInfo : OperatorInfo {
nocomponentsSymbolicInfo() {
name = "no_components";
signature = "mlabel -> int";
appendSignature("mlabels -> int");
appendSignature("mplace -> int");
appendSignature("mplaces -> int");
appendSignature("labels -> int");
appendSignature("places -> int");
syntax = "no_components ( _ )";
meaning = "Returns the number of units of the symbolic trajectory or the "
"number of components of a labels/places object.";
}
};
/*
\subsection{Operator ~getInterval~}
This operator returns the interval of a symbolic unit or the bounding interval
of a symbolic trajectory.
\subsubsection{Type Mapping}
*/
ListExpr getIntervalSymbolicTM(ListExpr args) {
if (!nl->HasLength(args, 1)) {
return listutils::typeError("One argument expected.");
}
if (!MLabel::checkType(nl->First(args)) &&
!MLabels::checkType(nl->First(args)) &&
!MPlace::checkType(nl->First(args)) &&
!MPlaces::checkType(nl->First(args)) &&
!ULabel::checkType(nl->First(args)) &&
!ULabels::checkType(nl->First(args)) &&
!UPlace::checkType(nl->First(args)) &&
!UPlaces::checkType(nl->First(args))) {
return listutils::typeError("Symbolic trajectory or symbolic unit "
"expected.");
}
return nl->SymbolAtom(SecInterval::BasicType());
}
/*
\subsubsection{Selection Function}
*/
int getIntervalSymbolicSelect(ListExpr args) {
if (MLabel::checkType(nl->First(args))) return 0;
if (MLabels::checkType(nl->First(args))) return 1;
if (MPlace::checkType(nl->First(args))) return 2;
if (MPlaces::checkType(nl->First(args))) return 3;
if (ULabel::checkType(nl->First(args))) return 4;
if (ULabels::checkType(nl->First(args))) return 5;
if (UPlace::checkType(nl->First(args))) return 6;
if (UPlaces::checkType(nl->First(args))) return 7;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class M>
int getIntervalSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
M *src = static_cast<M*>(args[0].addr);
SecInterval *res = static_cast<SecInterval*>(result.addr);
if (src->IsDefined()) {
src->GetInterval(*res);
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct getIntervalSymbolicInfo : OperatorInfo {
getIntervalSymbolicInfo() {
name = "getInterval";
signature = "mlabel -> interval";
appendSignature("mlabels -> interval");
appendSignature("mplace -> interval");
appendSignature("mplaces -> interval");
appendSignature("ulabel -> interval");
appendSignature("ulabels -> interval");
appendSignature("uplace -> interval");
appendSignature("uplaces -> interval");
syntax = "getInterval ( _ )";
meaning = "This operator returns the interval of a symbolic unit or the "
"bounding interval of a symbolic trajectory.";
}
};
/*
\subsection{Operator ~getunit~}
getunit: mlabel x int -> ulabel
getunit: mlabels x int -> ulabels
getunit: mplace x int -> uplace
getunit: mplaces x int -> uplaces
\subsubsection{Type Mapping}
*/
ListExpr getunitSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 2)) {
if (CcInt::checkType(nl->Second(args))) {
ListExpr first = nl->First(args);
if (MLabel::checkType(first)) {
return nl->SymbolAtom(ULabel::BasicType());
}
if (MLabels::checkType(first)) {
return nl->SymbolAtom(ULabels::BasicType());
}
if (MPlace::checkType(first)) {
return nl->SymbolAtom(UPlace::BasicType());
}
if (MPlaces::checkType(first)) {
return nl->SymbolAtom(UPlaces::BasicType());
}
}
}
return listutils::typeError("Expects a symbolic trajectory and an integer.");
}
/*
\subsubsection{Value Mapping}
*/
template<class M, class U>
int getunitSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
M *src = static_cast<M*>(args[0].addr);
CcInt* pos = static_cast<CcInt*>(args[1].addr);
U *res = static_cast<U*>(result.addr);
if (src->IsDefined() && pos->IsDefined()) {
if (pos->GetIntval() < src->GetNoComponents() && pos->GetIntval() >= 0) {
src->Get(pos->GetIntval(), *res);
}
else {
res->SetDefined(false);
}
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct getunitSymbolicInfo : OperatorInfo {
getunitSymbolicInfo() {
name = "getunit";
signature = "mlabel x int -> ulabel";
appendSignature("mlabels x int -> ulabels");
appendSignature("mplace x int -> uplace");
appendSignature("mplaces x int -> uplaces");
syntax = "getunit ( _, _ )";
meaning = "Returns the unit located at a certain position of the symbolic"
"trajectory.";
}
};
/*
\subsection{Operator ~getPosition~}
getPosition: mlabel x instant -> int
getPosition: mlabels x instant -> int
getPosition: mplace x instant -> int
getPosition: mplaces x instant -> int
\subsubsection{Type Mapping}
*/
ListExpr getPositionSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 2)) {
if (Instant::checkType(nl->Second(args))) {
ListExpr first = nl->First(args);
if (MLabel::checkType(first) || MLabels::checkType(first) ||
MPlace::checkType(first) || MPlaces::checkType(first)) {
return nl->SymbolAtom(CcInt::BasicType());
}
}
}
return listutils::typeError("Expects a moving(alpha) and an instant.");
}
/*
\subsubsection{Selection Function}
*/
int getPositionSymbolicSelect(ListExpr args) {
if (MLabel::checkType(nl->First(args))) return 0;
if (MLabels::checkType(nl->First(args))) return 1;
if (MPlace::checkType(nl->First(args))) return 2;
if (MPlaces::checkType(nl->First(args))) return 3;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class M>
int getPositionSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
CcInt *res = static_cast<CcInt*>(result.addr);
M *m = static_cast<M*>(args[0].addr);
Instant *inst = static_cast<Instant*>(args[1].addr);
if (!m->IsDefined() || !inst->IsDefined()) {
res->SetDefined(false);
return 0;
}
int pos = m->Position(*inst);
if (pos == -1) {
res->SetDefined(false);
return 0;
}
res->Set(true, m->Position(*inst));
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct getPositionSymbolicInfo : OperatorInfo {
getPositionSymbolicInfo() {
name = "getPosition";
signature = "mlabel x instant -> int";
appendSignature("mlabels x instant -> int");
appendSignature("mplace x instant -> int");
appendSignature("mplaces x instant -> int");
syntax = "getPosition ( _, _ )";
meaning = "Returns the unit position inside the moving object that "
"corresponds to the instant";
}
};
/*
\subsection{Operator ~units~}
units: mlabel -> (stream ulabel)
units: mlabels -> (stream ulabels)
units: mplace -> (stream uplace)
units: mplaces -> (stream uplaces)
\subsubsection{Type Mapping}
*/
ListExpr unitsSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 1)) {
if (MLabel::checkType(nl->First(args))) {
return nl->TwoElemList(nl->SymbolAtom(Stream<Attribute>::BasicType()),
nl->SymbolAtom(ULabel::BasicType()));
}
if (MLabels::checkType(nl->First(args))) {
return nl->TwoElemList(nl->SymbolAtom(Stream<Attribute>::BasicType()),
nl->SymbolAtom(ULabels::BasicType()));
}
if (MPlace::checkType(nl->First(args))) {
return nl->TwoElemList(nl->SymbolAtom(Stream<Attribute>::BasicType()),
nl->SymbolAtom(UPlace::BasicType()));
}
if (MPlaces::checkType(nl->First(args))) {
return nl->TwoElemList(nl->SymbolAtom(Stream<Attribute>::BasicType()),
nl->SymbolAtom(UPlaces::BasicType()));
}
}
return listutils::typeError("Correct signatures: mT -> (stream uT), with "
"T in {label(s), place(s)}");
}
/*
\subsubsection{Value Mapping}
*/
template<class Mapping, class Unit>
int unitsSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
Mapping *source = static_cast<Mapping*>(args[0].addr);
UnitsLI *li = static_cast<UnitsLI*>(local.addr);
switch (message) {
case OPEN: {
if (li) {
li = 0;
}
li = new UnitsLI();
local.addr = li;
return 0;
}
case REQUEST: {
if (!local.addr) {
result.addr = 0;
return CANCEL;
}
li = (UnitsLI*)local.addr;
if (li->index < source->GetNoComponents()) {
Unit unit(true);
source->Get(li->index, unit);
li->index++;
result = SetWord(unit.Clone());
return YIELD;
}
else {
return CANCEL;
}
}
case CLOSE: {
if (local.addr) {
li = (UnitsLI*)local.addr;
delete li;
local.addr = 0;
}
return 0;
}
}
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct unitsSymbolicInfo : OperatorInfo {
unitsSymbolicInfo() {
name = "units";
signature = "mT -> (stream uT), with T in {label(s), place(s)}";
syntax = "units ( _ )";
meaning = "Splits a mlabel(s) / mplace(s) into its units and returns them "
"as a stream.";
}
};
/*
\subsection{Operator ~initial~}
initial: XT -> iT with X in {u, m} and T in {label(s), place(s)}
\subsubsection{Type Mapping}
*/
ListExpr initialFinalSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 1)) {
ListExpr first = nl->First(args);
if (ULabel::checkType(first) || MLabel::checkType(first)) {
return nl->SymbolAtom(ILabel::BasicType());
}
if (ULabels::checkType(first) || MLabels::checkType(first)) {
return nl->SymbolAtom(ILabels::BasicType());
}
if (UPlace::checkType(first) || MPlace::checkType(first)) {
return nl->SymbolAtom(IPlace::BasicType());
}
if (UPlaces::checkType(first) || MPlaces::checkType(first)) {
return nl->SymbolAtom(IPlaces::BasicType());
}
}
return listutils::typeError("Correct signature: XT -> iT with X in {u, m} "
"and T in {label(s), place(s)}");
}
/*
\subsubsection{Selection Function}
*/
int initialFinalSymbolicSelect(ListExpr args) {
if (ULabel::checkType(nl->First(args))) return 0;
if (ULabels::checkType(nl->First(args))) return 1;
if (MLabel::checkType(nl->First(args))) return 2;
if (MLabels::checkType(nl->First(args))) return 3;
if (UPlace::checkType(nl->First(args))) return 4;
if (UPlaces::checkType(nl->First(args))) return 5;
if (MPlace::checkType(nl->First(args))) return 6;
if (MPlaces::checkType(nl->First(args))) return 7;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class UnitMapping, class Intime>
int initialSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Intime* res = static_cast<Intime*>(result.addr);
UnitMapping *src = static_cast<UnitMapping*>(args[0].addr);
src->Initial(*res);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct initialSymbolicInfo : OperatorInfo {
initialSymbolicInfo() {
name = "initial";
signature = "XT -> iT with X in {u, m} and T in {label(s), place(s)}";
syntax = "initial ( _ )";
meaning = "Returns the ilabel(s) belonging to the initial instant of the "
"ulabel(s) / mlabel(s) / uplace(s) / mplace(s).";
}
};
/*
\subsection{Operator ~final~}
final: XT -> iT with X in {u, m} and T in {label(s), place(s)}
\subsubsection{Value Mapping}
*/
template<class UnitMapping, class Intime>
int finalSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Intime* res = static_cast<Intime*>(result.addr);
UnitMapping *src = static_cast<UnitMapping*>(args[0].addr);
src->Final(*res);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct finalSymbolicInfo : OperatorInfo {
finalSymbolicInfo() {
name = "final";
signature = "XT -> iT with X in {u, m} and T in {label(s), place(s)}";
syntax = "final ( _ )";
meaning = "Returns the ilabel(s) belonging to the final instant of the "
"ulabel(s) / mlabel(s) / uplace(s) / mplace(s).";
}
};
/*
\subsection{Operator ~val~}
val: ilabel -> label
val: ilabels -> labels
val: iplace -> place
val: iplaces -> places
\subsubsection{Type Mapping}
*/
ListExpr valSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 1)) {
if (ILabel::checkType(nl->First(args))) {
return nl->SymbolAtom(Label::BasicType());
}
if (ILabels::checkType(nl->First(args))) {
return nl->SymbolAtom(Labels::BasicType());
}
if (IPlace::checkType(nl->First(args))) {
return nl->SymbolAtom(Place::BasicType());
}
if (IPlaces::checkType(nl->First(args))) {
return nl->SymbolAtom(Places::BasicType());
}
}
return listutils::typeError("Correct signature: ilabel -> label, "
"ilabels -> labels, iplace -> place, iplaces -> places");
}
/*
\subsubsection{Selection Function}
*/
int valInstSymbolicSelect(ListExpr args) {
if (ILabel::checkType(nl->First(args))) return 0;
if (ILabels::checkType(nl->First(args))) return 1;
if (IPlace::checkType(nl->First(args))) return 2;
if (IPlaces::checkType(nl->First(args))) return 3;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class Intime, class L>
int valSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
L* res = static_cast<L*>(result.addr);
Intime *src = static_cast<Intime*>(args[0].addr);
src->Val(*res);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct valSymbolicInfo : OperatorInfo {
valSymbolicInfo() {
name = "val";
signature = "ilabel -> label";
appendSignature("ilabels -> labels");
appendSignature("iplace -> place");
appendSignature("iplaces -> places");
syntax = "val ( _ )";
meaning = "Returns the value of the ilabel(s) or the iplace(s).";
}
};
/*
\subsection{Operator ~inst~}
inst: ilabel -> instant
inst: ilabels -> instant
inst: iplace -> instant
inst: iplaces -> instant
\subsubsection{Type Mapping}
*/
ListExpr instSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 1)) {
if (ILabel::checkType(nl->First(args)) ||
ILabels::checkType(nl->First(args)) ||
IPlace::checkType(nl->First(args)) ||
IPlaces::checkType(nl->First(args))) {
return nl->SymbolAtom(Instant::BasicType());
}
}
return listutils::typeError("Correct signature: ilabel -> instant, "
"ilabels -> instant, iplace -> instant, iplaces -> instant");
}
/*
\subsubsection{Value Mapping}
*/
template<class Intime>
int instSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Instant* res = static_cast<Instant*>(result.addr);
Intime *src = static_cast<Intime*>(args[0].addr);
if (src->IsDefined()) {
res->CopyFrom(&(src->instant));
}
else {
res->SetDefined(false);
}
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct instSymbolicInfo : OperatorInfo {
instSymbolicInfo() {
name = "inst";
signature = "ilabel -> instant";
appendSignature("ilabels -> instant");
appendSignature("iplace -> instant");
appendSignature("iplaces -> instant");
syntax = "inst ( _ )";
meaning = "Returns the instant of the ilabel(s) or the iplace(s).";
}
};
/*
\subsection{Operator ~inside~}
inside: mlabel x labels -> mbool
inside: mplace x places -> mbool
\subsubsection{Type Mapping}
*/
ListExpr insideSymbolicTM(ListExpr args) {
if (nl->HasLength(args, 2)) {
ListExpr first(nl->First(args)), second(nl->Second(args));
if ((MLabel::checkType(first) && Labels::checkType(second)) ||
(MPlace::checkType(first) && Places::checkType(second))) {
return nl->SymbolAtom(MBool::BasicType());
}
}
return listutils::typeError("Correct signatures: mlabel x labels -> mbool, "
" mplace x places -> mbool");
}
/*
\subsubsection{Selection Function}
*/
int insideSymbolicSelect(ListExpr args) {
if (MLabel::checkType(nl->First(args))) return 0;
if (MPlace::checkType(nl->First(args))) return 1;
return -1;
}
/*
\subsubsection{Value Mapping}
*/
template<class Mapping, class Collection>
int insideSymbolicVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
MBool* res = static_cast<MBool*>(result.addr);
Mapping *src = static_cast<Mapping*>(args[0].addr);
Collection *coll = static_cast<Collection*>(args[1].addr);
src->Inside(*coll, *res);
return 0;
}
/*
\subsubsection{Operator Info}
*/
struct insideSymbolicInfo : OperatorInfo {
insideSymbolicInfo() {
name = "inside";
signature = "mlabel x labels -> mbool";
appendSignature("mplace x places -> mbool");
syntax = "_ inside _";
meaning = "Returns a mbool with the same time intervals as the mlabel / "
"mplace. A unit\'s value is TRUE if and only if the label / "
"place is an element of the labels / places.";
}
};
/*
\section{Operator ~concat~}
\subsection{Type Mapping}
*/
ListExpr concatTM(ListExpr args) {
const string errMsg = "Expecting two symbolic trajectories of the same type.";
if (!nl->HasLength(args, 2)) {
return listutils::typeError(errMsg);
}
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if ((MLabel::checkType(arg1) && MLabel::checkType(arg2)) ||
(MLabels::checkType(arg1) && MLabels::checkType(arg2)) ||
(MPlace::checkType(arg1) && MPlace::checkType(arg2)) ||
(MPlaces::checkType(arg1) && MPlaces::checkType(arg2))) {
return arg1;
}
return listutils::typeError(errMsg);
}
/*
\subsection{Value Mapping}
*/
template<class T>
int concatVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T* src1 = static_cast<T*>(args[0].addr);
T* src2 = static_cast<T*>(args[1].addr);
result = qp->ResultStorage(s);
T* res = (T*)result.addr;
res->Concat(*src1, *src2);
return 0;
}
struct concatInfo : OperatorInfo {
concatInfo() {
name = "concat";
signature = "mT x mT -> mT, where T in {label(s), place(s)}";
syntax = "concat _ _";
meaning = "Concatenates two symbolic trajectories into one.";
}
};
/*
\section{Operator ~compress~}
\subsection{Type Mapping}
*/
ListExpr compressTM(ListExpr args) {
const string errMsg = "Expecting mT, T in {label, labels, place, places}";
if (!nl->HasLength(args, 1)) {
return listutils::typeError(errMsg);
}
ListExpr arg = nl->First(args);
if (MLabel::checkType(arg) || MLabels::checkType(arg) ||
MPlace::checkType(arg) || MPlaces::checkType(arg)) {
return arg;
}
return listutils::typeError(errMsg);
}
/*
\subsection{Selection Function}
*/
int compressSelect(ListExpr args) {
ListExpr arg = nl->First(args);
if (MLabel::checkType(arg)) return 0;
if (MLabels::checkType(arg)) return 1;
if (MPlace::checkType(arg)) return 2;
if (MPlaces::checkType(arg)) return 3;
return -1;
}
/*
\subsection{Value Mapping (for a single MLabel)}
*/
template<class T>
int compressVM(Word* args, Word& result, int message, Word& local, Supplier s) {
T* source = static_cast<T*>(args[0].addr);
result = qp->ResultStorage(s);
T* res = (T*)result.addr;
source->Compress(*res);
return 0;
}
/*
\subsection{Operator Info}
*/
struct compressInfo : OperatorInfo {
compressInfo() {
name = "compress";
signature = "mT -> mT, where T in {label(s), place(s)}";
syntax = "compress(_)";
meaning = "Unites temporally subsequent units with the same values.";
}
};
/*
\section{Operator ~fillgaps~}
\subsection{Type Mapping}
*/
ListExpr fillgapsTM(ListExpr args) {
string errMsg = "Expecting one argument of type mlabel or mstring and one of"
" type integer.";
if (nl->ListLength(args) != 2) {
return listutils::typeError("Two arguments expected.");
}
ListExpr arg = nl->First(args);
if ((MLabel::checkType(arg) || MLabels::checkType(arg) ||
MPlace::checkType(arg) || MPlaces::checkType(arg) ||
Stream<MLabel>::checkType(arg) || Stream<MLabels>::checkType(arg) ||
Stream<MPlace>::checkType(arg) || Stream<MPlaces>::checkType(arg))
&& CcInt::checkType(nl->Second(args))) {
return arg;
}
else {
return listutils::typeError(errMsg);
}
}
/*
\subsection{Selection Function}
*/
int fillgapsSelect(ListExpr args) {
ListExpr arg = nl->First(args);
if (MLabel::checkType(arg)) return 0;
if (MLabels::checkType(arg)) return 1;
if (MPlace::checkType(arg)) return 2;
if (MPlaces::checkType(arg)) return 3;
if (Stream<MLabel>::checkType(arg)) return 4;
if (Stream<MLabels>::checkType(arg)) return 5;
if (Stream<MPlace>::checkType(arg)) return 6;
if (Stream<MPlaces>::checkType(arg)) return 7;
return -1;
}
/*
\subsection{Value Mapping (for MLabel or MString)}
*/
template<class T>
int fillgapsVM_1(Word* args, Word& result, int message, Word& local,
Supplier s) {
T* source = (T*)(args[0].addr);
CcInt* ccDur = (CcInt*)(args[1].addr);
result = qp->ResultStorage(s);
T* res = (T*)result.addr;
DateTime dur(0, ccDur->GetValue(), durationtype);
source->Fill(*res, dur);
return 0;
}
/*
\subsection{Value Mapping (for a stream of MLabels)}
*/
template<class T>
int fillgapsVM_Str(Word* args, Word& result, int message, Word& local,
Supplier s){
CcInt* ccInt = 0;
switch (message) {
case OPEN: {
qp->Open(args[0].addr);
ccInt = (CcInt*)(args[1].addr);
local.addr = ccInt;
return 0;
}
case REQUEST: {
if (!local.addr) {
result.addr = 0;
return CANCEL;
}
Word arg;
qp->Request(args[0].addr, arg);
if (qp->Received(args[0].addr)) {
ccInt = (CcInt*)local.addr;
T* source =(T*)arg.addr;
T* res = new T(1);
DateTime dur(0, ccInt->GetValue(), durationtype);
source->Fill(*res, dur);
result.addr = res;
return YIELD;
}
else {
return CANCEL;
}
}
case CLOSE:{
qp->Close(args[0].addr);
local.addr=0;
return 0;
}
}
return 0;
}
/*
\subsection{Operator Info for operator ~fillgaps~}
*/
struct fillgapsInfo : OperatorInfo {
fillgapsInfo() {
name = "fillgaps";
signature = "mT -> mT, where T in {label(s), place(s)}";
appendSignature("stream(mT) -> stream(mT), where T in {label(s), "
"place(s)}");
syntax = "fillgaps(_)";
meaning = "Fills temporal gaps between two (not temporally) subsequent "
"units inside the symbolic trajectory if the values coincide";
}
};
class SymbolicTrajectoryBasicAlgebra : public Algebra {
public:
SymbolicTrajectoryBasicAlgebra() : Algebra() {
AddTypeConstructor(&label);
AddTypeConstructor(&ilabel);
AddTypeConstructor(&ulabel);
AddTypeConstructor(&mlabel);
AddTypeConstructor(&labels);
AddTypeConstructor(&ilabels);
AddTypeConstructor(&ulabels);
AddTypeConstructor(&mlabels);
AddTypeConstructor(&place);
AddTypeConstructor(&places);
AddTypeConstructor(&iplace);
AddTypeConstructor(&iplaces);
AddTypeConstructor(&uplace);
AddTypeConstructor(&uplaces);
AddTypeConstructor(&mplace);
AddTypeConstructor(&mplaces);
label.AssociateKind(Kind::DATA());
ilabel.AssociateKind(Kind::DATA());
ilabel.AssociateKind(Kind::TEMPORAL());
ulabel.AssociateKind(Kind::DATA());
ulabel.AssociateKind(Kind::TEMPORAL());
mlabel.AssociateKind(Kind::DATA());
mlabel.AssociateKind(Kind::TEMPORAL());
labels.AssociateKind(Kind::DATA());
ilabels.AssociateKind(Kind::DATA());
ilabels.AssociateKind(Kind::TEMPORAL());
ulabels.AssociateKind(Kind::DATA());
ulabels.AssociateKind(Kind::TEMPORAL());
mlabels.AssociateKind(Kind::DATA());
mlabels.AssociateKind(Kind::TEMPORAL());
place.AssociateKind(Kind::DATA());
iplace.AssociateKind(Kind::DATA());
iplace.AssociateKind(Kind::TEMPORAL());
uplace.AssociateKind(Kind::DATA());
uplace.AssociateKind(Kind::TEMPORAL());
mplace.AssociateKind(Kind::DATA());
mplace.AssociateKind(Kind::TEMPORAL());
places.AssociateKind(Kind::DATA());
iplaces.AssociateKind(Kind::DATA());
iplaces.AssociateKind(Kind::TEMPORAL());
uplaces.AssociateKind(Kind::DATA());
uplaces.AssociateKind(Kind::TEMPORAL());
mplaces.AssociateKind(Kind::DATA());
mplaces.AssociateKind(Kind::TEMPORAL());
ValueMapping tolabelVMs[] = {tolabelVM<FText>, tolabelVM<CcString>, 0};
AddOperator(tolabelInfo(), tolabelVMs, tolabelSelect, tolabelTM);
AddOperator(tostringInfo(), tostringVM, tostringTM);
AddOperator(totextInfo(), totextVM, totextTM);
AddOperator(mstringtomlabelInfo(), mstringtomlabelVM, mstringtomlabelTM);
ValueMapping tolabelsVMs[] = {tolabelsVM<FText>, tolabelsVM<CcString>, 0};
AddOperator(tolabelsInfo(), tolabelsVMs, tolabelsSelect, tolabelsTM);
ValueMapping toplacesVMs[] = {toplacesVM_P, toplacesVM_T, 0};
AddOperator(toplacesInfo(), toplacesVMs, toplacesSelect, toplacesTM);
ValueMapping collect_labelsVMs[] = {collect_labelsVM<Label>,
collect_labelsVM<CcString>, collect_labelsVM<FText>, 0};
AddOperator(collect_labelsInfo(), collect_labelsVMs, collect_labelsSelect,
collect_labelsTM);
ValueMapping containsVMs[] = {containsSingleVM<Labels, Label>,
containsSingleVM<Places, Place>, containsMultiVM<Labels, Labels>,
containsMultiVM<Places, Places>, containsBasicVM<CcString>,
containsBasicVM<FText>, 0};
AddOperator(containsInfo(), containsVMs, containsSelect, containsTM);
ValueMapping intersectsVMs[] = {intersectsVM<Labels>, intersectsVM<Places>,0};
AddOperator(intersectsInfo(), intersectsVMs, intersectsSelect, intersectsTM);
ValueMapping toplaceVMs[] = {toplaceVM<CcString>, toplaceVM<FText>, 0};
AddOperator(toplaceInfo(), toplaceVMs, toplaceSelect, toplaceTM);
AddOperator(nameInfo(), nameVM, nameTM);
AddOperator(refInfo(), refVM, refTM);
ValueMapping equalsVMs[] = {equalsVM<Label>, equalsVM<Labels>,
equalsVM<Place>, equalsVM<Places>, equalsVM<Label, CcString>,
equalsVM<Label, FText>, equalsVM<CcString, Label>, equalsVM<FText, Label>,
0};
AddOperator(equalsInfo(), equalsVMs, equalsUnequalsSelect, equalsUnequalsTM);
ValueMapping unequalsVMs[] = {unequalsVM<Label>, unequalsVM<Labels>,
unequalsVM<Place>, unequalsVM<Places>, unequalsVM<Label, CcString>,
unequalsVM<Label, FText>, unequalsVM<CcString, Label>,
unequalsVM<FText, Label>, 0};
AddOperator(unequalsInfo(), unequalsVMs, equalsUnequalsSelect,
equalsUnequalsTM);
ValueMapping unionVMs[] = {unionVM<Label, Label, Labels>,
unionVM<Labels, Label, Labels>, unionVM<Label, Labels, Labels>,
unionVM<Labels, Labels, Labels>, unionVM<Place, Place, Places>,
unionVM<Places, Place, Places>, unionVM<Place, Places, Places>,
unionVM<Places, Places, Places>, 0};
AddOperator(unionInfo(), unionVMs, unionSelect, unionTM);
ValueMapping intersectionVMs[] = {intersectionVM<Labels>,
intersectionVM<Places>, 0};
AddOperator(intersectionInfo(), intersectionVMs, intersectionSelect,
intersectionTM);
ValueMapping minusVMs[] = {minusVM<Labels, Label>, minusVM<Labels, Labels>,
minusVM<Places, Place>, minusVM<Places, Places>, 0};
AddOperator(minusInfo(), minusVMs, minusSelect, minusTM);
#ifdef RECODE
ValueMapping recodeVMs[] = {recodeVM<MLabel>, recodeVM<MLabels>, 0};
AddOperator(recodeInfo(), recodeVMs, recodeSelect, recodeTM);
#endif
ValueMapping the_unitSymbolicVMs[] = {the_unitSymbolicVM<Label, ULabel>,
the_unitSymbolicVM<Labels, ULabels>, the_unitSymbolicVM<Place, UPlace>,
the_unitSymbolicVM<Places, UPlaces>, the_unitIvSymbolicVM<Label, ULabel>,
the_unitIvSymbolicVM<Labels, ULabels>, the_unitIvSymbolicVM<Place, UPlace>,
the_unitIvSymbolicVM<Places, UPlaces>, 0};
AddOperator(the_unitSymbolicInfo(), the_unitSymbolicVMs,
the_unitSymbolicSelect, the_unitSymbolicTM);
ValueMapping makemvalueSymbolicVMs[] = {makemvalueSymbolicVM<ULabel, MLabel>,
makemvalueSymbolicVM<ULabels, MLabels>, makemvalueSymbolicVM<UPlace,MPlace>,
makemvalueSymbolicVM<UPlaces, MPlaces>, 0};
AddOperator(makemvalueSymbolicInfo(), makemvalueSymbolicVMs,
makemvalueSymbolicSelect, makemvalueSymbolic_TM);
ValueMapping makemvalue2SymbolicVMs[] = {makemvalue2SymbolicVM<ULabel,MLabel>,
makemvalue2SymbolicVM<ULabels, MLabels>,
makemvalue2SymbolicVM<UPlace, MPlace>,
makemvalue2SymbolicVM<UPlaces, MPlaces>, 0};
AddOperator(makemvalue2SymbolicInfo(), makemvalue2SymbolicVMs,
makemvalueSymbolicSelect, makemvalueSymbolic_TM);
ValueMapping passesSymbolicVMs[] = {passesSymbolicVM<MLabel, Label>,
passesSymbolicVM<MLabel, CcString>, passesSymbolicVM<MLabel, FText>,
passesSymbolicVM<MLabels, Label>, passesSymbolicVM<MLabels, Labels>,
passesSymbolicVM<MLabels, CcString>, passesSymbolicVM<MLabels, FText>,
passesSymbolicVM<MPlace, Place>, passesSymbolicVM<MPlaces, Place>,
passesSymbolicVM<MPlaces, Places>, 0};
AddOperator(passesSymbolicInfo(), passesSymbolicVMs, atPassesSymbolicSelect,
passesSymbolicTM);
ValueMapping atSymbolicVMs[] = {atSymbolicVM<MLabel, Label>,
atSymbolicVM<MLabel, CcString>, atSymbolicVM<MLabel, FText>,
atSymbolicVM<MLabels, Label>, atSymbolicVM<MLabels, Labels>,
atSymbolicVM<MLabels, CcString>, atSymbolicVM<MLabels, FText>,
atSymbolicVM<MPlace, Place>, atSymbolicVM<MPlaces, Place>,
atSymbolicVM<MPlaces, Places>, 0};
AddOperator(atSymbolicInfo(), atSymbolicVMs, atPassesSymbolicSelect,
atSymbolicTM);
ValueMapping deftimeSymbolicVMs[] = {deftimeSymbolicVM<MLabel>,
deftimeSymbolicVM<MLabels>, deftimeSymbolicVM<MPlace>,
deftimeSymbolicVM<MPlaces>, 0};
AddOperator(deftimeSymbolicInfo(), deftimeSymbolicVMs, symbolicSimpleSelect,
deftimeSymbolicTM);
ValueMapping atinstantSymbolicVMs[] = {atinstantSymbolicVM<MLabel, ILabel>,
atinstantSymbolicVM<MLabels, ILabels>, atinstantSymbolicVM<MPlace, IPlace>,
atinstantSymbolicVM<MPlaces, IPlaces>, 0};
AddOperator(atinstantSymbolicInfo(), atinstantSymbolicVMs,
symbolicSimpleSelect, atinstantSymbolicTM);
ValueMapping atperiodsSymbolicVMs[] = {atperiodsSymbolicVM<MLabel>,
atperiodsSymbolicVM<MLabels>, atperiodsSymbolicVM<MPlace>,
atperiodsSymbolicVM<MPlaces>, 0};
AddOperator(atperiodsSymbolicInfo(), atperiodsSymbolicVMs,
symbolicSimpleSelect, atperiodsSymbolicTM);
ValueMapping nocomponentsSymbolicVMs[] = {nocomponentsSymbolicVM<MLabel>,
nocomponentsSymbolicVM<MLabels>, nocomponentsSymbolicVM<MPlace>,
nocomponentsSymbolicVM<MPlaces>, nocomponentsSymbolicVM<Labels>,
nocomponentsSymbolicVM<Places>, 0};
AddOperator(nocomponentsSymbolicInfo(), nocomponentsSymbolicVMs,
nocomponentsSymbolicSelect, nocomponentsSymbolicTM);
ValueMapping getIntervalSymbolicVMs[] = {getIntervalSymbolicVM<MLabel>,
getIntervalSymbolicVM<MLabels>, getIntervalSymbolicVM<MPlace>,
getIntervalSymbolicVM<MPlaces>, getIntervalSymbolicVM<ULabel>,
getIntervalSymbolicVM<ULabels>, getIntervalSymbolicVM<UPlace>,
getIntervalSymbolicVM<UPlaces>, 0};
AddOperator(getIntervalSymbolicInfo(), getIntervalSymbolicVMs,
getIntervalSymbolicSelect, getIntervalSymbolicTM);
ValueMapping getunitSymbolicVMs[] = {getunitSymbolicVM<MLabel, ULabel>,
getunitSymbolicVM<MLabels, ULabels>, getunitSymbolicVM<MPlace, UPlace>,
getunitSymbolicVM<MPlaces, UPlaces>, 0};
AddOperator(getunitSymbolicInfo(), getunitSymbolicVMs, symbolicSimpleSelect,
getunitSymbolicTM);
ValueMapping getPositionSymbolicVMs[] = {getPositionSymbolicVM<MLabel>,
getPositionSymbolicVM<MLabels>, getPositionSymbolicVM<MPlace>,
getPositionSymbolicVM<MPlaces>, 0};
AddOperator(getPositionSymbolicInfo(), getPositionSymbolicVMs,
getPositionSymbolicSelect, getPositionSymbolicTM);
ValueMapping unitsSymbolicVMs[] = {unitsSymbolicVM<MLabel, ULabel>,
unitsSymbolicVM<MLabels, ULabels>, unitsSymbolicVM<MPlace, UPlace>,
unitsSymbolicVM<MPlaces, UPlaces>, 0};
AddOperator(unitsSymbolicInfo(), unitsSymbolicVMs, symbolicSimpleSelect,
unitsSymbolicTM);
ValueMapping initialSymbolicVMs[] = {initialSymbolicVM<ULabel, ILabel>,
initialSymbolicVM<ULabels, ILabels>, initialSymbolicVM<MLabel, ILabel>,
initialSymbolicVM<MLabels, ILabels>, initialSymbolicVM<UPlace, IPlace>,
initialSymbolicVM<UPlaces, IPlaces>, initialSymbolicVM<MPlace, IPlace>,
initialSymbolicVM<MPlaces, IPlaces>, 0};
AddOperator(initialSymbolicInfo(), initialSymbolicVMs,
initialFinalSymbolicSelect, initialFinalSymbolicTM);
ValueMapping finalSymbolicVMs[] = {finalSymbolicVM<ULabel, ILabel>,
finalSymbolicVM<ULabels, ILabels>, finalSymbolicVM<MLabel, ILabel>,
finalSymbolicVM<MLabels, ILabels>, finalSymbolicVM<UPlace, IPlace>,
finalSymbolicVM<UPlaces, IPlaces>, finalSymbolicVM<MPlace, IPlace>,
finalSymbolicVM<MPlaces, IPlaces>, 0};
AddOperator(finalSymbolicInfo(), finalSymbolicVMs,
initialFinalSymbolicSelect, initialFinalSymbolicTM);
ValueMapping valSymbolicVMs[] = {valSymbolicVM<ILabel, Label>,
valSymbolicVM<ILabels, Labels>, valSymbolicVM<IPlace, Place>,
valSymbolicVM<IPlaces, Places>, 0};
AddOperator(valSymbolicInfo(), valSymbolicVMs, valInstSymbolicSelect,
valSymbolicTM);
ValueMapping instSymbolicVMs[] = {instSymbolicVM<ILabel>,
instSymbolicVM<ILabels>, instSymbolicVM<IPlace>, instSymbolicVM<IPlaces>,
0};
AddOperator(instSymbolicInfo(), instSymbolicVMs, valInstSymbolicSelect,
instSymbolicTM);
ValueMapping insideSymbolicVMs[] = {insideSymbolicVM<MLabel, Labels>,
insideSymbolicVM<MPlace, Places>, 0};
AddOperator(insideSymbolicInfo(), insideSymbolicVMs, insideSymbolicSelect,
insideSymbolicTM);
ValueMapping concatVMs[] = {concatVM<MLabel>, concatVM<MLabels>,
concatVM<MPlace>, concatVM<MPlaces>, 0};
AddOperator(concatInfo(), concatVMs, symbolicSimpleSelect, concatTM);
ValueMapping compressVMs[] = {compressVM<MLabel>, compressVM<MLabels>,
compressVM<MPlace>, compressVM<MPlaces>, 0};
AddOperator(compressInfo(), compressVMs, compressSelect, compressTM);
ValueMapping fillgapsVMs[] = {fillgapsVM_1<MLabel>, fillgapsVM_1<MLabels>,
fillgapsVM_1<MPlace>, fillgapsVM_1<MPlaces>, fillgapsVM_Str<MLabel>,
fillgapsVM_Str<MLabels>, fillgapsVM_Str<MPlace>, fillgapsVM_Str<MPlaces>,0};
AddOperator(fillgapsInfo(), fillgapsVMs, fillgapsSelect, fillgapsTM);
}
~SymbolicTrajectoryBasicAlgebra() {}
};
}
extern "C"
Algebra* InitializeSymbolicTrajectoryBasicAlgebra(NestedList *nlRef,
QueryProcessor *qpRef) {
return new stj::SymbolicTrajectoryBasicAlgebra;
}