/*File Name: Univers.h
  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

compile file with:
	g++ -Wall -g -o univ universe.cpp
	g++ -Wall -g -O -o univ universe.cpp
	g++ -Wall -g -O1 -o univ universe.cpp

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

*/

#ifndef ___UNIVERS_h__
#define ___UNIVERS_h__

#include <iostream>
//#include <stdio.h>
#include <fstream>
#include <list>
#include <utility>
//#include <time.h>// define time()

#include "mersenne.h"
#include "ReadValues.h"

using std::list;
using std::pair;
using std::ostream;
using std::ofstream;
using std::fstream;
using std::ios;
using std::istream;
using std::ifstream;
using std::cout;
using std::endl;
using std::flush;
using namespace ReadValues;

class TPoint{//links to cells/nodes
//class of the univers points
public:
	unsigned long name;//name of the point
	list<TPoint*> pPoint;//positv neibors
	list<TPoint*> nPoint;//negativ neibors

	unsigned long tmpValue;/*this variable helps to spead up the algorithm,
		be carefull if you change this, the value of this variable should
		always be smale as the tmpValue of the univers*/

	TPoint():name(0),tmpValue(0){}
	/*standart constructor*/

	TPoint(TPoint &poi):name(poi.name),pPoint(poi.pPoint),nPoint(poi.nPoint),tmpValue(0)
	/*copy constructor*/
	{}

	bool operator<(const TPoint tpoi) const
	/*the lower realtion for TPoint
	pre: two TPoint
	post: true if the name of the first TPoint of the first is lower
		then the secound, else false*/
	{return (name<tpoi.name);}

	friend ostream &operator<<(ostream &ostream, TPoint &tpoi);

	bool static lower(const TPoint* tpoi1,const TPoint* tpoi2)
	/*the lower realtion for TPoint pointers
	pre: two TPoint pointers
	post: true if the name of the first TPoint of the first pointer is lower
		then the secound, else false*/
	{return ((tpoi1->name)<(tpoi2->name));}
};



class TOPoint{//output form of a TPoint
public:
	TPoint* original;//pointer to the original point
	list<unsigned long> pPoint;//positiv neibors
	list<unsigned long> nPoint;//negativ neibors
};

class TUPart{
//part universes, with relevant data
public:
	list<TPoint*> partUnivers;//the part univers structur
	unsigned long pDistances;//positiv Distances
	unsigned long nDistances;//negativ Distance
	unsigned long last;//last given name
	bool operator<(const TUPart part) const
		{return ((pDistances+nDistances)<(part.pDistances+part.nDistances));}
	bool operator>(const TUPart part) const
		{return ((pDistances+nDistances)>(part.pDistances+part.nDistances));}
};

class TParameter{
//class to store the line and comments of the parameter
public:
	unsigned int line;//line wher the parameter should be writen
	unsigned int number;//number of the parameter
	char* name;//description of the parameter

	TParameter():line(0),number(0),name(0)
	/*standart constructor of this class
	standart values are 0 far all*/
	{}

	TParameter(const TParameter &tPara):line(tPara.line),number(tPara.number)
	/*copy constructor of this class
	copies the values and the name string*/
	{
	if(tPara.name)
	{
		unsigned int i=0;
		for(i=0;tPara.name[i]!=0;i++){}//cont chars of the name of tPara
		name=new char[i+1];
		for(unsigned int a=0;a<=i;a++){name[a]=tPara.name[a];}
	}else{name=0;}
	}

	bool operator<(const TParameter para) const
	/*order the parameter by lines
	pre: a paramerter para to compare this parameter with
	post: true if this parameter has a lower line as te given parameter, else false*/
		{return (line<(para.line));}

};

class Univers
{

protected:
	TRandomMersenne *rg1;//random generator
	list<TPoint*> univers;//structur of the univers
	unsigned long iTime;//intern time(number of ticks till creation)
	unsigned long pDistance;//positiv Distances
	unsigned long nDistance;//negativ Distances
	unsigned long trans[10];//number of transitions i
	unsigned long last; //last point
	bool outComent;//output comments?
	unsigned long cutAfter;//cut every cutAfter ticks; if 0 don't cut
	unsigned long outUniv;//output the actual univers every outUniv ticks; if 0 don't output
	unsigned long outStat;//output the statistics every outStat ticks; if 0 don't output
	long bTime;//the basis time to begin conting with
	unsigned long maxTime;// maximal Time (0 = infinum); if iTime > maxTime stop evaluation(tick)
	unsigned long maxPoints;//maximal number of points avter iteration/tick
		//(0 = infinum) if the univers has more after a tick the end condition is reached
	unsigned long checkMaxPoints;//check maxPoints condition every
		//checkMaxPoints ticks; if 0 don't check; standart is 1
	fstream *statFile;//statistic file
	char* statFileName;//name of the statistic file
	char* uFolder;//folder for the universes to write to, standart is: "./universes/"
	char* bUName;//base name for the universes files,standart is: "univers" it will be converted to "univers(bTime+iTime).txt
	double cutNearDimension;//the dimension to prefer to be nearest to with
		//the choosen univers by the cut operation
	double cutMaxClassRatio;//cut operator the size ratio to the maximal
		//univers, till wich universes are put in the class to choose the
		//best from(best is the one with a dimension nearest cutNearDimension)
	bool appendUnivers;//is true if the new univers data should appendet to the old
	char* parameterFile;//the file wher the parameters are loaded from and should be stored to if the univers should appended
	list<TParameter> parameter;//the numbers and text to the parameter of this class instanze
	bool outRealTime;//if the time statistic should be outputed
	char* rTimeFileName;//the name of the file wher the real time statistic should be outputed
	fstream *rTimeFile;//the file wher the real time statistic is stored
	bool outCutStatistic;//if the cut statistic should be outputed
	char* cutFileName;//the name of the file wher the cut statistic  should be outputed
	fstream *cutFile;//the file wher the cut statistic is stored

	unsigned long tmpValue;/*this variable helps to spead up the algorithm,
	be carefull if you change this, the value of all point variables should
	always be smale as the tmpValue of the univers*/

	void nullTMPValues();
	/*sets all tmpValues (of all points and the univers) to 0*/

public:
	Univers();
	/*standart constructor, constructs a new univers with standart values
	standart statistic file is: "./statistics.txt"*/

	Univers(bool outC, unsigned int cutA=0, unsigned long mTm=1000, unsigned long maxP=0, unsigned long cMP=1, char* stat="./statistics.txt", char* uFol="./universes/", char* bUN="univers", double cutDim=3.0, double cutRatio=1.0, bool appU=false);
	/*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"*/

	Univers(Univers &univ);
	/*copy constructor, constructs a copy of the given univers*/

	~Univers();
	/*standart destructor
	destructs the univers and closes all open files of the univers*/

	list<TPoint*> &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*>* getUniversStructur() {return &univers;}
	/*returns a pointer to the univers
	post: the pointer to the univers structur*/

	TUPart 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*/

	unsigned long getNumberOfPoints() const {return univers.size();}
	/*returns the number of the points in the univers
	post: the number of the points of the univers*/

	unsigned long getInternalTime() const {return iTime;}
	/*returns the internal Time(number of ticks till creation) of the univers
	post: the internal time of the univers*/

	unsigned long getNumberOfPDistance() const {return pDistance;}
	/*returns the number of the positiv Distances in the univers
	post: the number of the positiv Distances of the univers*/

	unsigned long getNumberOfNDistance() const {return nDistance;}
	/*returns the number of the negativ Distances in the univers
	post: the number of the negativ Distances of the univers*/

	unsigned long* getNumberOfLastTransitions()
	/*returns the number of the different transitions in the last tick(0-9)
	like in the transition diagram above; array point 0 is the transition sum
	post: the number of the transitions of the univers*/
	{trans[0]=trans[1]+trans[2]+trans[3]+trans[4]+trans[5]+trans[6]+trans[7]+trans[8]+trans[9];
	return trans;}

	unsigned long getLastName() const {return last;}
	/*returns the last name number of the univers in the univers
	post: the number of the negativ Distances of the univers*/

	bool getCommentsActiv() const {return outComent;}
	/*returns if comments are shown
	post: true if comments are shown, else false*/

	unsigned long getCutCycle() const {return cutAfter;}
	/*returns the after wich number of maxTime a cut is performed
	if 0 is returned don't cut
	post: after wich number of maxTime a cut is performed*/

	unsigned long getOutUniversCycle() const {return outUniv;}
	/*returns the after wich number of maxTime a the univers is outputed
	if 0 is returned don't output
	post: after wich number of maxTime the univers is outputed*/

	unsigned long getOutStatisticCycle() const {return outStat;}
	/*returns the after wich number of maxTime a the statistics is outputed
	if 0 is returned don't output
	post: after wich number of maxTime the statistics is outputed*/

	long getTimeBase() const {return bTime;}
	/*returns the time base of the univers(the time the univers begins is user defined)
	post: the time base*/

	unsigned long getMaxNumberOfTime() const {return maxTime;}
	/*returns the maximal Time
	if 0 repeat infinum
	post: the maximal Time*/

	unsigned long getMaxNumberOfPoints() const {return maxPoints;}
	/*returns the maximal number of points(maximal number after a tick)
	if 0 repeat infinum
	post: the maximal number of maxTime*/

	unsigned long getCheckMaxPoints() const {return checkMaxPoints;}
	/*returns every wich number of ticks the maxPoints condition should be
	checked; if 0 never check
	post: the number of ticks the max point condition is checked*/

	char* getStatisticFileName() const {return statFileName;}
	/*returns the statistic file name
	post: the statistic file name*/

	char* getUniversFolderName() const {return uFolder;}
	/*returns the univers folder name, wher the actual universes files are writen to
	post: the univers folder*/

	char* getUniversFileBaseName() const {return bUName;}
	/*returns the univers file base name, with wich the saved universes begin with
	post: the univers base name*/

	double getCutNearDimension() const {return cutNearDimension;}
	/*returns the cutNearDimension value
	post: the cutNearDimension value*/

	double getCutMaxClassRatio() const {return cutMaxClassRatio;}
	/*returns the cutMaxClassRatio value
	post: the cutMaxClassRatio value*/

	bool getOutRealTime() const {return outRealTime;}
	/*returns if the real time statistic should be outputed
	post: the outRealTime value*/

	char* getRTimeFileName() const {return rTimeFileName;}
	/*returns the real time statistic file name
	post: the real time statistic name*/

	bool getOutCutStatistic() const {return outCutStatistic;}
	/*returns if the cut statistic should be outputed
	post: the outCutStatistic value*/

	char* getCutFileName() const {return cutFileName;}
	/*returns the cut statistic file name
	post: the cut statistic name*/

//set methods

	unsigned long 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*/

	unsigned long  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*/

	void setCommentsActiv(const bool comAc) {outComent=comAc;}
	/*set if comments are shown
	pre: a value if the comments should be shown*/

	void setCutCycle(const unsigned long cutA){cutAfter=cutA;}
	/*set after wich number of ticks a cut is performed, 0 don't cut
	pre: after wich number of ticks a cut is performed*/

	void setOutUniversCycle(const unsigned long outU)
		{if ((outUniv==0)&&(outU)){cratePath(uFolder);}outUniv=outU;}
	/*set after wich number of ticks a the univers is outputed, if 0 don't output
	pre: after wich number of ticks the univers is outputed*/

	void 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*/

	void setTimeBase(const long bTim) {bTime=bTim;}
	/*set the time base of the univers(the time the univers begins is user defined)
	pre: the time base*/

	void setMaxNumberOfTime(const unsigned long mTm) {maxTime=mTm;}
	/*set the maximal Time(number of ticks performed), if 0 repeat infinum
	pre: the maximal Time*/

	void setMaxNumberOfPoints(const unsigned long mPoi) {maxPoints=mPoi;}
	/*set maximal number of points(maximal number after a tick)
	if 0 infinum points
	pre: the maximal number of points till stop*/

	void setCheckMaxPoints(const unsigned long cMP) {checkMaxPoints=cMP;}
	/*sets every wich number of ticks the maxPoints condition should be
	checked; if 0 never check
	pre: the number of ticks the max point condition is checked*/

	bool 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*/

	void setUniversFolderName(char* uFol)
	/*set the univers folder name, wher the actual universes files are writen to
	pre: a pointer to the the univers folder*/
	{
	if (uFolder) {delete [] uFolder;}
	unsigned int i;
	for(i=0;uFol[i]!=0;i++);i++;//get length of string
	uFolder=new char[i];
	for(unsigned int a=0;a<i;a++){uFolder[a]=uFol[a];}//copy string
	if(outUniv>0){cratePath(uFolder);}
	}

	void setUniversFileBaseName(char* uFB)
	/*set the univers file base name, with wich the saved universes begin with
	pre: the univers base name*/
	{
	if (bUName) {delete [] bUName;}
	unsigned int i;
	for(i=0;uFB[i]!=0;i++);i++;//get length of string
	bUName=new char[i];
	for(unsigned int a=0;a<i;a++){bUName[a]=uFB[a];}//copy string
	}

	void setCutNearDimension(const double cND) {cutNearDimension=cND;}
	/*set the cutNearDimension value
	pre: the cutNearDimension value*/

	void setCutMaxClassRatio(const double cMCR) {cutMaxClassRatio=cMCR;}
	/*set the cutMaxClassRatio value
	pre: the cutMaxClassRatio value*/

	void setOutRealTime(bool rT);
	/*set if the real time statistic should be outputed
	pre: the outRealTime value*/

	bool setRTimeFileName(char* rTimeF);
	/*set real 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*/

	void printRealTimeStatisticHead() const;
	/*prints the head of the real time statistic to the real time statistic file*/

	void setOutCutStatistic(bool cut);
	/*set if the cut statistic should be outputed
	pre: the outCutStatistic value*/

	bool setCutFileName(char* cutF);
	/*set cut 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 cut time statistic file name
	post: true if the change was posibel(could open the new file), else false*/

	void printCutStatisticHead() const;
	/*prints the head of the cut statistic to the real time statistic file*/

	bool 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*/

	bool 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*/

	void 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*/

	void 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*/

	void 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*/

	void tick(unsigned long trans);
	/*Evalue a tick, minimal time change, of the univers. For that trans
	random choosen points of the univers a random transition is performed.
	Points that have no neigthbours are deleted.
	post: this univers changed*/

	bool 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 */

	bool 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*/

	bool 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*/

	void start(unsigned long trans=0);
	/*Starts the evaluation of the univers. Makes ticks till the end condition
	holds.
	post: the this univers changed*/


};

#endif
