/*File Name: Univers.cpp
  Author: Bernd Oesterholz ; Date: 12.01.2005
  System: C++


  Copyright (C) 2004  Bernd Österholz

  This program 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, June 1991, of the License, or
  (at your option) any later version.

  This program 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 this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

This file contains the program for a univers.
Ther are 2 basictypes in this univers points and conections(positiv and
negativ) betwean them. Points are changing Points of the univers.
Every tick(minimum time) every point creates a new zero distance. (nothing is
produced, conservation of distances) A zero distance is a positiv (+1) and a
negativ (-1) distance. The 2 signed distances are random conected to a
neigbor of the point or a new point. (each possibility has same probability)
Neigbor points of a point are points that are conected with distances to the point.
Two not eqaul signed distances betwean to points destroy each other.(add to zero)
If one part (signed distance) of a zero distanc is destroyed, but not the
other, the other distance one end ist displaced from the point of his
creation to the point that was conected with the creation point by the
destroyed distance. (the distance betwean the end and the point becomes zero)

translation diagram:(for tree points)
	pi point i=1..3
	+ positiv distance
	- negativ distance
	no distance
	befor -> after
	p2 is the point wher the zero distance is created, p1 is the point choosen
	for the positiv part(distance) to go to and p3 is the point choosen
	for the negativ part(distance) to go to

	1) p1+p2+p3 -> p3+p1+p2
	2) p1+p2-p3 -> p1++p2--p3
	3) p1-p2+p3 -> p1 p2 p3
	4) p1-p2-p3 -> p3-p1-p2
	5) p1+p2 p3 -> p1++p2-p3
	6) p1 p2+p3 -> p1+p3 p2
	7) p1-p2 p3 -> p1-p3 p2
	8) p1 p2-p3 -> p1+p2--p3
	9) p1 p2 p3 -> p1+p2-p3

*/

#include "Univers.h"


Univers::Univers():iTime(0),pDistance(0),nDistance(0),
	outComent(true),cutAfter(0),outUniv(0),outStat(0),bTime(0),
	maxTime(100),maxPoints(0),checkMaxPoints(1),statFile(NULL),statFileName(0),uFolder(0),
	bUName(0),cutNearDimension(3.0),cutMaxClassRatio(1.0),appendUnivers(false),
	parameterFile(0),outRealTime(false),rTimeFileName(0),rTimeFile(0),
	outCutStatistic(false),cutFileName(0),cutFile(0),tmpValue(0)
/*standart constructor, constructs a new univers with standart values
standart statistic file is: "./statistics.txt"*/
{
rg1=new TRandomMersenne(time(0)); // make instance of random number generator0
//new univers
TPoint* bang=new TPoint();//the littel bang point
bang->name=1;
last=1;
univers.push_back(bang);
setStatisticFileName("./statistics.txt");
setUniversFolderName("./universes/");//standart folder for the universes
setUniversFileBaseName("univers");//standart file base name for the universes
setRTimeFileName("./rTime.txt");
setCutFileName("./cut.txt");
for (unsigned long i=0;i<10;i++){trans[i]=0;}
}

Univers::Univers(bool outC, unsigned int cutA, unsigned long mTm, unsigned long maxP, unsigned long cMP, char* stat, char* uFol, char* bUN, double cutDim, double cutRatio, bool appU):
	iTime(0),pDistance(0),nDistance(0),
	outComent(outC),cutAfter(cutA),outUniv(0),outStat(0),bTime(0),
	maxTime(mTm),maxPoints(maxP),checkMaxPoints(cMP),statFile(0),statFileName(0),
	uFolder(0),bUName(0),cutNearDimension(cutDim),
	cutMaxClassRatio(cutRatio),appendUnivers(appU),parameterFile(0),
	outRealTime(false),rTimeFileName(0),rTimeFile(0),outCutStatistic(false),
	cutFileName(0),cutFile(0),tmpValue(0)
/*parameter constructor, constructs a new univers with standart values
beware this constructor copies just the char* pointers, but not the string in them!
parameters: output comments outC, cut after steps cutA, number of maxTime
mTm, name of the statistic file, the dimension to prefer by cut
cutNearDimension ,the Ratio till wich to generate the max class by cut
cutMaxClassRatio, check maxPoints condition every cMP (checkMaxPoints)
ticks, append univers if appU is true
standart statistic file is: "./statistics.txt"*/
{
rg1=new TRandomMersenne(time(0)); // make instance of random number generator0
//new univers
TPoint* bang=new TPoint();//the littel bang point
bang->name=1;
last=1;
univers.push_back(bang);
setStatisticFileName(stat);
setUniversFolderName(uFol);
setUniversFileBaseName(bUN);
setRTimeFileName("./rTime.txt");
setCutFileName("./cut.txt");
for (unsigned long i=0;i<10;i++){trans[i]=0;}
}


Univers::Univers(Univers &univ):iTime(univ.iTime),pDistance(univ.pDistance),nDistance(univ.nDistance),last(univ.last),
	outComent(univ.outComent),cutAfter(univ.cutAfter),outUniv(univ.outUniv),outStat(0),bTime(univ.bTime),
	maxTime(univ.maxTime),maxPoints(univ.maxPoints),checkMaxPoints(univ.checkMaxPoints),
	statFileName(0),uFolder(0),bUName(0),cutNearDimension(univ.cutNearDimension),
	cutMaxClassRatio(univ.cutMaxClassRatio),appendUnivers(false),
	parameterFile(0),outRealTime(false),rTimeFileName(0),rTimeFile(0),outCutStatistic(false),
	cutFileName(0),cutFile(0),tmpValue(0)
/*copy constructor, constructs a copy of the given univers;
statistic output cycles will be set to 0 and append univers will be false*/
{
rg1=new TRandomMersenne(time(0)); // make instance of random number generator
univers=copyUniversStructur(univ.univers);
setStatisticFileName(univ.getUniversFolderName());
setUniversFolderName(univ.getUniversFolderName());
setUniversFileBaseName(univ.getUniversFileBaseName());
setRTimeFileName(univ.getRTimeFileName());
setCutFileName(univ.getCutFileName());
for (unsigned long i=0;i<10;i++){trans[i]=univ.trans[i];}
}


Univers::~Univers()
/*standart destructor
destructs the univers and closes all open files of the univers*/
{
for (list<TPoint*>::iterator itr=univers.begin();itr!=univers.end();itr++)
	{delete (*itr);}//delete all points
univers.clear();
if (statFile!=NULL){statFile->close();delete statFile;}
delete [] statFileName;
delete [] uFolder;
delete [] bUName;
if (rTimeFile!=NULL){rTimeFile->close();delete rTimeFile;}
delete [] rTimeFileName;
if (cutFile!=NULL){cutFile->close();delete cutFile;}
delete [] cutFileName;
}

list<TPoint*> &Univers::copyUniversStructur(list<TPoint*> &univ) const
/*returns a copy of the given univers
pre: a univers to copy
post: a copy of the given univers*/
{
list<TPoint*> *univCopy=new list<TPoint*>;
TPoint* poi;
univ.sort(&TPoint::lower);
for (list<TPoint*>::iterator itr=univ.begin();itr!=univ.end();itr++){
	poi=new TPoint;
	poi->name=(*itr)->name;
	univCopy->push_back(poi);
}
list<TPoint*>::iterator itr1,itr2;
list<TPoint*>::iterator itrC=univCopy->begin();
for (list<TPoint*>::iterator itr=univ.begin();(itr!=univ.end())&&(itrC!=univCopy->end());itr++,itrC++)
{
	(*itr)->pPoint.sort(&TPoint::lower);
	itr1=univCopy->begin();
	for (itr2=(*itr)->pPoint.begin();itr2!=(*itr)->pPoint.end();itr2++)
	{
		if(((*itr)->name)>=(*itr2)->name){break;}
		while (itr1!=univCopy->end())
		{
			if ((*itr1)->name==(*itr2)->name) {break;};
			itr1++;
		}
		if(itr1!=univers.end()){//create positiv distance
			(*itrC)->pPoint.push_back(*itr1);
			(*itr1)->pPoint.push_back(*itrC);
		}
	}
	(*itr)->nPoint.sort(&TPoint::lower);
	itr1=univCopy->begin();
	for (itr2=(*itr)->nPoint.begin();itr2!=(*itr)->nPoint.end();itr2++)
	{
		if(((*itr)->name)>=(*itr2)->name){break;}
		while (itr1!=univers.end())
		{
			if ((*itr1)->name==(*itr2)->name) {break;};
			itr1++;
		}
		if(itr1!=univers.end()){//create positiv distance
			(*itrC)->nPoint.push_back(*itr1);
			(*itr1)->nPoint.push_back(*itrC);
		}
	}

}
return *univCopy;
}

//get methods

TUPart Univers::getUnivers()
/*returns the univers data
don't copy the univers
post: the data of the univers in a TUPart, with the pointer to the univers structur*/
{
TUPart tmpU;
tmpU.partUnivers=univers;
tmpU.pDistances=pDistance;//positiv Distances
tmpU.nDistances=nDistance;//negativ Distance
tmpU.last=last;
return tmpU;
}

//set methods:

unsigned long Univers::addNumberOfPDistance(const long pDDist)
/*adds the given number to the number of positiv distances of the univers
if the old number of positiv distances plus the given value is lower 0 the
number of positiv distances is set to 0
pre: number(positiv or negativ) to add to the positiv distances
post: the changed postitiv distances of the univers*/
{
if (long(pDistance)>=(-pDDist))
	{pDistance+=pDDist;}
else{pDistance=0;}
return pDistance;
}

unsigned long  Univers::addNumberOfNDistance(const long nDDist)
/*adds the given number to the number of negativ distances of the univers
if the old number of negativ distances plus the given value is lower 0 the
number of negativ distances is set to 0
pre: number(positiv or negativ) to add to the negativ distances
post: the changed negativ distances of the univers*/
{
if (nDistance>=(nDDist*-1.0))
	{nDistance+=nDDist;}
else{nDistance=0;}
return pDistance;
}

void Univers::setOutStatisticCycle(const unsigned long outS)
/*set after wich number of ticks a the statistics is outputed, if 0 don't output
pre: after wich number of ticks the statistics is outputed*/
{
if (outS&&(statFile==NULL))
{
	statFile=new fstream(statFileName,ios::out);
	if (statFile!=NULL){printStatisticHead(statFile);}
}
outStat=outS;
}

bool Univers::setStatisticFileName(char* statF)
/*set statistic file name, close the old statistic file, opens the new
statistic File and print the statistic head to it, if posibel
pre: a pointer to the statistic file name
post: true if the change was posibel(could open the new file), else false*/
{
if (statFileName) {delete [] statFileName;}
unsigned int i;
for(i=0;statF[i]!=0;i++);i++;//get length of string
statFileName=new char[i];
for(unsigned int a=0;a<i;a++){statFileName[a]=statF[a];}//copy string
if (statFile!=NULL){statFile->close();delete statFile;}
if (outStat)
{
	statFile=new fstream(statFileName,ios::out);
	if (statFile!=NULL){printStatisticHead(statFile);}
		else{return false;}
}else{statFile=NULL;}
return true;
}


void Univers::setOutRealTime(bool rT)
/*set if the real time statistic should be outputed
pre: the outRealTime value*/
{
if (rT&&(rTimeFile==NULL))
{
	rTimeFile=new fstream(rTimeFileName,ios::out);
	printRealTimeStatisticHead();
}
outRealTime=rT;
}

bool Univers::setRTimeFileName(char* rTimeF)
/*set eal time statistic file name, close the old statistic file, opens the new
statistic File and print the statistic head to it, if posibel
pre: a pointer to the real time statistic file name
post: true if the change was posibel(could open the new file), else false*/
{
if (rTimeFileName) {delete [] rTimeFileName;}
unsigned int i;
for(i=0;rTimeF[i]!=0;i++);i++;//get length of string
rTimeFileName=new char[i];
for(unsigned int a=0;a<i;a++){rTimeFileName[a]=rTimeF[a];}//copy string
if (rTimeFile!=NULL){rTimeFile->close();delete rTimeFile;}
if (outRealTime)
{
	rTimeFile=new fstream(rTimeFileName,ios::out);
	if (rTimeFile!=NULL){printRealTimeStatisticHead();}
		else{return false;}
}else{rTimeFile=NULL;}
return true;
}

void Univers::printRealTimeStatisticHead() const
/*prints the head of the real time statistic to the real time statistic file*/
{
if (rTimeFile!=NULL){
	(*rTimeFile)<<"time; real time; time till last tick; time for tick; time for cut;";
	 (*rTimeFile)<<"time for output the univers; time for direct statistic; ";
	 (*rTimeFile)<<"time for neibour statistic; time for distance statistic; time for part size statistic;"<<endl;
}
}

void Univers::setOutCutStatistic(bool cut)
/*set if the real time statistic should be outputed
pre: the outRealTime value*/
{
if (cut&&(cutFile==NULL))
{
	cutFile=new fstream(cutFileName,ios::out);
	printCutStatisticHead();
}
outCutStatistic=cut;
}

bool Univers::setCutFileName(char* cutF)
/*set eal time statistic file name, close the old statistic file, opens the new
statistic File and print the statistic head to it, if posibel
pre: a pointer to the real time statistic file name
post: true if the change was posibel(could open the new file), else false*/
{
if (cutFileName) {delete [] cutFileName;}
unsigned int i;
for(i=0;cutF[i]!=0;i++);i++;//get length of string
cutFileName=new char[i];
for(unsigned int a=0;a<i;a++){cutFileName[a]=cutF[a];}//copy string
if (cutFile!=NULL){cutFile->close();delete cutFile;}
if (outCutStatistic)
{
	cutFile=new fstream(cutFileName,ios::out);
	if (cutFile!=NULL){printCutStatisticHead();}
		else{return false;}
}else{cutFile=NULL;}
return true;
}

void Univers::printCutStatisticHead() const
/*prints the head of the cut statistic to the real time statistic file*/
{
if (cutFile!=NULL){
	(*cutFile)<<"time; all points; all positiv distances; all negativ distances; coherent parts;";
	(*cutFile)<<"data for parts (points, positiv distances, negativ distances); "<<endl;
}//6 * ';'
}


bool Univers::printUnivers(ostream &ostream)
/*prints the values of the univers to the given output stream, if it exists
pre: the outputstream ostream to print the univers to
post: if the stream exists true and the actual univers in the stream
	ostream in a readebel form(integer numbers seperated by ",",";" and "."),
	false else*/
{
if(!ostream){return false;}
univers.sort(&TPoint::lower);
//convert and output the univers to a output form
ostream<<(unsigned long)univers.size()<<"."<<endl;
for (list<TPoint*>::iterator itr=univers.begin();itr!=univers.end();itr++)
	{ostream<<(**itr);}
return true;
}


bool Univers::readUnivers(istream &stream)
/*replaces the actual univers with the univers of the stream, if it exists,
for that deletes the old univers and reads the values of the univers from
the stream(the values should be of the form of printUnivers uses)
pre: the input stream stream to read the univers from
post: if the stream exists true and this univers is the univers readed from
	the stream, else false*/
{
if (!stream){return false;}
//delete old universe
pDistance=0;//positiv Distances
nDistance=0;//negativ Distances
for (list<TPoint*>::iterator itr=univers.begin();itr!=univers.end();)
	{delete (*itr);univers.erase(itr);itr=univers.begin();}//delete all pointe
//read Data
unsigned long size,a;
unsigned long name;
char c;
stream>>size;
if(outComent){cout<<"univers size : "<<size<<endl;}
stream>>c;//"."
TOPoint tmpU[size];
for (unsigned long i=0;i<size;i++)
{
	stream>>name;
	stream>>c;
	for(;;)
	{
		stream>>c;
		if (c==';'){break;}
		stream>>a;
		tmpU[i].pPoint.push_back(a);
		pDistance++;
	}
	for(;;)
	{
		stream>>c;
		if (c=='.'){break;}
		stream>>a;
		tmpU[i].nPoint.push_back(a);
		nDistance++;
	}
	tmpU[i].pPoint.sort();
	tmpU[i].nPoint.sort();//find faster the conected points
	tmpU[i].original=new TPoint;
	tmpU[i].original->name=name;
	univers.push_back(tmpU[i].original);//insert Point in universe
	if (name>last){last=name;}
}
univers.sort(&TPoint::lower);//find faster the conected points
pDistance=pDistance/2;nDistance=nDistance/2;//distances are double counted
//convert Distances
list<TPoint*>::iterator itr1;
if(outComent){cout<<endl;}
for (unsigned long i=0;i<size;i++)
{
	if(outComent){if(((i>>8)<<8)==i){cout<<i<<" : "<<flush;}}
	//find conected points and make conection to them
	itr1=univers.begin();
	for (list<unsigned long>::iterator itr=tmpU[i].pPoint.begin();itr!=tmpU[i].pPoint.end();itr++)
	{
		if((tmpU[i].original->name)<=(*itr)){break;}
		while (itr1!=univers.end())
		{
			if ((*itr1)->name==(*itr)) {break;};
			itr1++;
		}
		if(itr1!=univers.end()){//create positiv distance
			tmpU[i].original->pPoint.push_back(*itr1);
			(*itr1)->pPoint.push_back(tmpU[i].original);
		}
	}
	itr1=univers.begin();
	for (list<unsigned long>::iterator itr=tmpU[i].nPoint.begin();itr!=tmpU[i].nPoint.end();itr++)
	{
		if((tmpU[i].original->name)<=(*itr)){break;}
		while (itr1!=univers.end())
		{
			if ((*itr1)->name==(*itr)) {break;};
			itr1++;
		}
		if(itr1!=univers.end()){//create negativ distance
			tmpU[i].original->nPoint.push_back(*itr1);
			(*itr1)->nPoint.push_back(tmpU[i].original);
		}
	}
}
if(outComent){cout<<"reading done"<<endl;}
return true;
}


void Univers::nullTMPValues()
/*sets all tmpValues (of all points and the univers) to 0*/
{
for (list<TPoint*>::iterator uItr=univers.begin();uItr!=univers.end();uItr++)
	{(*uItr)->tmpValue=0;}
tmpValue=0;
}

void Univers::cutUnivers(const double dim, const double maxClass)
/*Trys to delete parts of the univers that are no more conected to the main part.
The main part is the part, wich is the biggest(in number of Distances)
under the parts that are not smaler than (maxClass * (biggest Part)) and that
has a dimension nearest to dim.
pre: the value of the dimension dim to be nearest to and the minimum ratio
	maxClass the universes to choos must have (if 1 the bigest univers will
	allways be choosen)
post: the choosen univers as this univers*/
{
list<TUPart> uParts;
list<TUPart>::iterator pItr;
list<TPoint*>::iterator uItr;
list<TPoint*>::iterator itr1;
list<TPoint*>::iterator itr2;
TUPart ePart;
if(tmpValue>=+4294967000U){nullTMPValues();}
tmpValue++;
if(outCutStatistic&&(cutFile!=NULL))
	{(*cutFile)<<bTime+iTime<<"; "<<getNumberOfPoints()<<"; "<<pDistance<<"; "<<nDistance<<"; ";}
//seperate the parts
while(!univers.empty())
{
	//insert new empty part univers
	pItr=uParts.insert(uParts.end(),ePart);
	pItr->pDistances=0;pItr->nDistances=0;
	//transver the firts point of the univers to the new part and delet transvered part
	pItr->partUnivers.push_back(*(univers.begin()));
	(*(univers.begin()))->tmpValue=tmpValue;
	univers.erase(univers.begin());
	for (uItr=pItr->partUnivers.begin();uItr!=pItr->partUnivers.end();uItr++)
	{//for all conections to the Point transfer conected points to the part
		pItr->pDistances+=(*uItr)->pPoint.size();pItr->nDistances+=(*uItr)->nPoint.size();
		//distances are double counted
		for (itr1=(*uItr)->pPoint.begin();itr1!=(*uItr)->pPoint.end();itr1++)
		{
			if((*itr1)->tmpValue!=tmpValue)
			{//if the Point is not in the part, insert it and erase right point from the univers
				(*itr1)->tmpValue=tmpValue;
				pItr->partUnivers.push_back(*itr1);
			}
		}
		for (itr1=(*uItr)->nPoint.begin();itr1!=(*uItr)->nPoint.end();itr1++)
		{//get right point
			if((*itr1)->tmpValue!=tmpValue)
			{//if the Point is not in the part, insert it and erase right point from the univers
				(*itr1)->tmpValue=tmpValue;
				pItr->partUnivers.push_back(*itr1);
			}
		}
	}
	//delete the points the wher inserted in a part
	for (uItr=univers.begin();uItr!=univers.end();uItr++){
		if((*uItr)->tmpValue==tmpValue)
			{uItr=univers.erase(uItr);uItr--;}}
}
//bigger universes first
uParts.sort();
uParts.reverse();
if(outComent){cout<<"cutparts : "<<uParts.size();}
if(outCutStatistic&&(cutFile!=NULL)){
	(*cutFile)<<uParts.size()<<"; ";
	for (pItr=uParts.begin();pItr!=uParts.end();pItr++)
		{(*cutFile)<<"( "<<pItr->partUnivers.size()<<", "<<pItr->pDistances/2<<", "<<pItr->nDistances/2<<" ) ";}
	(*cutFile)<<";"<<endl;
}
//choos part
pItr=uParts.begin();
if((maxClass<=1.0)&&(maxClass>0.0))
{
	list<TUPart>::iterator tItr=uParts.begin();
	double dimDist=((double)((pItr->pDistances+pItr->nDistances)/2)/(double)(pItr->partUnivers.size()))-dim;
	if (dimDist<0){dimDist=dimDist*(-1.0);}
	double tDist;
	double biggest=((double)(pItr->pDistances+pItr->nDistances));
	for(;;)
	{
		tItr++;
		if (tItr==uParts.end()){break;}
		//if the part is in the max class and has a nearer dimension to dim, choos it
		if((double)(tItr->pDistances+tItr->nDistances)<(biggest*maxClass)){break;}
		tDist=((double)((tItr->pDistances+tItr->nDistances)/2)/(double)(tItr->partUnivers.size()))-dim;
		if (tDist<0.0){tDist=tDist*(-1.0);}
		if (dimDist>tDist) {pItr=tItr;dimDist=tDist;}
	}
}
//transfer choosen part pItr to univers
univers=pItr->partUnivers;
pDistance=(pItr->pDistances)/2;nDistance=(pItr->nDistances)/2;//all distances wher counted double
uParts.erase(pItr);//don't delete points
//delete other parts points
for (pItr=uParts.begin();pItr!=uParts.end();pItr++)
{
	for (uItr=pItr->partUnivers.begin();uItr!=pItr->partUnivers.end();uItr++)
		{delete (*uItr);uItr=pItr->partUnivers.erase(uItr);}
}
}

inline void Univers::evaluePoint(TPoint* poi)
/*Makes a random transition of the transition diagram with the TPoint poi
(p2 in the diagram) and two random neigthbours(includes new TPoints)(p1 and
p3 in the diagram).
pre: the choosen point poi of the univers
post: the this univers changed through the transition*/
{
unsigned long pDist=poi->pPoint.size();
unsigned long nDist=poi->nPoint.size();
unsigned long Point1=rg1->IRandom(0,(pDist+nDist));//choos first point(p1)
unsigned long Point2=rg1->IRandom(0,(pDist+nDist));//choos secound(p3) point
//if Point1/2 is (pDist+nDist) it is a new Point, if it is smaler then pDist
//it has a positiv conection(distance) to pio(p2) else it has negativ
//conection(distance) to pio(p2)
if ((Point1==Point2)&&(Point1!=pDist+nDist)) {return;}//this conection would destry itself
list<TPoint*>::iterator itr1;//Point1
list<TPoint*>::iterator itr2;//Point2
list<TPoint*>::iterator itr3;//Point3; this point
//3 posibilitys for each point: point is new, point is pDist or point is nDist
//trans = transition as in the transitions diagram
if (Point1<pDist)
{
	for (itr1=poi->pPoint.begin();itr1!=poi->pPoint.end();itr1++)
		{if (Point1==0){break;}Point1--;}//get right point
	if (Point2<pDist)//trans 1
	{
		for (itr2=poi->pPoint.begin();itr2!=poi->pPoint.end();itr2++)
			{if (Point2==0){break;}Point2--;}//get right point
		if ((*itr1)==(*itr2)){//don't make a distance with the same endpoints
			TPoint* tmpP2=new TPoint();
			last++;tmpP2->name=last;
			univers.push_back(tmpP2);
			(*itr1)->pPoint.push_back(tmpP2);
			tmpP2->pPoint.push_back(*itr1);
			poi->pPoint.erase(itr1);
			for (itr3=(*itr1)->pPoint.begin();itr3!=(*itr1)->pPoint.end();itr3++)
				{if ((*itr3)==poi){break;}}//get right point
			(*itr1)->pPoint.erase(itr3);
		}else{
			TPoint* tmpP2=(*itr2);
			(*itr1)->pPoint.push_back(tmpP2);
			tmpP2->pPoint.push_back(*itr1);
			poi->pPoint.erase(itr2);
			for (itr3=tmpP2->pPoint.begin();itr3!=tmpP2->pPoint.end();itr3++)
				{if ((*itr3)==poi){break;}}//get right point
			tmpP2->pPoint.erase(itr3);
		}
		trans[1]++;
 }else{
		if (Point2<(pDist+nDist))//Point2>=pDist; trans 2
		{
			Point2-=pDist;
			for (itr2=poi->nPoint.begin();itr2!=poi->nPoint.end();itr2++)
				{if (Point2==0){break;}Point2--;}//get right point
			(*itr1)->pPoint.push_back(poi);
			poi->pPoint.push_back(*itr1);
			(*itr2)->nPoint.push_back(poi);
			poi->nPoint.push_back(*itr2);
			pDistance++;nDistance++;trans[2]++;
		}else{//Point2==pDist+nDist->make nnew point; trans 5
			(*itr1)->pPoint.push_back(poi);
			poi->pPoint.push_back(*itr1);
			TPoint* tmpP=new TPoint();
			last++;tmpP->name=last;
			univers.push_back(tmpP);
			poi->nPoint.push_back(tmpP);
			tmpP->nPoint.push_back(poi);
			pDistance++;nDistance++;trans[5]++;
		}
	}
}else{
	if (Point1<(pDist+nDist))//Point1>=pDist
	{
		Point1-=pDist;
		for (itr1=poi->nPoint.begin();itr1!=poi->nPoint.end();itr1++)
			{if (Point1==0){break;}Point1--;}//get right point
		if (Point2<pDist)//trans 3
		{
			for (itr2=poi->pPoint.begin();itr2!=poi->pPoint.end();itr2++)
				{if (Point2==0){break;}Point2--;}//get right point
			TPoint* tmpP1=(*itr1);
			TPoint* tmpP2=(*itr2);
			poi->nPoint.erase(itr1);
			for (itr3=tmpP1->nPoint.begin();itr3!=tmpP1->nPoint.end();itr3++)
				{if ((*itr3)==poi){break;}}//get right point
			tmpP1->nPoint.erase(itr3);
			poi->pPoint.erase(itr2);
			for (itr3=tmpP2->pPoint.begin();itr3!=tmpP2->pPoint.end();itr3++)
				{if ((*itr3)==poi){break;}}//get right point
			tmpP2->pPoint.erase(itr3);
			pDistance--;nDistance--;trans[3]++;
		}else{
			if (Point2<(pDist+nDist))//Point2>=pDist; trans 4
			{
				Point2-=pDist;
				for (itr2=poi->nPoint.begin();itr2!=poi->nPoint.end();itr2++)
					{if (Point2==0){break;}Point2--;}//get right point
				if ((*itr1)==(*itr2)){//don't make a distance with the same endpoints
					TPoint* tmpP2=new TPoint();
					last++;tmpP2->name=last;
					univers.push_back(tmpP2);
					(*itr1)->nPoint.push_back(tmpP2);
					tmpP2->nPoint.push_back(*itr1);
					poi->nPoint.erase(itr1);
					for (itr3=(*itr1)->nPoint.begin();itr3!=(*itr1)->nPoint.end();itr3++)
						{if ((*itr3)==poi){break;}}//get right point
					(*itr1)->nPoint.erase(itr3);
				}else{
					TPoint* tmpP1=(*itr1);
					(*itr2)->nPoint.push_back(tmpP1);
					tmpP1->nPoint.push_back(*itr2);
					poi->nPoint.erase(itr1);
					for (itr3=tmpP1->nPoint.begin();itr3!=tmpP1->nPoint.end();itr3++)
						{if ((*itr3)==poi){break;}}//get right point
					tmpP1->nPoint.erase(itr3);
				}
				trans[4]++;
			}else{//Point2==pDist+nDist; trans 7
				TPoint* tmpP2=new TPoint();
				last++;tmpP2->name=last;
				univers.push_back(tmpP2);
				TPoint* tmpP1=(*itr1);
				(*itr1)->nPoint.push_back(tmpP2);
				tmpP2->nPoint.push_back(*itr1);
				poi->nPoint.erase(itr1);
				for (itr3=tmpP1->nPoint.begin();itr3!=tmpP1->nPoint.end();itr3++)
					{if ((*itr3)==poi){break;}}//get right point
				tmpP1->nPoint.erase(itr3);
				trans[7]++;
			}
		}
	}else{//Point1==pDist+nDist
		if (Point2<pDist)//; trans 6
		{
			for (itr2=poi->pPoint.begin();itr2!=poi->pPoint.end();itr2++)
				{if (Point2==0){break;}Point2--;}//get right poi
			TPoint* tmpP1=new TPoint();
			last++;tmpP1->name=last;
			univers.push_back(tmpP1);
			TPoint* tmpP2=(*itr2);
			(*itr2)->pPoint.push_back(tmpP1);
			tmpP1->pPoint.push_back(*itr2);
			poi->pPoint.erase(itr2);
			for (itr3=tmpP2->pPoint.begin();itr3!=tmpP2->pPoint.end();itr3++)
				{if ((*itr3)==poi){break;}}//get right point
			tmpP2->pPoint.erase(itr3);
			trans[6]++;
		}else{
			if (Point2<(pDist+nDist))//Point2>=pDist; trans 8
			{
				Point2-=pDist;
				for (itr2=poi->nPoint.begin();itr2!=poi->nPoint.end();itr2++)
					{if (Point2==0){break;}Point2--;}//get right point
				(*itr2)->nPoint.push_back(poi);
				poi->nPoint.push_back(*itr2);
				TPoint* tmpP1=new TPoint();
				last++;tmpP1->name=last;
				univers.push_back(tmpP1);
				poi->pPoint.push_back(tmpP1);
				tmpP1->pPoint.push_back(poi);
				pDistance++;nDistance++;trans[8]++;
			}else{//Point2==pDist+nDist->two new points; trans 9
				TPoint* tmpP1=new TPoint();
				last++;tmpP1->name=last;
				univers.push_back(tmpP1);
				poi->pPoint.push_back(tmpP1);
				tmpP1->pPoint.push_back(poi);
				TPoint* tmpP2=new TPoint();
				last++;tmpP2->name=last;
				univers.push_back(tmpP2);
				poi->nPoint.push_back(tmpP2);
				tmpP2->nPoint.push_back(poi);
				pDistance++;nDistance++;trans[9]++;
			}
		}
	}
}

}

void Univers::tick()
/*Evalue a tick, minimal time change, of the univers. For that to all
points of the univers a random transition is performed.
Points that have no neigthbours are deleted.
post: this univers changed*/
{
list<TPoint*>::iterator itr=univers.begin();
unsigned long uSz=univers.size();
for (unsigned long i=0;i<10;i++)
	{trans[i]=0;}
for (unsigned long i=0;i<uSz;i++)//evalue all old points
{
	if ((((*itr)->pPoint.empty())&&((*itr)->nPoint.empty()))&&(univers.size()>1))
	{//cut points with no conections
		delete (*itr);itr=univers.erase(itr);
	}else{
		evaluePoint(*itr);
		itr++;
	}
}
}

void Univers::tick(unsigned long trans)
/*Evalue a tick, minimal time change, of the univers. For that on trans
random choosen points of the univers a random transition is performed.
Points that have no neigthbours are deleted.
post: this univers changed*/
{
list<TPoint*>::iterator itr=univers.begin();
unsigned long rand=0;
for (unsigned long i=0;i<trans;i++)//evalue trans transitions
{
	rand=rg1->IRandom(0,univers.size());
	for (;rand>0;rand--){
		itr++;
		if(itr==univers.end()){itr=univers.begin();}
	}

	if ((((*itr)->pPoint.empty())&&((*itr)->nPoint.empty()))&&(univers.size()>1))
	{//cut points with no conections
		delete (*itr);itr=univers.erase(itr);
		i--;
	}else{evaluePoint(*itr);}
}
}

bool Univers::printStatisticHead(ostream* ostream) const
/*Print the head of the statistics to the statistic stream, if it exists.
The diverent rows a seperated by ";".
pre: the output stream ostream to print the statistics head to
post: true if the stream exists and the head of the statistics in the
	output stream, else false */
{
if(ostream==NULL){return false;}
(*ostream)<<"time ; points ; pos distances ; neg distances ; distances/points ; ";
(*ostream)<<"transitions ins ; trans 1 ; trans 1 p ; trans 2 ; trans 2 p ; trans 3 ; trans 3 p ; trans 4 ; trans 4 p ; ";
(*ostream)<<"trans 5 ; trans 5 p ; trans 6 ; trans 6 p ; trans 7 ; trans 7 p ; trans 8 ; trans 8 p ; trans 9 ; trans 9 p ; ";
(*ostream)<<endl;
return true;
}

bool Univers::printStatistic(ostream* ostream)
/*Print the the statistics of the actual univers and the last transitions
to the statistic stream, if it exists. The diverent rows a seperated by ";".
Prints one line.
pre: the output stream ostream to print the actual statistics to
post: if the stream exists true and the actual statistics in the output
	stream, else false*/
{
if(ostream==NULL){return false;}
//trans[0] is the transition sum
trans[0]=trans[1]+trans[2]+trans[3]+trans[4]+trans[5]+trans[6]+trans[7]+trans[8]+trans[9];
(*ostream)<<iTime+bTime<<" ; "<<getNumberOfPoints()<<" ; "<<pDistance<<" ; "<<nDistance;
(*ostream)<<" ; "<<((double)(pDistance+nDistance)/(double)(getNumberOfPoints())) <<" ; ";
(*ostream)<<trans[0]<<" ; "<<trans[1]<<" ; "<<(double)(trans[1])/(double)(trans[0])<<" ; ";
(*ostream)<<trans[2]<<" ; "<<(double)(trans[2])/(double)(trans[0])<<" ; ";
(*ostream)<<trans[3]<<" ; "<<(double)(trans[3])/(double)(trans[0])<<" ; ";
(*ostream)<<trans[4]<<" ; "<<(double)(trans[4])/(double)(trans[0])<<" ; ";
(*ostream)<<trans[5]<<" ; "<<(double)(trans[5])/(double)(trans[0])<<" ; ";
(*ostream)<<trans[6]<<" ; "<<(double)(trans[6])/(double)(trans[0])<<" ; ";
(*ostream)<<trans[7]<<" ; "<<(double)(trans[7])/(double)(trans[0])<<" ; ";
(*ostream)<<trans[8]<<" ; "<<(double)(trans[8])/(double)(trans[0])<<" ; ";
(*ostream)<<trans[9]<<" ; "<<(double)(trans[9])/(double)(trans[0])<<" ; ";
(*ostream)<<endl;
return true;
}

bool Univers::endCondition() const
/*Evalues the end condition for the univers. Means when the evaluation of
the univers is stoped.
case 1: the time iTime is higer than the maximum number of ticks(maxTime,
	maxTime=0 -> inf) or (the number of points should be checked (it is the
	checkMaxPoints tick) and it is higher then the maximal number of points
	(maxPoints, maxPoints=0 -> inf))
post: true if the end condition holds and the univers should be stoped,
	else false*/
{
if ((maxTime==0))
{
	if ((maxPoints==0)||(checkMaxPoints==0))
		{return false;}//run infinity
	if ((checkMaxPoints)&&((((iTime/checkMaxPoints)*checkMaxPoints)==iTime)))
		{return (maxPoints<getNumberOfPoints());}
		return false;
}
if ((maxPoints==0)||(checkMaxPoints==0))
	{return (iTime+bTime>=maxTime);}
if (((iTime/checkMaxPoints)*checkMaxPoints)==iTime)
	{return ((iTime+bTime>=maxTime)||(maxPoints<getNumberOfPoints()));}
return (iTime+bTime>=maxTime);
}

void Univers::start(unsigned long trans)
/*Starts the evaluation of the univers. Makes ticks till the end condition
holds.
post: the this univers changed*/
{
while (!endCondition())
{
	iTime++;
	if (trans==0) {tick();}
		else{tick(trans);}
	if(outComent)
	{
		cout<<"iteration : "<<iTime<<" Points : "<<getNumberOfPoints()<<" pos distances : "<<pDistance;
		cout<<" neg distances : "<<nDistance<<" distances/points : "<<((double)(pDistance+nDistance)/ (double)(getNumberOfPoints())) <<endl;
	}
	if((cutAfter)&&((iTime/cutAfter)*cutAfter==iTime))//dont cut every time
	{//cut univers
		cutUnivers(cutNearDimension, cutMaxClassRatio);
		if(outComent)
		{
			cout<<" points: "<<getNumberOfPoints()<<" pos distances : "<<pDistance;
			cout<<" neg distances : "<<nDistance<<" distances/points : "<<((double)(pDistance+nDistance)/(double)(getNumberOfPoints()))<<endl;
		}
	}
	if (outStat && (statFile)) if (((bTime+iTime)/outStat)*outStat==(bTime+iTime)){printStatistic(statFile);}
	if (outUniv) if (((bTime+iTime)/outUniv)*outUniv==(bTime+iTime))
	{//output actual universe
		char univFile[1000];
		sprintf(univFile,"%s%s%i.txt",uFolder,bUName,bTime+iTime);
		ofstream uFile(univFile);
		if(uFile)
		{
			printUnivers(uFile);
			uFile.close();
		}else {printf( "Problem opening the univers file\n" );}
	}
}
}



#ifndef ___Univers_OutOp__
#define ___Univers_OutOp__
ostream &operator<<(ostream &ostream, TPoint &tpoi)
/*outputs this TPoint to the ostream
first comes the name of this TPoint then a ";", the the names of positiv
neigbours(for each a ","), then a ";", the the names of negativ
neigbours(for each a ","), the a "." and a newline
pre: this TPoint
post: this TPoint in the stream*/
{
ostream<<tpoi.name<<";";
for (list<TPoint*>::iterator itr1=tpoi.pPoint.begin();itr1!=tpoi.pPoint.end();itr1++)
{
	ostream<<","<<(*itr1)->name;
}
ostream<<";";
for (list<TPoint*>::iterator itr1=tpoi.nPoint.begin();itr1!=tpoi.nPoint.end();itr1++)
{
	ostream<<","<<(*itr1)->name;
}
ostream<<"."<<endl;
return ostream;
}
#endif




