1 /**
2 *   Copyright: © 2012-2014 Anton Gushcha
3 *   License: Subject to the terms of the MIT license, as written in the included LICENSE file.
4 *   Authors:  NCrashed <ncrashed@gmail.com>,
5 *             LeMarwin <lemarwin42@gmail.com>,
6 *             Nazgull09 <nazgull90@gmail.com>
7 */
8 module devol.compiler;
9 
10 import std.stdio;
11 import std.array;
12 
13 import devol.singleton;
14 import core.time;
15 import core.thread;
16 
17 public
18 {
19 	import devol.typemng;
20 	import devol.operatormng;
21 	import devol.population;
22 	import devol.evolutor;
23 	import devol.programtype;
24 }
25 
26 struct SequentCompilation
27 {
28 	static void initPop( PopAbstract pop, WorldAbstract world, ProgTypeAbstract progType )
29 	{
30 		foreach( ind; pop )
31 		{
32 			ind.invals = progType.initValues( world );
33 			ind.outvals = new Line[0];		
34 		}		
35 	}
36 	
37 	static void compilePop( PopAbstract pop, WorldAbstract world, ProgTypeAbstract progType, bool delegate() whenExit )
38 	{
39 		writeln("Entered compile method");
40 		foreach ( ind; pop )
41 		{
42 		    if(whenExit()) return;
43 			writeln("Taking indivi");
44 			foreach( line; ind.program )
45 			{
46 			    if(whenExit()) return;
47 				writeln("Compiling line");
48 				line.compile(ind, world);
49 			}
50 		}
51 	}
52 	
53 	static void calcPopFitness( PopAbstract pop, WorldAbstract world, ProgTypeAbstract progType )
54 	{
55 		uint i =0;
56 		ulong summ = 0;
57 		foreach( ind; pop )
58 		{
59 			writeln("Individ №",i++);
60 			ind.fitness = progType.getFitness(ind, world, 0);
61 			summ += ind.fitness;
62 			writeln("Fitness = ", ind.fitness ); 
63 		}
64 		auto asumm = cast(double)summ/pop.length;
65 		writeln("Average fitness = ", asumm);
66 	}
67 }
68 
69 struct GameCompilation(alias stopCond, alias drawStep, alias drawFinal, int roundsPerInd) 
70 {
71 	static void initPop( PopAbstract pop, WorldAbstract world, ProgTypeAbstract progType )
72 	{
73 		foreach( ind; pop )
74 		{
75 			ind.invals = progType.initValues( world );
76 			ind.outvals = new Line[0];		
77 		}		
78 	}
79 	
80 	static void compilePop( PopAbstract pop, WorldAbstract world, ProgTypeAbstract progType, bool delegate() whenExit )
81 	{
82 		writeln("Entered compile method");
83 
84 		foreach ( ind; pop )
85 		{
86 			auto fitts = new double[roundsPerInd];
87 			foreach(j; 0..roundsPerInd)
88 			{
89 			    if(whenExit()) return;
90 				world.initialize();
91 				int step = 0;
92 				ind.initialize();
93 				while( !stopCond( step, ind, world ) )
94 				{
95 					
96 					foreach( line; ind.program )
97 					{
98 					    if(whenExit()) return;
99 						writeln("Compiling line");
100 						line.compile(ind, world);
101 						drawStep(ind, world);
102 					}
103 					
104 					step++;
105 				}
106 				fitts[j] = progType.getFitness(ind, world, 0);
107 			}
108 			double summ = 0;
109 			foreach(val; fitts)
110 				summ+=val;
111 			ind.fitness = summ/fitts.length;
112 		}			
113 	}
114 	
115 	static void calcPopFitness( PopAbstract pop, WorldAbstract world, ProgTypeAbstract progType )
116 	{
117 		uint i =0;
118 		ulong summ = 0;
119 		foreach( ind; pop )
120 		{
121 			writeln("Individ №",i++);
122 			//ind.fitness = progType.getFitness(ind, world, 0);
123 			summ += ind.fitness;
124 			writeln("Fitness = ", ind.fitness ); 
125 		}
126 		
127 		drawFinal(pop, world);
128 		auto asumm = cast(double)summ/pop.length;
129 		writeln("Average fitness = ", asumm);
130 	}	
131 }
132 
133 class Compiler(
134 	CompStg = SequentCompilation, 
135 	EvolutorStg = Evolutor, 
136 	ProgType, 
137 	PopType,
138 	WorldType) 
139 	if( __traits(compiles, "PopAbstract pop = new PopType()") )
140 	: Singleton!Compiler
141 {
142 public: 
143 
144 	this()
145 	{
146 		//super(this);
147 		//if ( OperatorMng.getSingleton() is null )
148 		//	new OperatorMng();
149 			
150 		//if ( TypeMng.getSingleton() is null )
151 		//	new TypeMng();
152 			
153 		evolutor = new EvolutorStg();
154 		pops = new PopType[0];
155 		world = new WorldType();
156 		progtype = new ProgType();
157 	}
158 	
159 	void addPop(PopType pop)
160 	{
161 		if (pop is null || !checkPop(pop)) return;
162 		
163 		pops ~= pop;
164 	}
165 	
166 	PopType getPop(uint i)
167 	{
168 		return pops[i];
169 	}
170 	
171 	PopType addPop(int size, string name="")
172 	{
173 		auto pop = new PopType(size);
174 		
175 		if (name.empty)
176 			pop.genName();
177 		else
178 			pop.name = name;
179 		
180 	
181 		foreach(ref ind; pop)
182 		{
183 			evolutor.generateInitProgram(ind, progtype);
184 		}
185 		
186 		debug writeln("Created population ", pop.name, " size of ", size);
187 		
188 		pops ~= pop;
189 		return pop;
190 	}
191 	
192 	void envolveGeneration(bool delegate() whenExit)
193 	{
194 		writeln("Entering comp...");
195 		foreach( ref pop; pops )
196 		{
197 			writeln("Pop init");
198 			CompStg.initPop( pop, world, progtype );
199 			if(whenExit()) return;
200 			
201 			writeln("Pop compile");
202 			CompStg.compilePop( pop, world, progtype, whenExit);
203 			if(whenExit()) return;
204 			
205 			writeln("GENERATION №", pop.generation, " results:");
206 			CompStg.calcPopFitness( pop, world, progtype );
207 			scope(exit)
208 			{
209 			    pop.saveBests("saves/AntsBests/");
210 			    pop.saveAll("saves/AntsAll/");
211 		    }
212 			
213 			if(whenExit()) return;
214 			pop = evolutor.formNextPopulation( pop, progtype );
215 			pop.generation = pop.generation + 1;
216 			if(whenExit()) return;
217 		}
218 	}
219 	
220 protected:
221 	
222 	PopType[] pops;
223 	WorldAbstract world;
224 	ProgTypeAbstract progtype;
225 	EvolutorStg evolutor;
226 	
227 	bool checkPop(PopAbstract pop)
228 	{
229 		foreach(p; pops)
230 		{
231 			if (p == pop) return false;
232 		}
233 		return true;
234 	}
235 
236 }