source: liacs/ccs/op4/merit.pl@ 402

Last change on this file since 402 was 2, checked in by Rick van der Zwet, 15 years ago

Initial import of data of old repository ('data') worth keeping (e.g. tracking
means of URL access statistics)

  • Property svn:executable set to *
File size: 11.5 KB
Line 
1#!/usr/bin/env perl
2
3use strict;
4
5our $debug = 0;
6our %taken;
7
8our $length = 0;
9our $round_size = 100;
10our $maxstack = 150;
11our $working_mfactor = 0;
12our $best_mfactor = 0;
13our $best_vector;
14our $refill = 0;
15our $maxrounds = 20;
16our @winners;
17our $winnercompare = 10;
18
19our $total = 0;
20
21sub message {
22 our $debug;
23 my $level = shift;
24 my $message = shift;
25 if ( $level => $debug ) {
26 print "DEBUG [$level]: $message\n";
27 }
28}
29
30sub merit {
31 my $y = shift;
32 our $length;
33 my $e = 0;
34 my $f;
35 my $t;
36
37 foreach my $k (1 .. ($length - 1)) {
38 $t = 0;
39 for my $i (0 .. ($length - 1 - $k)) {
40 $t += $$y[$i] * $$y[$i+$k];
41 }
42 $e += $t ** 2;
43 }
44
45 $f = ($length ** 2) / ( 2 * $e);
46 printer('DEBUG merit', $f, $y) if $debug > 5;
47 return($f);
48}
49
50sub randarray {
51 our $debug;
52 my @output = ();
53 my ($i,$v);
54 message(1,"New randarray of length $length");
55 foreach $i ( 0 .. ($length - 1)) {
56 $v = int(rand() + 0.5);
57 $output[$i] = ( $v ) ? 1 : -1;
58 }
59 return(\@output);
60}
61
62sub flip {
63 my $rref = shift;
64 my $number = shift;
65 my $v = $$rref[$number];
66 $v = ($v == 1) ? -1 : 1;
67 $$rref[$number] = $v;
68}
69
70sub try_merit {
71 our @stack;
72 our %taken;
73 our $best_mfactor;
74 our $best_vector;
75 our $working_mfactor;
76
77 my $try_array = shift;
78 my $new_mfactor;
79 my $result = 0;
80 my $array2string = join('',@{$try_array});
81
82 if ( not exists ($taken{$array2string}) ) {
83 $new_mfactor = merit($try_array);
84 $taken{$array2string} = $new_mfactor;
85
86 if ($new_mfactor > $best_mfactor) {
87 $best_mfactor = $new_mfactor;
88 $best_vector = $try_array;
89 $result = 1;
90 unshift(@stack,$try_array);
91 }
92 }
93 if ( $debug == 5 ) {
94 print "==== " . scalar(@stack) . "====\n";
95 print join("\n",@stack) . "\n";
96 }
97 return($result);
98}
99
100sub combine {
101 our $length;
102 our $debug;
103 message(1,"Working on combine");
104
105 my $result = 0;
106 my $loop;
107 my $input = shift;
108 my $input2 = shift;
109 my @result_l;
110 my @result_r;
111
112
113 my $middle = int($length / 2);
114 @result_l = (@{$input}[0 .. $middle],
115 @{$input2}[ $middle + 1 .. ($length-1) ]);
116 @result_r = (@{$input2}[0 .. $middle],
117 @{$input}[ $middle + 1 .. ($length-1) ]);
118
119 if ($debug > 3) {
120 print "Orig l: ";
121 print @{$input};
122 print "\n";
123 print "Orig 2: ";
124 print @{$input2};
125 print "\n";
126 print "Combine l: ";
127 print @result_l;
128 print "\n";
129 print "Combine r: ";
130 print @result_r;
131 print "\n";
132 }
133 message(1,"DEBUG: Done on combine");
134 return(\@result_l,\@result_r);
135}
136
137sub crossover {
138 my $input = shift;
139 my $rev_array = shift;
140 my $result = 0;
141 my ($try_array_l,$try_array_r) = combine($input,$rev_array);
142
143 if ( try_merit($try_array_l) ) {
144 $result = 1;
145 }
146
147 if ( try_merit($try_array_r) ) {
148 $result = 1;
149 }
150 return($result);
151}
152
153
154sub mutations {
155 our $length;
156
157 my @try_array;
158 my $result = 0;
159 my @test_array = @_;
160
161 message(1,"Working on mutations");
162
163 foreach my $i ( 0 .. ($length - 1) ) {
164 my @try_array = ();
165 @try_array = @test_array;
166 flip(\@try_array, $i);
167
168 if ( try_merit(\@try_array) ) {
169 $result = 1;
170 }
171 }
172 message(1,"Done on mutations");
173 return($result) ;
174}
175
176
177sub crossovers {
178 our $length;
179
180 my @try_array;
181 my $result = 0;
182 my @test_array = @_;
183
184 my $i;
185 my $j;
186
187 message(1,"Working on crossovers");
188 foreach $i ( 0 .. ($length - 1) ) {
189 my @try_array = ();
190 @try_array = @test_array;
191 foreach $j ( $i .. ($length - 1) ) {
192 flip(\@try_array, $j);
193 }
194
195 if ( try_merit(\@try_array) ) {
196 $result = 1;
197 }
198 }
199 message(1,"Done on crossovers");
200 return($result);
201}
202
203
204
205
206sub randmutate {
207 our $length;
208 my $switchtimes = shift;
209 my $switchnumbers = shift;
210 my @test_array = @_;
211 my $result = 0;
212 my @try_array;
213 my $i;
214 my $j;
215 my $n;
216 my @flipped;
217
218 message(1,"Working on randmutate");
219
220 foreach $i ( 0 .. $switchtimes ) {
221 my @try_array = ();
222 @try_array = @test_array;
223 @flipped = ();
224 foreach $j ( 0 .. $switchnumbers ) {
225 $n = int(rand($length - 1));
226 if ( not exists $flipped[$n] ) {
227 flip(\@try_array,$n);
228 $flipped[$n] = 1;
229 }
230 }
231
232 if ( try_merit(\@try_array) ) {
233 $result = 1;
234 }
235 }
236 return($result);
237}
238
239sub printer {
240 my $message = shift;
241 my $mfactor = shift;
242 my $input = shift;
243 return("Message : $message \n" .
244 "Vector : " . join(',',array2string($input) . "\n" .
245 "mfactor : $mfactor \n" .
246 "--\n");
247}
248
249
250
251our @stack = ();
252our $best_mfactor = 0;
253our $best_vector;
254
255sub array2string {
256 my $input = shift;
257 my @result = ();
258 my $n = 1;
259 foreach my $i (1 .. $#$input) {
260 if ($$input[$i] != $$input[$i - 1]) {
261 push(@result,$n);
262 $n = 1;
263 }
264 else {
265 $n++;
266 }
267 }
268 push(@result,$n);
269 return(@result);
270}
271
272sub string2array {
273 my @output = ();
274 my $input = shift;
275 $input = split(//,$input);
276 my $c = 0;
277 my $v = 1;
278
279 my ($n,$i);
280
281 for $n ( 0 .. length($input) - 1) {
282 for $i ( 1 .. @{$input}[$n] ) {
283 $output[$c] = $v;
284 $c++;
285 }
286 $v = ( $v == 1) ? -1 : 1;
287 }
288
289 return(@output);
290}
291
292
293#
294# Vul de stack met een random arrays
295sub init {
296 our $length = shift;
297 our @stack;
298 our $best_mfactor;
299
300 my ($n,$y);
301
302 @stack = ();
303 $best_mfactor = 0;
304
305 foreach $n ( 1 .. 75 ) {
306 $y = randarray();
307 push(@stack,$y);
308 }
309
310}
311
312sub reinit {
313 our $refill;
314 our $winnercompare;
315 our $length;
316 our @winners;
317 our %taken;
318 our @stack;
319 our $best_vector;
320 our $best_mfactor;
321
322 my $maxwinners = 5;
323
324 my ($result_l,$result_r);
325 my ($i,$j);
326 my ($n,$y);
327 my ($r);
328
329 %taken = ();
330 @stack = ();
331
332 $refill++;
333 #push best array on good place
334 $i = merit($best_vector);
335 print printer("Round best vector",$i,$best_vector);
336 my $ws = $#winners - 1;
337 my $done = 0;
338 foreach $n ( 0 .. $ws ) {
339 $j = merit($winners[$n]);
340 if ( $i > $j ) {
341 foreach $r ($ws .. ($n + 1)) {
342 $winners[$r] = $winners[$r-1];
343 }
344 $winners[$n] = $best_vector;
345 $done = 1;
346 last;
347 }
348 }
349 if ( ($done == 0) && ($ws < $maxwinners) ) {
350 push(@winners,$best_vector);
351 }
352 print printer("Current best vector",merit($winners[0]),$winners[0]);
353
354 if ( $refill == $winnercompare ) {
355 push(@stack,@winners);
356 $refill = 0;
357 $r = scalar(@stack) - 1;
358 foreach $i ( 0 .. ($r - 1)) {
359 foreach $j ( ($i) .. $r ) {
360 ($result_l,$result_r) = combine($stack[$i],$stack[$j]);
361 push(@stack,$result_l);
362 push(@stack,$result_r);
363 }
364 }
365 $best_mfactor = merit($winners[0]);
366 }
367 else {
368 foreach $n ( 1 .. 75 ) {
369 $y = randarray();
370 push(@stack,$y);
371 }
372 $best_mfactor = 0;
373 }
374}
375
376sub main {
377 our $working_mfactor;
378 our $round_number;
379 our $maxstack;
380 our $maxrounds;
381
382 my $rounds = 0;
383 my $number = 0;
384 my $improvement = 0;
385 my $result;
386 my $stacksize;
387 my ($i,$j,$r,$y);
388
389 while ( 'true' )
390 {
391 $total++;
392
393 $number = ($improvement) ? 0 : $number + 1;
394 print "Number: $number\n" if $debug;
395
396 $working_mfactor = merit(@stack[$number]);
397 if ( $debug > 1 ) {
398 message(1,
399 printer("Working vector",$working_mfactor,@stack[$number]));
400 }
401
402 message(1,"\n" . $number . " of " . $stacksize );
403 $improvement = 0;
404
405 $result = try_merit(@stack[$number]);
406 if ($result > 0 ) {
407 message(1,
408 printer("better array", $best_mfactor,@stack[$number]));
409 $improvement = 1;
410 }
411
412 my @rev = reverse(@{$stack[$number]});
413 $result = crossover($stack[$number],\@rev);
414 if ($result > 0 ) {
415 message(1,
416 printer("better combine", $best_mfactor,@stack[$number]));
417 $improvement = 1;
418 }
419
420 $result = mutations(@{$stack[$number]});
421 if ($result > 0 ) {
422 message(1,
423 printer("better mutation", $best_mfactor,@stack[$number]));
424 $improvement = 1;
425 }
426
427# Experimental 'crossover make'
428 $result = crossovers(@{$stack[$number]});
429 if ($result > 0 ) {
430 message(1,
431 printer("better crossovers", $best_mfactor,@stack[$number]));
432 $improvement = 1;
433 }
434
435# Not very usefull, not value added
436# $result = randmutate($length, $length / 3,@{$stack[0]});
437# if ($result > 0 ) {
438# printer("better randmutate", $best_mfactor,@stack[0]);
439# next;
440# }
441
442 if ( $improvement ) {
443 print "Stack size: " . scalar(@stack) . "\n";
444 print "best max mfactor " . $best_mfactor . "\n";
445 print "total done " . $total . "\n";
446 print "round " . $rounds;
447 print "\n---\n";
448 }
449
450 if ( ($total % $round_size) == 0 ) {
451 print "===============================\n";
452 print "=== Completed Round $rounds ===\n";
453 print "===============================\n";
454 $rounds++;
455 reinit();
456 if ( $rounds == $maxrounds ) {
457 last;
458 }
459 $r = <> if $debug > 3;
460 $improvement = 1;
461 print "===============================\n";
462 print "=== New Round $rounds ===\n";
463 print "===============================\n";
464 next;
465 }
466
467 $stacksize = scalar(@stack);
468 if ( $stacksize > $maxstack ) {
469 while ( scalar(@stack) >= 5 ) {
470 pop(@stack);
471 }
472 }
473 message(1,"$number of " . scalar(@stack) . "\n");;
474 $stacksize = scalar(@stack);
475 if ( (($number +2) > $stacksize) ) {
476 message(1,"Start EVOLVING");
477 $number = 0;
478 while ( scalar(@stack) > 5 ) {
479 pop(@stack);
480 }
481
482 foreach ( 5 .. 9 ) {
483 $y = randarray();
484 push(@stack,$y);
485 }
486
487 foreach $i ( 0 .. 4) {
488 foreach $j ( 5 .. 9 ) {
489 my ($result_l,$result_r) = combine($stack[$i],$stack[$j]);
490 push(@stack,$result_l);
491 push(@stack,$result_r);
492 }
493 }
494 message(1,"Done EVOLVING");
495 }
496
497 #pause during debugging
498 $r = <> if $debug > 4;
499 }
500}
501
502$debug = 0;
503$round_size = 100;
504$maxstack = 150;
505$maxrounds = 20;
506$winnercompare = 5;
507init($ARGV[0]);
508main();
509
510print "\n\n\n";
511
512print "===============================\n";
513print "=== Results ===\n";
514print "===============================\n";
515
516$best_vector = $winners[0];
517$best_mfactor = merit($best_vector);
518print printer("Final", $best_mfactor,$best_vector);
519print "Total parents : $total\n";
520print "Total rounds : $maxrounds\n";
521print "Round parents : $round_size\n";
522print "Winner compare: $winnercompare\n";
523print "Max stack : $winnercompare\n";
524print "Vector size : $length\n";
Note: See TracBrowser for help on using the repository browser.