Files
secondo/Algebras/Periodic/PMSimple.h
2026-01-23 17:03:45 +08:00

1944 lines
56 KiB
C++

/*
3.16 ~PMSimple~
*/
#ifndef PMSIMPLE_H
#define PMSIMPLE_H
#include <iostream>
#include <string>
#include "NestedList.h"
#include "PeriodicSupport.h"
#include "PeriodicTypes.h"
#include "StandardTypes.h"
#include "DateTime.h"
extern NestedList* nl;
namespace periodic{
/*
~Constructor~
*/
template <class T, class Unit>
PMSimple<T, Unit>::PMSimple(){}
template <class T, class Unit>
PMSimple<T, Unit>::PMSimple(int dummy):
Attribute(false),
linearMoves(1),
compositeMoves(1),
compositeSubMoves(1),
periodicMoves(1),
canDelete(false),
interval(1),
startTime(datetime::instanttype){
__TRACE__
}
template <class T, class Unit>
PMSimple<T,Unit>::PMSimple(const PMSimple<T,Unit>& source):
Attribute(source.IsDefined()){
Equalize(&source);
}
/*
~Destructor~
*/
template <class T, class Unit>
PMSimple<T, Unit>::~PMSimple() {
__TRACE__
if(canDelete){
linearMoves.Destroy();
compositeMoves.Destroy();
compositeSubMoves.Destroy();
periodicMoves.Destroy();
}
}
/*
~Assignment operator~
*/
template <class T, class Unit>
PMSimple<T, Unit> PMSimple<T, Unit>::operator=(const PMSimple<T, Unit>& source){
Equalize(&source);
return *this;
}
/*
~Destroy~
If this function is called, the destructor can destroy the
FLOB objects.
[3] O(1)
*/
template <class T, class Unit>
void PMSimple<T,Unit>::Destroy(){
__TRACE__
canDelete = true;
}
/*
~Equalize~
This function takes the value for this PMSimple from another instance __B__.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
void PMSimple<T, Unit>::Equalize(const PMSimple<T,Unit>* B2){
__TRACE__
linearMoves.copyFrom(B2->linearMoves);
compositeMoves.copyFrom(B2->compositeMoves);
compositeSubMoves.copyFrom(B2->compositeSubMoves);
periodicMoves.copyFrom(B2->periodicMoves);
SetDefined(B2->IsDefined());
interval.Equalize(&(B2->interval));
startTime.Equalize(&(B2->startTime));
submove.Equalize(&(B2->submove));
}
/*
~NumOfFLOBs~
Returns four because four DbArrays are managed.
[3] O(1)
*/
template <class T, class Unit>
int PMSimple<T, Unit>::NumOfFLOBs() const{
__TRACE__
return 4;
}
/*
~GetFLOB~
This function returns the FLOB at the specified index. If the index
is out of range, the system will going down. The flobs are:
* 0: the units
* 1: the composite moves
* 2: the composite submoves
* 3: the periodic moves
[3] O(1)
*/
template <class T, class Unit>
Flob* PMSimple<T,Unit>::GetFLOB(const int i){
__TRACE__
assert(i>=0 && i<NumOfFLOBs());
if(i==0) return &linearMoves;
if(i==1) return &compositeMoves;
if(i==2) return &compositeSubMoves;
if(i==3) return &periodicMoves;
return 0;
}
/*
~Compare~
Because we have no unique representation of the periodic moves, this function is
not implemented in this moment.
[3] O(-1)
*/
template <class T, class Unit>
int PMSimple<T, Unit>::Compare(const Attribute* arg) const{
__TRACE__
cout << "PMSImple::Compare not implemented yet " << std::endl;
return -1;
}
/*
~Adjacent~
Returns false because it's not clear when two moving constants should be
adjacent.
[3] O(1)
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::Adjacent(const Attribute*)const{
__TRACE__
return false;
}
/*
~Clone~
This functions creates a new periodic moving constant with the same value
like the calling instance and returns it.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
PMSimple<T,Unit>* PMSimple<T, Unit>::Clone() const{
__TRACE__
PMSimple<T,Unit>* res = new PMSimple<T,Unit>(1);
res->Equalize(this);
return res;
}
/*
~SizeOf~
Returns the size of the class PMSimple.
[3] O(1)
*/
template <class T, class Unit>
size_t PMSimple<T, Unit>::Sizeof()const{
__TRACE__
return sizeof(PMSimple<T,Unit>);
}
/*
~HashValue~
This functions computes a HashValue for this PMSimple from the sizes of
the contained FLOBs.
[3] O(1)
*/
template <class T, class Unit>
size_t PMSimple<T, Unit>::HashValue() const{
__TRACE__
return (size_t) (interval.HashValue()+linearMoves.Size()+
compositeMoves.Size()+ periodicMoves.Size()+
compositeSubMoves.Size());
}
/*
~CopyFrom~
By calling this function the value of this instance will be
equalized with this one of the attribute. The attribute must be
of Type PMSimple. If __arg__ is of another type, the result is
not determined and can lead to a crash of [secondo].
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
void PMSimple<T,Unit>::CopyFrom(const Attribute* arg){
__TRACE__
Equalize((PMSimple<T,Unit>*) arg);
}
/*
~ToListExpr~
This function converts a periodic moving constant into its
nested list representation.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
ListExpr PMSimple<T, Unit>::ToListExpr(const ListExpr typeInfo)const {
__TRACE__
ListExpr timelist = startTime.ToListExpr(false);
ListExpr SubMoveList = GetSubMoveList(submove);
return ::nl->TwoElemList(timelist,SubMoveList);
}
/*
~ReadFrom~
Takes the value of this simple periodic moving object from a
nested list. The result informs about the success of this
call. If the List don't represent a valid periodic moving
object, this instance will be undefined. This behavior
differns to other ~readFrom~ functions to avoid some
expensive tests before creating the actual object.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::ReadFrom(const ListExpr value,
const ListExpr typeInfo){
__TRACE__
/* The list is scanned twice. In the first scan we
compute only the needed size of the contained arrays.
The reason is, that we want to avoid frequently ~Resize~
on the arrays.
*/
if(::nl->ListLength(value)!=2){
if(DEBUG_MODE){
std::cerr << __POS__ << ": wrong listlength (";
std::cerr << (::nl->ListLength(value)) << ")" << std::endl;
}
SetDefined(false);
return false;
}
if(!ResizeArrays(value)){
if(DEBUG_MODE){
std::cerr << __POS__ << ": resize array failed" << std::endl;
}
SetDefined(false);
return false;
}
if(!startTime.ReadFrom(::nl->First(value),false)){
if(DEBUG_MODE){
std::cerr << __POS__ << "reading of the start time failed" << std::endl;
std::cerr << "The list is " << std::endl;
::nl->WriteListExpr(::nl->First(value));
}
SetDefined(false);
return false;
}
// now we have to append the included submove
ListExpr SML = ::nl->Second(value);
if(::nl->ListLength(SML)!=2){
if(DEBUG_MODE){
std::cerr << __POS__ << ": wrong list length for submove" << std::endl;
}
SetDefined(false);
return false;
}
ListExpr SMT = ::nl->First(SML);
int LMIndex = 0;
int CMIndex = 0;
int SMIndex = 0;
int PMIndex = 0;
if(::nl->IsEqual(SMT,"linear")){
submove.arrayNumber = LINEAR;
submove.arrayIndex = 0;
if(!AddLinearMove(::nl->Second(SML),LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
std::cerr << __POS__ << " Error in reading linear move"
<< std::endl;
}
SetDefined(false);
return false;
}
SetDefined(true);
Unit LM;
linearMoves.Get(0,LM);
interval.Equalize(&(LM.interval));
CorrectDurationSums();
return true;
}
if(::nl->IsEqual(SMT,"composite")){
submove.arrayNumber=COMPOSITE;
submove.arrayIndex = 0;
if(!AddCompositeMove(::nl->Second(SML),LMIndex,
CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
std::cerr << __POS__ << "error in reading composite move"
<< std::endl;
}
SetDefined(false);
return false;
}
SetDefined(true);
CompositeMove CM;
compositeMoves.Get(0,CM);
interval.Equalize(&(CM.interval));
CorrectDurationSums();
return true;
}
if(::nl->IsEqual(SMT,"period")){
submove.arrayNumber = PERIOD;
submove.arrayIndex = 0;
if(!AddPeriodMove(::nl->Second(SML),LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
std::cerr << __POS__ << " error in reading periodic move"
<< std::endl;
}
SetDefined(false);
return false;
}
SetDefined(true);
PeriodicMove PM;
periodicMoves.Get(0,PM);
interval.Equalize(&(PM.interval));
CorrectDurationSums();
return true;
}
if(DEBUG_MODE){
std::cerr << __POS__ << "unknown subtype" << std::endl;
::nl->WriteListExpr(SMT);
}
return false;
}
/*
~IsEmpty~
This function yields __true__ if this periodic moving constant don't
contain any unit.
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::IsEmpty()const{
return linearMoves.Size()==0;
}
/*
~At~
This function returns a pointer to a new created instance of type
T. If this periodic moving constant is not defined at this
timepoint, the result will be 0. The caller of this function has to
delete the returned value of this function if the result is not null.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
void PMSimple<T, Unit>::At(const datetime::DateTime* instant,T& res)const{
__TRACE__
datetime::DateTime* duration = new datetime::DateTime(*instant);
duration->Minus(&startTime); // now it is a duration
if(interval.Contains(duration)){
// in the other case, we have nothing to do
// because the result is initialized with "undefined"
SubMove sm(submove);
CompositeMove CM;
PeriodicMove PM;
RelInterval RI;
while(sm.arrayNumber!=LINEAR){
if(sm.arrayNumber==COMPOSITE){
// in this stage of implementation a linear search is
// executed. i have to make it better in the future
int i = sm.arrayIndex;
compositeMoves.Get(i,CM);
int cur = CM.minIndex;
int max = CM.maxIndex;
bool found=false;
while( (cur<=max) && ! found){
CSubMove csm;
compositeSubMoves.Get(cur,csm); // get the submove
if(csm.arrayNumber==LINEAR){
Unit LM;
linearMoves.Get(csm.arrayIndex,LM);
RI = LM.interval;
} else if(csm.arrayNumber==PERIOD){
periodicMoves.Get(csm.arrayIndex,PM);
RI = PM.interval;
} else { //another submoves are not allowed
assert(false);
}
if(RI.Contains(duration)) // be happy
found=true;
else{ // search again
datetime::DateTime* L = RI.GetLength();
duration->Minus(L);
delete L;
L = NULL;
cur++;
}
}
assert(found); //otherwise we have an error in computation
} else if(sm.arrayNumber==PERIOD){
int index = sm.arrayIndex;
periodicMoves.Get(index,PM);
// this is a very slow implementation
// i have to speed up it in the future
sm = PM.submove;
RelInterval RI;
if(sm.arrayNumber==LINEAR){
Unit LM;
linearMoves.Get(sm.arrayIndex,LM);
RI = LM.interval;
} else if(sm.arrayNumber==COMPOSITE){
compositeMoves.Get(sm.arrayIndex,CM);
RI = CM.interval;
} else { //another submoves are not allowed
assert(false);
}
while(!RI.Contains(duration)){
datetime::DateTime* L = RI.GetLength();
duration->Minus(L);
delete L;
L = NULL;
}
} else{
// this case should never occurs
assert(false);
}
}
Unit LM;
linearMoves.Get(sm.arrayIndex,LM);
if(LM.IsDefinedAt(duration)){
LM.At(duration,res);
}
}
delete duration;
duration = NULL;
}
/*
~Initial~
This function computes the first defined value of this moving constant.
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::Initial(T& result) const{
__TRACE__
if(!IsDefined() || IsEmpty()){
return false;
}
Unit lm;
linearMoves.Get(0,lm);
return lm.Initial(result);
}
/*
~Final~
The ~Final~ function returns the last defined value of this periodic
moving object.
If none exists, NULL is returned.
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::Final(T& res)const{
__TRACE__
if(!IsDefined()){
return false;
}
if(IsEmpty()){
return false;
}
Unit lm = GetLastUnit();
return lm.Final(res);
}
/*
~Translation~
Moves this simple time within the time.
*/
template<class T, class Unit>
void PMSimple<T, Unit>::Translate(const datetime::DateTime& duration){
startTime += duration;
}
template<class T, class Unit>
void PMSimple<T, Unit>::Translate(const datetime::DateTime* duration,
PMSimple<T,Unit>& res)const{
res.Equalize(this);
res.startTime += *duration;
}
/*
~Minimize~
When this function is called, consecutive units with the same value are
summarized into single units.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::Minimize(){
if(MinimizationRequired()){
DbArray<Unit> newLinearMoves(1);
DbArray<CompositeMove> newCompositeMoves(1);
DbArray<CSubMove> newCompositeSubMoves(1);
DbArray<PeriodicMove> newPeriodicMoves(1);
Unit Summarization;
bool CompleteSummarized;
SubMove SM3 = MinimizeRec(submove,newLinearMoves,newCompositeMoves,
newCompositeSubMoves,
newPeriodicMoves,Summarization,CompleteSummarized);
if(CompleteSummarized){
// the whole movement can be represented in a single linear move
compositeMoves.clean();
compositeSubMoves.clean();
periodicMoves.clean();
linearMoves.clean();
linearMoves.Append(Summarization);
submove.arrayNumber = LINEAR;
submove.arrayIndex = 0;
} else{
submove = SM3;
// copy the new created objects into the local dbarrays
linearMoves.copyFrom(newLinearMoves);
compositeMoves.copyFrom(newCompositeMoves);
compositeSubMoves.copyFrom(newCompositeSubMoves);
periodicMoves.copyFrom(newPeriodicMoves);
}
}
CorrectDurationSums();
}
/*
~Statistical Information~
The following functions can be used in debugging for get some
additional information about the inner structure of this instant.
*/
template <class T, class Unit>
int PMSimple<T, Unit>::NumberOfLinearMoves(){
return linearMoves.Size();
}
template <class T, class Unit>
int PMSimple<T, Unit>::NumberOfCompositeMoves(){
return compositeMoves.Size();
}
template <class T, class Unit>
int PMSimple<T, Unit>::NumberOfCompositeSubMoves(){
return compositeSubMoves.Size();
}
template <class T, class Unit>
int PMSimple<T,Unit>::NumberOfPeriodicMoves(){
return periodicMoves.Size();
}
/*
~Split~
Calling this function splits this moving object at the given instant.
The splitpoint is given by an instant as well as a flag describing whether
this instant should be contained in the 'left' part. The results are stored
into the corresponding arguments. When the instant is outside the definition
time of this moving object, oe part will contain a copy of this, the other
part will be undefined.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::Split(const datetime::DateTime instant,
const bool toLeft,
PMSimple<T,Unit>& leftPart, PMSimple<T,Unit>& rightPart){
SubMove SMLeft,SMRight;
SMLeft.arrayNumber = -1;
SMRight.arrayNumber = -1;
datetime::DateTime stCopy = startTime;
splitRec(instant, toLeft,leftPart,rightPart,submove,stCopy,SMLeft,SMRight);
// set the values of the root record of the left part
if(SMLeft.arrayNumber<0){ // leftpart is empty
leftPart.defined=false;
} else{ // leftpart is non-empty
leftPart.defined = true;
leftPart.startTime = startTime;
leftPart.GetInterval(SMLeft,leftPart.interval);
}
// set the values of the root record of the right part
if(SMRight.arrayNumber<0){
rightPart.defined=false;
}else{
rightPart.defined=true;
rightPart.startTime = instant;
rightPart.GetInterval(SMRight,rightPart.interval);
}
std::cerr << "Missing correction for splitted infinite periodic moves !!!"
<< std::endl;
}
/*
~SpliRec~
This function splits the given submove of this periodic moving objects into
two part. The leftPart will be extended by the part of this submove before
the given instant. The remainder of this submove will stored into rightPart.
The new added submove of leftPart and rightPart is returned in the arguments
SMLeft and SMRight respectively. The argument toLeft controls whereto put
in the object at the given instant (closure properties). The starttime is
changed to be after the processed submove. If the submove is not defined
before the given instant, leftPart is not changed and SMLeft will hold an
negative number for the arrayNumber indicating an invalid value. When submove
is'nt defined after this instant, the same holds for rightPart and SMRight.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::splitRec(const datetime::DateTime instant,
const bool toLeft,
PMSimple<T,Unit>& leftPart, PMSimple<T,Unit>& rightPart,
SubMove submove, datetime::DateTime& startTime,
SubMove& SMLeft, SubMove& SMRight){
if(submove.arrayNumber==LINEAR){
// here we process a single unit. this case is easy to handle because a
// unit have to provide a split function
Unit LML;
linearMoves.Get(submove.arrayIndex,LML);
Unit LMR;
datetime::DateTime Dur = instant - startTime;
startTime = startTime + (*LML.interval.GetLength());
bool saveLeft,saveRight;
if(LML.GetDefined()){
LML.Split(Dur,toLeft,LMR);
saveLeft = LML.GetDefined();
saveRight = LMR.GetDefined();
} else{ // original is undefined
LML.interval.Split(Dur,toLeft,LMR.interval);
LMR.SetDefined(false);
saveLeft = LML.interval.IsDefined();
saveRight = LMR.interval.IsDefined();
}
if(saveLeft){
SMLeft.arrayNumber=LINEAR;
SMLeft.arrayIndex = leftPart.linearMoves.Size();
leftPart.linearMoves.Append(LML);
}else{
SMLeft.arrayNumber = -1;
}
// do the same thing with the right part
if(saveRight){
SMRight.arrayNumber=LINEAR;
SMRight.arrayIndex=rightPart.linearMoves.Size();
rightPart.linearMoves.Append(LML);
} else{
SMRight.arrayNumber = -1;
}
return; // linear moves processed
}
if(submove.arrayNumber==COMPOSITE){
// we store the submoves of this composite moves into an vector
// to ensure a single block representing this submove
CompositeMove CM;
compositeMoves.Get(submove.arrayIndex,CM);
std::vector<CSubMove> submovesLeft(CM.maxIndex-CM.minIndex+1);
std::vector<CSubMove> submovesRight(CM.maxIndex-CM.minIndex+1);
CSubMove SM;
for(int i=CM.minIndex;i<=CM.maxIndex;i++){
compositeSubMoves.Get(i,SM); // get the submove
// call recursive
splitRec(instant,toLeft,leftPart,rightPart,SM,startTime,SMLeft,SMRight);
// collect valid submoves
CSubMove CSMLeft;
CSMLeft.arrayNumber = SMLeft.arrayNumber;
CSMLeft.arrayIndex = SMLeft.arrayIndex;
CSubMove CSMRight;
CSMRight.arrayNumber = SMRight.arrayNumber;
CSMRight.arrayIndex = SMRight.arrayIndex;
if(SMLeft.arrayNumber>=0)
submovesLeft.push_back(CSMLeft);
if(SMRight.arrayNumber>=0)
submovesRight.push_back(CSMRight);
}
// process the left part
int size = submovesLeft.size();
if(size==0){
SMLeft.arrayNumber = -1;
} else if (size>1){ // in case size==1 is nothing to do
CompositeMove CMLeft;
CMLeft.minIndex = leftPart.compositeSubMoves.Size();
for(int i=0;i<size;i++){
leftPart.compositeSubMoves.Append(submovesLeft[i]);
}
CMLeft.maxIndex = leftPart.compositeSubMoves.Size()-1;
SMLeft.arrayNumber = COMPOSITE;
SMLeft.arrayIndex = leftPart.compositeMoves.Size();
leftPart.compositeMoves.Append(CMLeft);
}
// process the right part
size = submovesRight.size();
if(size==0){ // nothing remains at the right
SMRight.arrayNumber = -1;
} else if(size>1){
CompositeMove CMRight;
CMRight.minIndex = rightPart.compositeSubMoves.Size();
for(int i=0;i<size;i++){
rightPart.compositeSubMoves.Append(submovesRight[i]);
}
CMRight.maxIndex = rightPart.compositeSubMoves.Size()-1;
SMRight.arrayNumber = COMPOSITE;
SMRight.arrayIndex = rightPart.compositeMoves.Size();
rightPart.compositeMoves.Append(CMRight);
}
return; // composite moves processed
}
if(submove.arrayNumber==PERIOD){
// first, we check whether the split instant is outside the interval
PeriodicMove PM;
periodicMoves.Get(submove.arrayIndex,PM);
RelInterval sminterval;
GetInterval(PM.submove,sminterval);
datetime::DateTime smlength(datetime::durationtype);
sminterval.StoreLength(smlength);
datetime::DateTime ZeroTime(datetime::instanttype);
sminterval.StoreLength(smlength);
// find out how many repeatations left on both sides
// first compute the duration which should be transferred
//into the left part
datetime::DateTime LeftDuration = instant - startTime;
return; // periodic moves processed
}
assert(false); // unknown submove
}
/*
~SplitLeft~
This function equalizes leftPart with the part of this move which is located
before the instant.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::SplitLeft(const datetime::DateTime& instant,
const bool toLeft,
PMSimple<T,Unit>* result){
SubMove LastMove;
datetime::DateTime startTimecopy(datetime::instanttype);
startTimecopy.Equalize(&startTime);
if(!SplitLeftRec(instant,toLeft,*result,submove,startTimecopy,LastMove))
result->SetDefined(false);
else{
result->startTime = startTime;
datetime::DateTime len = instant-startTime;
result->interval.Set(&len,interval.IsLeftClosed(),toLeft);
result->submove = LastMove;
}
}
template <class T , class Unit>
bool PMSimple<T, Unit>::SplitLeftRec(const datetime::DateTime& instant,
const bool toLeft,
PMSimple<T,Unit>& result,const SubMove& submove,
datetime::DateTime& startTime,SubMove& lastSubmove){
/*
First, we handle the a single unit.
*/
if(submove.arrayNumber==LINEAR){
if(startTime > instant) // is right of the instant
return false;
Unit u;
linearMoves.Get(submove.arrayIndex,u);
RelInterval interval;
interval.Equalize(&u.interval);
datetime::DateTime dur = instant-startTime;
if(!u.interval.Contains(&dur)){
return false;
}
Unit rightUnit;
u.Split(dur,toLeft,rightUnit);
result.linearMoves.Append(u);
datetime::DateTime len(datetime::durationtype);
interval.StoreLength(len);
startTime = startTime + len;
lastSubmove.arrayNumber=LINEAR;
lastSubmove.arrayIndex = result.linearMoves.Size()-1;
return true;
}
/*
Second, handling of composite moves
*/
if(submove.arrayNumber == COMPOSITE){
CompositeMove CM;
compositeMoves.Get(submove.arrayIndex,CM);
datetime::DateTime dur = instant-startTime;
if(!CM.interval.Contains(&dur))
return false;
CSubMove SM;
std::vector<SubMove> mySubmoves(CM.maxIndex-CM.minIndex);
bool done = false;
for(int i =CM.minIndex;i<=CM.maxIndex && !done;i++){
compositeSubMoves.Get(i,SM);
if(SplitLeftRec(instant,toLeft,result,SM,startTime,lastSubmove)){
mySubmoves.push_back(lastSubmove);
} else { // after this move can't follow any further moves
done=true;
}
}
if(mySubmoves.size()<2){ // ok, this submoves is end in smoke
return true;
}else{ // we have to build a composite move from the remaining submoves
datetime::DateTime length(datetime::durationtype);
datetime::DateTime nextLength(datetime::durationtype);
int size = mySubmoves.size();
RelInterval interval;
CM.minIndex = result.compositeSubMoves.Size();
for(int i=0;i<size;i++){
SubMove simple = mySubmoves[i];
SM.arrayIndex = simple.arrayIndex;
SM.arrayNumber = simple.arrayNumber;
if(i==0)
result.GetInterval(SM,CM.interval);
else{
result.GetInterval(SM,interval);
CM.interval.Append(&interval);
}
result.compositeSubMoves.Append(SM);
}
CM.maxIndex = result.compositeSubMoves.Size()-1;
// append the composite move
lastSubmove.arrayIndex=COMPOSITE;
lastSubmove.arrayIndex = result.compositeMoves.Size();
result.compositeMoves.Append(CM);
return true;
}
}
if(submove.arrayIndex==PERIOD){
PeriodicMove PM;
periodicMoves.Get(submove.arrayIndex,PM);
datetime::DateTime dur = instant-startTime;
}
assert(false); // the program should never reach this position
}
/*
~Intersection~
This function reduces the definition time of this PMSimple to the
interval defined by the arguments. This function cannot be constant, i.e.
it changes the *this* argument, because
we have to scan the dbarrays in some cases.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::Intersection( const datetime::DateTime minTime,
const bool minIncluded,
const datetime::DateTime maxTime,
const bool maxIncluded,
PMSimple<T,Unit>* res){
PMSimple<T,Unit> TMPPM1;
PMSimple<T,Unit> TMPPM2;
Split(minTime,!minIncluded,TMPPM2,TMPPM1);
//TMPPM1.Split(maxTime,maxIncluded,TMPPM1,*result);
TMPPM1.SplitLeft(maxTime,maxIncluded,res);
}
/*
~CopyValuesFrom~
By calling this function, the value of this pmsimple is set to the given values.
There is no check whether the values are valid. Use this function very
carefully.
A possible application of this function is to take the tree from another
periodic moving object.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::CopyValuesFrom( DbArray<Unit>& linearMoves,
DbArray<CompositeMove>& compositeMoves,
DbArray<SubMove>& compositeSubMoves,
DbArray<PeriodicMove>& periodicMoves,
bool defined,
RelInterval interval,
datetime::DateTime startTime,
SubMove submove){
// first, clear all contained arraysa
this->linearMoves.copyFrom(linearMoves);
this->compositeMoves.copyFrom(compositeMoves);
this->compositeSubMoves.copyFrom(compositeSubMoves);
this->periodicMoves.copyFrom(periodicMoves);
SetDefined(defined);
this->interval.Equalize(&interval);
this->startTime.Equalize(&startTime);
this->submove=submove;
}
/*
~TakeValuesFrom~
This function works similar to the ~CopyValuesFrom~ function.
The difference is, that the values are assigned to the internal
variables. These variables are cleaned before.
*Note*: There is no check for the integrity of the given data.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::TakeValuesFrom( DbArray<Unit>& linearMoves,
DbArray<CompositeMove>& compositeMoves,
DbArray<SubMove>& compositeSubMoves,
DbArray<PeriodicMove>& periodicMoves,
bool defined,
RelInterval interval,
datetime::DateTime startTime,
SubMove submove){
this->linearMoves.Clear();
this->linearMoves.Destroy();
this->compositeMoves.clean();
this->compositeMoves.Destroy();
this->compositeSubMoves.clean();
this->compositeSubMoves.Destroy();
this->periodicMoves.clean();
this->periodicMoves.Destroy();
this->linearMoves = linearMoves;
this->compositeMoves = compositeMoves;
this->compositeSubMoves = compositeSubMoves;
this->periodicMoves = periodicMoves;
this->defined = defined;
this->interval = interval;
this->startTimes = startTime;
this->submove = submove;
}
/*
~SetStartTime~
This function can be used for moving this PMsimple in time.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::SetStartTime(datetime::DateTime newStart){
startTime.Equalize(&newStart);
}
/*
~Functions returning pointers to the members~
Each of the next functions returns a pointer for a member.
This way bypasses the protected declaration of the members
because this function enables the possibility to manipulate the
members direcly without control of the PMSimple class. This may
be not good for encapsulating the code but the only way to have
an efficient implementation for that. The caller of this functions
must be very very carefully to ensure that all the manipulated
members results in a consistent instance of type PMSimple.
A possible application of this function is to make a copy of the
tree structure of another periodic moving object.
*/
template <class T, class Unit>
DbArray<Unit>* PMSimple<T, Unit>::GetLinearMoves(){
return &linearMoves;
}
template <class T, class Unit>
DbArray<CompositeMove>* PMSimple<T,Unit>::GetCompositeMoves(){
return &compositeMoves;
}
template <class T, class Unit>
DbArray<CSubMove>* PMSimple<T, Unit>::GetCompositeSubMoves(){
return &compositeSubMoves;
}
template <class T, class Unit>
DbArray<PeriodicMove>* PMSimple<T, Unit>::GetPeriodicMoves(){
return &periodicMoves;
}
template <class T, class Unit>
RelInterval* PMSimple<T, Unit>::GetInterval(){
return &interval;
}
template <class T, class Unit>
SubMove* PMSimple<T, Unit>::GetSubmove(){
return &submove;
}
/*
~GetLength~
This function returns the lenght of the interval of the given
submove.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::GetLength(SubMove sm, datetime::DateTime& result){
switch(sm.arrayNumber){
case LINEAR: { Unit U;
linearMoves.Get(sm.arrayIndex,U);
U.interval.StoreLength(result);
} break;
case COMPOSITE: {
CompositeMove CM;
compositeMoves.Get(sm.arrayIndex,CM);
CM.interval.StoreLength(result);
}break;
case PERIOD: {
PeriodicMove PM;
periodicMoves.Get(sm.arrayIndex,PM);
PM.interval.StoreLength(result);
} break;
default: assert(false); // unknown move type
}
}
/*
~GetLeftClosed~
This function returns the state of the LeftClosed flag of the interval
of the given submove.
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::GetLeftClosed(SubMove sm){
switch(sm.arrayNumber){
case LINEAR: { Unit U;
linearMoves.Get(sm.arrayIndex,U);
return U.interval.IsLeftClosed();
}
case COMPOSITE: {
CompositeMove CM;
return CM.interval.IsLeftClosed();
}
case PERIOD: {
PeriodicMove PM;
return PM.interval.IsLeftClosed();
}
default: assert(false); // unknown move type
}
}
/*
~GetRightClosed~
This function returns the state of the RightClosed flag of the interval
of the given submove.
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::GetRightClosed(SubMove sm){
switch(sm.arrayNumber){
case LINEAR: { Unit U;
linearMoves.Get(sm.arrayIndex,U);
return U.interval.IsRightClosed();
}
case COMPOSITE: {
CompositeMove CM;
return CM.interval.IsRightClosed();
}
case PERIOD: {
PeriodicMove PM;
return PM.interval.IsRightClosed();
}
default: assert(false); // unknown move type
}
}
/*
~GetInterval~
This function returns the returns the interval of the given submove independly
of the type of the submove.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::GetInterval(SubMove sm,RelInterval& interval){
switch(sm.arrayNumber){
case LINEAR: { Unit U;
linearMoves.Get(sm.arrayIndex,U);
interval.Equalize(&U.interval);
} break;
case COMPOSITE: {
CompositeMove CM;
compositeMoves.Get(sm.arrayIndex,CM);
interval.Equalize(&CM.interval);
}break;
case PERIOD: {
PeriodicMove PM;
periodicMoves.Get(sm.arrayIndex,PM);
interval.Equalize(&PM.interval);
}break;
default: assert(false); // unknown move type
}
}
/*
~GetSubMoveList~
This function returns the list representation for the submove in the
argument.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
ListExpr PMSimple<T, Unit>::GetSubMoveList(const SubMove SM) const{
__TRACE__
ListExpr SubMoveList;
int SubMoveType = SM.arrayNumber;
int index = SM.arrayIndex;
if(SubMoveType==LINEAR)
SubMoveList = GetLinearMoveList(index);
else if(SubMoveType==COMPOSITE)
SubMoveList = GetCompositeMoveList(index);
else if(SubMoveType==PERIOD)
SubMoveList = GetPeriodicMoveList(index);
else{
std::cerr << __POS__ << " Error in creating ListExpr" << std::endl;
SubMoveList = ::nl->TheEmptyList();
}
return SubMoveList;
}
/*
~GetLinearMoveList~
This functions takes the linear move at the specified index and
returns its nested list representation.
[3] O(1)
*/
template <class T, class Unit>
ListExpr PMSimple<T, Unit>::GetLinearMoveList(const int index)const{
__TRACE__
Unit LM;
linearMoves.Get(index,LM);
return LM.ToListExpr();
}
/*
~GetPeriodicMoveList~
Creates a nested list for the periodic move at the specified index.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
ListExpr PMSimple<T, Unit>::GetPeriodicMoveList(const int index)const{
__TRACE__
PeriodicMove PM;
periodicMoves.Get(index,PM);
ListExpr periodtype = ::nl->SymbolAtom("period");
ListExpr RepList = ::nl->IntAtom(PM.repeatations);
ListExpr SML = GetSubMoveList(PM.submove);
ListExpr RC = ::nl->BoolAtom(interval.IsRightClosed());
ListExpr LC = ::nl->BoolAtom(interval.IsLeftClosed());
return ::nl->TwoElemList(periodtype,::nl->FourElemList(RepList,LC,RC,SML));
}
/*
~GetCompositeMoveList~
Returns the CompositeMove at the specified index in its nested list
representation.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
ListExpr PMSimple<T, Unit>::GetCompositeMoveList(const int index)const{
__TRACE__
CompositeMove CM;
compositeMoves.Get(index,CM);
ListExpr CType = ::nl->SymbolAtom("composite");
int minIndex = CM.minIndex;
int maxIndex = CM.maxIndex;
ListExpr SubMovesList;
if(maxIndex<minIndex){
std::cerr << __POS__ << "empty composite move" << std::endl;
SubMovesList = ::nl->TheEmptyList();
}
else{
// construct the List of submoves
CSubMove SM;
compositeSubMoves.Get(minIndex,SM);
SubMovesList = ::nl->OneElemList(GetSubMoveList(SM));
ListExpr Last = SubMovesList;
for(int i=minIndex+1;i<=maxIndex;i++){
compositeSubMoves.Get(i,SM);
Last = ::nl->Append(Last,GetSubMoveList(SM));
}
}
return ::nl->TwoElemList(CType,SubMovesList);
}
/*
~ResizeArrays~
This functions resizes all array to be able to insert the moves
contained in the argument list.This function should be called
before this instance is read from a nested list to avoid
frequently resize of the contained DB-Arrays. The return
value of this function is an indicator for the correctness
of the structure of this list. If the result is __false__,
the list don't represent a valid periodic moving object.
But a return value of __true__ don't guarantees a correct
list representation.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::ResizeArrays(const ListExpr value){
__TRACE__
// first all entries in the arrays are removed
linearMoves.clean();
compositeMoves.clean();
compositeSubMoves.clean();
periodicMoves.clean();
int LMSize = 0;
int CMSize = 0;
int SMSize = 0;
int PMSize = 0;
if(!AddSubMovesSize(::nl->Second(value),LMSize,CMSize,SMSize,PMSize))
return false;
// set the arrays to the needed size
if(LMSize>0) linearMoves.resize(LMSize);
if(CMSize>0) compositeMoves.resize(CMSize);
if(SMSize>0) compositeSubMoves.resize(SMSize);
if(PMSize>0) periodicMoves.resize(PMSize);
return true;
}
/*
~AddSubMovesSize~
Adds the number of in value contained submoves to the appropriate
size. If the result is__false__, the list is not a correct
representation of a periodic moving object. If it is __true__
the content of the list can be wrong but the structure is correct.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::AddSubMovesSize(const ListExpr value,
int &LMSize,int &CMSize,
int &SMSize,int &PMSize){
__TRACE__
// all moves have the length 2
if(::nl->ListLength(value)!=2)
return false;
ListExpr type = ::nl->First(value);
if(::nl->AtomType(type)!=SymbolType)
return false;
// in a linear move we have only to increment the size of LM
if(::nl->IsEqual(type,"linear")){
LMSize = LMSize +1;
return true;
}
if(::nl->IsEqual(type,"composite")){
CMSize = CMSize+1; // the composite move itself
ListExpr rest = ::nl->Second(value);
SMSize = SMSize+::nl->ListLength(rest); // the contained submoves
while(!::nl->IsEmpty(rest)){
if(!AddSubMovesSize(::nl->First(rest),LMSize,CMSize,SMSize,PMSize))
return false;
rest = ::nl->Rest(rest);
}
return true;
}
if(::nl->IsEqual(type,"period")){
PMSize = PMSize+1;
int len = ::nl->ListLength(value);
ListExpr PMove;
if(len==2)
PMove = ::nl->Second(value);
else if(len==4)
PMove = ::nl->Fourth(value);
else // incorrect listlength
return false;
return AddSubMovesSize(::nl->Second(PMove),
LMSize,CMSize,SMSize,PMSize);
}
// a unknown type description
return false;
}
/*
~AddLinearMove~
This function adds the LinearMove given in value to this PMSimple.
If the list represents a valid Unit, this unit is append to to
appropriate dbarray and the argument __LMIndex__ is increased.
If the list is incorrect, this periodic moving object is not
changed and the result will be __false__.
[3] O(1)
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::AddLinearMove(const ListExpr value,int &LMIndex,
int &CMIndex,
int &SMIndex, int &PMIndex){
__TRACE__
Unit LM = Unit(0);
if(!LM.ReadFrom(value))
return false;
linearMoves.Put(LMIndex,LM);
LMIndex++;
return true;
}
/*
~AddCompositeMove~
This function creates a CompositeMove from value and adds it
(and all contained submoves) to this PMSimple. The return
value corresponds to the correctness of the list for this
composite move. The arguments are increased by the number of
contained submoves in this composite move. *Note*: This
function can change this periodic moving object even when
the list is not correct. In the case of a result of __false__,
the state of this object is not defined and the defined flag
should be set to false.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::AddCompositeMove(const ListExpr value,
int &LMIndex, int &CMIndex,
int &SMIndex, int &PMIndex){
__TRACE__
// a composite move has to contains at least two submoves
int len = ::nl->ListLength(value);
if(len<2){
if(DEBUG_MODE){
std::cerr << __POS__ << " less than 2 submoves ("
<< len << ")" << std::endl;
}
return false;
}
CompositeMove CM=CompositeMove(1);
int CMPos=CMIndex;
int SMPos=SMIndex;
// ensure that no submove used the positions for this composite move
CMIndex++;
CM.minIndex=SMIndex;
CM.maxIndex=SMIndex+len-1;
SMIndex= SMIndex+len;
// Append the contained Submoves
ListExpr rest = value;
ListExpr SML,TL,VL;
bool isFirst = true;
while(!::nl->IsEmpty(rest)){
SML = ::nl->First(rest);
rest = ::nl->Rest(rest);
if(::nl->ListLength(SML)!=2){ // all submoves have the
// format (type value)
if(DEBUG_MODE){
std::cerr << __POS__ << " submove has wrong length (";
std::cerr << ::nl->ListLength(SML) << ")" << std::endl;
}
return false;
}
TL = ::nl->First(SML);
VL = ::nl->Second(SML);
if(::nl->IsEqual(TL,"linear")){
// process a linear submove
int LMPos = LMIndex;
if(!AddLinearMove(VL,LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
std::cerr << __POS__ << " can't add a linear move " << std::endl;
}
return false;
}
Unit LM;
linearMoves.Get(LMPos,LM);
// Append the interval of LM to CM
if(isFirst){
isFirst=false;
CM.interval.Equalize(&(LM.interval));
}else{
if(!CM.interval.Append(&(LM.interval))){
if(DEBUG_MODE){
std::cerr << __POS__ << " can't append interval "
<< std::endl;
std::cerr << "The original interval is";
std::cerr << CM.interval.ToString() << std::endl;
std::cerr << "The interval to append is";
std::cerr << LM.interval.ToString() << std::endl;
}
return false;
}
}
// put the submove in the array
CSubMove SM;
SM.arrayNumber = LINEAR;
SM.arrayIndex = LMPos;
compositeSubMoves.Put(SMPos,SM);
SMPos++;
} else if(::nl->IsEqual(TL,"period")){
// process a periodic submove
int PMPos = PMIndex;
if(!AddPeriodMove(VL,LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
std::cerr << __POS__ << "can't add period move " << std::endl;
}
return false;
}
PeriodicMove PM;
periodicMoves.Get(PMPos,PM);
if(isFirst){
isFirst=false;
CM.interval.Equalize(&(PM.interval));
}else{
if(!CM.interval.Append(&(PM.interval))){
if(DEBUG_MODE){
std::cerr << __POS__ << " can't append interval" << std::endl;
}
return false;
}
}
CSubMove SM;
SM.arrayNumber = PERIOD;
SM.arrayIndex = PMPos;
compositeSubMoves.Put(SMPos,SM);
SMPos++;
} else{ // not of type linear or period
if(DEBUG_MODE){
std::cerr << __POS__ << " submove not of type ";
std::cerr << "linear od period" << std::endl;
}
return false;
}
}
// put the compositeMove itself
compositeMoves.Put(CMPos,CM);
return true;
}
/*
~AddPeriodMove~
Adds the period move described in value to this PMSimple.
*Note*: This function can change this objects even wehn
the list does not represent a valid period move. If the
result is __false__ the __defined__ flag of this move
should be set to false.
[3] O(L), where L is the number of contained linear moves
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::AddPeriodMove(const ListExpr value,
int &LMIndex, int &CMIndex,
int &SMIndex, int &PMIndex){
__TRACE__
int len = ::nl->ListLength(value);
if((len!=2) && (len!=4)){ // (repeatations <submove>)
if(DEBUG_MODE)
std::cerr << __POS__ << ": wrong listlength" << std::endl;
return false;
}
if(::nl->AtomType(::nl->First(value))!=IntType){
if(DEBUG_MODE){
std::cerr << __POS__ << ": wrong type for repeatations" << std::endl;
}
return false;
}
int rep = ::nl->IntValue(::nl->First(value));
// rep must be greater than 1
if(rep<=1 ){
if(DEBUG_MODE){
std::cerr << __POS__ << " wrong number of repeatations" << std::endl;
}
return false;
}
ListExpr SML;
if(len==2){
SML = ::nl->Second(value);
} else { // len == 4
SML = ::nl->Fourth(value);
}
if(::nl->ListLength(SML)!=2){
if(DEBUG_MODE){
std::cerr << __POS__ << ": wrong length for submove" << std::endl;
}
return false;
}
PeriodicMove PM=PeriodicMove(1);
PM.repeatations = rep;
int IncludePos = PMIndex; // store the positiuon
PMIndex++;
ListExpr SMT = ::nl->First(SML); // take the submove type
if(::nl->IsEqual(SMT,"linear")){
int LMPos = LMIndex;
if(!AddLinearMove(::nl->Second(SML),LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
std::cerr << __POS__ << ": can't add linear submove" << std::endl;
}
return false;
}
PM.submove.arrayNumber = LINEAR;
PM.submove.arrayIndex = LMPos;
Unit LM;
linearMoves.Get(LMPos,LM);
RelInterval SMI = LM.interval;
PM.interval.Equalize(&SMI);
PM.interval.Mul(rep);
if(len==4){
ListExpr LC = ::nl->Second(value);
ListExpr RC = ::nl->Third(value);
if((::nl->AtomType(LC)!=BoolType) || (::nl->AtomType(RC)!=BoolType))
return false;
PM.interval.SetLeftClosed(::nl->BoolValue(LC));
PM.interval.SetRightClosed(::nl->BoolValue(RC));
}
periodicMoves.Put(IncludePos,PM);
return true;
}else if(::nl->IsEqual(SMT,"composite")){
int CMPos = CMIndex;
if(!AddCompositeMove(::nl->Second(SML),LMIndex,CMIndex,
SMIndex,PMIndex)){
if(DEBUG_MODE){
std::cerr << __POS__ << ": can't add composite submove" << std::endl;
}
return false;
}
PM.submove.arrayNumber = COMPOSITE;
PM.submove.arrayIndex = CMPos;
CompositeMove CM;
compositeMoves.Get(CMPos,CM);
RelInterval SMI = CM.interval;
PM.interval.Equalize(&SMI);
PM.interval.Mul(rep);
if(len==4){
ListExpr LC = ::nl->Second(value);
ListExpr RC = ::nl->Third(value);
if((::nl->AtomType(LC)!=BoolType) || (::nl->AtomType(RC)!=BoolType))
return false;
PM.interval.SetLeftClosed(::nl->BoolValue(LC));
PM.interval.SetRightClosed(::nl->BoolValue(RC));
}
periodicMoves.Put(IncludePos,PM);
return true;
}
return false; // invalid type
}
/*
~GetLastUnit~
This function returns the temporal last unit of this periodic moving point.
It is realized by going down the repetition tree up to a unit.
*/
template <class T, class Unit>
Unit PMSimple<T, Unit>::GetLastUnit()const{
__TRACE__
const SubMove* s = &submove;
while(s->arrayNumber!=LINEAR){
if(s->arrayNumber==PERIOD){
PeriodicMove PM;
periodicMoves.Get(s->arrayIndex,PM);
s = &PM.submove;
} else if(s->arrayNumber==COMPOSITE){
CompositeMove CSM;
compositeMoves.Get(s->arrayIndex,CSM);
CSubMove csm;
compositeSubMoves.Get(CSM.maxIndex,csm);
SubMove sm;
sm.arrayNumber = csm.arrayNumber;
sm.arrayIndex = csm.arrayIndex;
s = &sm;
} else{
assert(false); // unknown arraynumber
}
}
Unit res;
linearMoves.Get(s->arrayIndex,res);
return res;
}
/*
~MinimizationRequired~
This function checks, whether an call of ~Minimize~ will change the
tree. Particularly, it checks whether two consecutive units can
be summarized to a single one.
*/
template <class T, class Unit>
bool PMSimple<T, Unit>::MinimizationRequired(){
__TRACE__
Unit LM;
Unit LM2;
CompositeMove CM;
PeriodicMove PM;
const SubMove* SM=0;
// check periodic moves
int size = periodicMoves.Size();
for(int i=0;i<size;i++){
periodicMoves.Get(i,PM);
SM = &PM.submove;
if(SM->arrayIndex==LINEAR){
linearMoves.Get(SM->arrayIndex,LM);
if(LM.interval.CanAppended(&LM.interval))
return true;
}
}
CSubMove CSM;
CSubMove CSM2;
// check composite moves
size = compositeMoves.Size();
for(int i=0;i<size;i++){
compositeMoves.Get(i,CM);
for(int k=CM.minIndex;k< CM.maxIndex;k++){
compositeSubMoves.Get(k,CSM);
compositeSubMoves.Get(k+1,CSM2);
if( (CSM.arrayNumber==LINEAR) && (CSM2.arrayNumber==LINEAR)){
linearMoves.Get(CSM.arrayIndex,LM);
linearMoves.Get(CSM2.arrayIndex,LM2);
if( LM.CanSummarized(&LM2))
return true;
}
}
}
return false;
}
/*
~MinimizeRec~
This function summarizes consecutive units with the same value.
The result is stored in the arguments. Note that no detection of
equal linear moves is performed. This means, when a unit occurs
twice or more, this unit will be also stored several times in
the corresponding dbarray.
*/
template <class T, class Unit>
SubMove PMSimple<T, Unit>::MinimizeRec(SubMove SM,
DbArray<Unit>& newLinearMoves,
DbArray<CompositeMove>& newCompositeMoves,
DbArray<CSubMove>& newCompositeSubMoves,
DbArray<PeriodicMove>& newPeriodicMoves,
Unit& Summarization,
bool& CompleteSummarized){
if(SM.arrayNumber==LINEAR){
linearMoves.Get(SM.arrayIndex,Summarization);
CompleteSummarized=true;
return SM;
}
if(SM.arrayNumber==PERIOD){
PeriodicMove PM2;
periodicMoves.Get(SM.arrayIndex,PM2);
SubMove SM2 = MinimizeRec(PM2.submove,
newLinearMoves,newCompositeMoves,
newCompositeSubMoves,newPeriodicMoves,
Summarization, CompleteSummarized);
if(!CompleteSummarized){
PM2.submove = SM2;
int Pos = newPeriodicMoves.Size();
newPeriodicMoves.Append(PM2);
SM2.arrayNumber=PERIOD;
SM2.arrayIndex= Pos;
CompleteSummarized = false;
return SM2;
}else{ // the result is a single linear move
if(!Summarization.interval.CanAppended(
&Summarization.interval)){ // a little gap
int LinPos = newLinearMoves.Size();
newLinearMoves.Append(Summarization);
PM2.submove.arrayNumber=LINEAR;
PM2.submove.arrayIndex=LinPos;
// store this periodic move
int PerPos = newPeriodicMoves.Size();
newPeriodicMoves.Append(PM2);
SM2.arrayNumber=PERIOD;
SM2.arrayIndex=PerPos;
CompleteSummarized=false;
return SM2;
}else{ // we don't need longer this periodic move
Summarization.interval.Mul(PM2.repeatations);
return SM2;
}
}
}
if(SM.arrayNumber==COMPOSITE){
CompositeMove CM;
compositeMoves.Get(SM.arrayIndex,CM);
Unit LM(0);
bool LMdefined = false;
std::vector<CSubMove> MySubMoves;
for(int i=CM.minIndex;i<=CM.maxIndex;i++){
CSubMove Current;
compositeSubMoves.Get(i,Current);
SubMove SM2 = MinimizeRec(Current,
newLinearMoves,newCompositeMoves,
newCompositeSubMoves,newPeriodicMoves,
Summarization, CompleteSummarized);
if(!CompleteSummarized){
// store summarized submove if present
if(LMdefined){
int LinPos = newLinearMoves.Size();
newLinearMoves.Append(LM);
LMdefined=false;
CSubMove SM3;
SM3.arrayNumber=LINEAR;
SM3.arrayIndex=LinPos;
MySubMoves.push_back(SM3);
}
CSubMove SM3;
SM3.arrayIndex = SM2.arrayIndex;
SM3.arrayNumber= SM2.arrayNumber;
MySubMoves.push_back(SM3);
}else{ // submove complete summarized
if(!LMdefined){ // first summarized LinearMove;
LM = Summarization;
LMdefined=true;
}else{
if(LM.CanSummarized(&Summarization)){
// append the new summarization to LM
LM.interval.Append(&Summarization.interval);
} else{
// the new summarization cannot appendend to LM
// store LM
int LinPos = newLinearMoves.Size();
newLinearMoves.Append(LM);
CSubMove SM3;
SM3.arrayNumber=LINEAR;
SM3.arrayIndex=LinPos;
MySubMoves.push_back(SM3);
LM = Summarization;
}
}
}
} // all submoves processed;
if(MySubMoves.size()==0){ // all its collected into LM
CompleteSummarized=true;
Summarization = LM;
return SM; // unimportant in this case
}else{
if(LMdefined){ // store the last summarization
int LinPos = newLinearMoves.Size();
newLinearMoves.Append(LM);
CSubMove SM3;
SM3.arrayNumber = LINEAR;
SM3.arrayIndex = LinPos;
MySubMoves.push_back(SM3);
}
CM.minIndex = newCompositeSubMoves.Size();
CM.maxIndex = CM.minIndex + MySubMoves.size()-1;
// store the submoves
for(unsigned int k=0;k<MySubMoves.size();k++){
newCompositeSubMoves.Append(MySubMoves[k]);
}
SubMove SM3;
SM3.arrayNumber=COMPOSITE;
SM3.arrayIndex=newCompositeMoves.Size();
newCompositeMoves.Append(CM);
CompleteSummarized=false;
return SM3;
}
}
assert(false);
}
/*
~CorrectDurationSums~
Each son of a composite move stores the sum of all from its
predecessors. This enables binary search for an given instant
within composite moves. Because ensuring correct values is
a little bit difficult within functions changing the arrays (a lot
of special cases), this function provides a correction of the stored
durations. This means, the functions can work without be care about the
durations when this function is called after the work of the function is
done.
*/
template <class T, class Unit>
void PMSimple<T, Unit>::CorrectDurationSums(){
if(IsEmpty() || !IsDefined()){ // nothing to do
return;
}
int cmsize = compositeMoves.Size();
RelInterval currentInterval;
datetime::DateTime currentLength(datetime::durationtype);
datetime::DateTime duration(datetime::durationtype);
CompositeMove CM;
// process all compositeMoves.
for(int i=0;i<cmsize;i++){
compositeMoves.Get(i,CM);
duration.SetToZero();
for(int j=CM.minIndex;j<=CM.maxIndex;j++){
CSubMove csm1;
compositeSubMoves.Get(j,csm1);
CSubMove csm;
csm.Equalize(&csm1);
csm.duration.Equalize(&duration);
compositeSubMoves.Put(j,csm);
GetLength(csm,currentLength);
duration += currentLength;
}
}
}
} // end of namespace periodic
#endif