OpenCores
URL https://opencores.org/ocsvn/firgen/firgen/trunk

Subversion Repositories firgen

[/] [firgen/] [trunk/] [firgen/] [RedFIR/] [firgen/] [geneticoptimizer.cpp] - Rev 8

Compare with Previous | Blame | View Log

/*
 * firgen is the name of the Programm which is optimized for creating FIR filter with less resources
 * copyright (C) 2007 
 *
 * 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 3 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, 
 * /see <http://www.gnu.org/licenses/>.
*/
 
/***************************************************************************
                          geneticoptimizer.cpp  -  description
                             -------------------
    begin                : Mon Oct 15 2001
    copyright            : (C) 2001 by otto stephan
    email                : ottosn
 ***************************************************************************/
 
#include "geneticoptimizer.h"
#include "exception.h"
#include <limits.h>
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include "benchmark.h"
 
 
geneticOptimizer::geneticOptimizer( nodeGraph *n, structureList *sl){
 
  ng = n;
	bestDNA = sl;
	genLines = bestDNA->getLineCnt();
	// if only one line exist, no optimizing process is needed
 
	lastBest = 0;
	// set default values:
	idleGenerations = 100;
	runTime = 600.00;        // seconds
	mutationRate = -0.02;
	populationSize = 50;
	parentPerIndividuum = 2;
	plotFile = 0;
	srand( (unsigned)time( NULL));
	setEffort(sl->get_effort(),sl->get_generations());
 
 
}
geneticOptimizer::~geneticOptimizer(){
	delete cost;
	delete ranking;
	delete parentDNA;
	for ( int p=0; p<populationSize; p++)
  	deleteDNA( populationDNA[p]);
  delete populationDNA;
	for ( int p=0; p<parentPerIndividuum; p++)
  delete parentIter[p];
  delete parentIter;
}
// set time to optimize in minutes
void geneticOptimizer::setEffort( double min, int iGenerations /*= 100*/) {
	runTime = min;
	idleGenerations = iGenerations;
}
 
int geneticOptimizer::optimize( char *benchmarkFile) {
 
  int i_success=0;
  benchmark b;
	plotFile = fopen( benchmarkFile, "a");
 	b.now();
  long startTime = b.get_process_time();
	long lastTime=1;
 
 
	if (plotFile) {
	  fprintf( plotFile, "\n\n... genOpt info: genetic optimizer started\n");
		fprintf( plotFile, "... genOpt value: population size   : %d individuum per generation\n", populationSize);
		fprintf( plotFile, "... genOpt value: mutation rate     : %2.4f\n", mutationRate*100);
		fprintf( plotFile, "... genOpt value: count of parents  : %d per individuum\n", parentPerIndividuum);
		fprintf( plotFile, "... genOpt value: foot count        : %d nodes\n", bestDNA->getCoefCnt());
		fprintf( plotFile, "... genOpt value: coefficient width : %d bit\n", bestDNA->getCoefWidth());
		fprintf( plotFile, "... genOpt value: maximal runtime   : %f min\n", runTime);
		fprintf( plotFile, "... genOpt value: idle break        : %d generations\n", idleGenerations);
    fflush(plotFile);
 
		b.now();
 
    fprintf(plotFile,"\n\n... genOpt progress: initialize population (+%ld.%02ld.%03ld min)\n",(b.get_process_time()-startTime) /60000,
  			(b.get_process_time()-startTime) /1000, (b.get_process_time()-startTime)% 1000);
    fflush(plotFile);
    initializePopulation();
 
 
  	g = 0;
	  b.now();
 		fprintf(plotFile,"\n... genOpt progress: search best DNA (+%ld.%02ld.%03ld min)",(b.get_process_time()-startTime) /60000,
  			(b.get_process_time()-startTime) /1000, (b.get_process_time()-startTime)% 1000);
    fflush(plotFile);
  	do{
  	  if ((g%50)==0)
   		{
   		  fprintf(plotFile,"\n... genOpt progress: ");
   		  fflush(plotFile);
   		};
  	  b.now();
  	  g++;
  		fprintf(plotFile,".");
  		analyzeCost();
  		if (saveBestDNA()) {
  		  fprintf(plotFile,"\n... genOpt progress: new best DNA found! cost score: %d ", bestDNA->cost);
  			fprintf(plotFile,"\n... genOpt progress: generation: %d time: +%ld.%02ld.%03ld min\n",g, (b.get_process_time()-startTime) /60000,
  			(b.get_process_time()-startTime) /1000, (b.get_process_time()-startTime)% 1000);
  			lastBest = g;
  			lastTime=(b.get_process_time()-startTime) /60000;
  	    fprintf(plotFile,"... genOpt progress: ");
   		  fflush(plotFile);
  		}
  		mutate();
  		combine();		
 
  	} while (( ((b.get_process_time()-startTime)/60000) < runTime)
  	      &&( ( g-lastBest)<idleGenerations));
 
  	fprintf(plotFile,"\n... genOpt progress: last generation: %d time: +%ld.%02ld.%03ld min\n",g, (b.get_process_time()-startTime) /60000,
  			(b.get_process_time()-startTime) /1000, (b.get_process_time()-startTime)% 1000);
 
  	i_actual_best_cost=bestDNA->cost;
    fprintf( plotFile, "... genOpt progress: best cost: %d ,",i_actual_best_cost );
  	if ( ((b.get_process_time()- startTime)/ 60000) >= runTime)
  		fprintf(plotFile,"time limit reached \n");
 
  	if ( ( g - lastBest) >= idleGenerations)
  	  fprintf( plotFile, "idle count reached\n");
 
   fprintf( plotFile, "... genOpt info: genetic optimizer done\n");
   fclose( plotFile);
 		i_success=1;
 
	};
 
 
	return i_success;
}
 
void geneticOptimizer::combine() {
	typedef dna* pdna;
	// step 1:
	// get maximal cost
  uint maxCost = 0;                // needed for creating rate array
 
  for ( int p=0; p<populationSize; p++)
  	if ( cost[p] > maxCost)
  		maxCost = cost[p];
  maxCost++;												// avoid ranking error !!
	// step 2:
  // create ranking array to select good parents with an higher probability
  int sumRate = 0;					// needed for random parent-choose
  int diff = 0;
  for ( int p=0; p<populationSize; p++) {
  	diff = maxCost - cost[p];
  	ranking[p] =  diff + sumRate;
  	sumRate += diff;
  }
  // step 3:
  // generate new population by
  // choose parents per random
  dna **newGenerationDNA = new pdna [populationSize];
  unsigned int choice = 0;
	for ( int i=0; i<populationSize; i++) {
		// select parents per ranking
		for ( int parent=0; parent<parentPerIndividuum; parent++) {
      choice = rand() % sumRate;
      for ( int dummy=0; dummy < populationSize; dummy++) {
        if ( ranking[dummy] > choice) {
          parentDNA[parent] = populationDNA[dummy];
          break;
        }
      }
  	}
  	// create new dna by choosen parents
  	newGenerationDNA[i] = mergeDNA();
  }
  // step 4:
  // delete old dna
  for ( int p=0; p<populationSize; p++)
  	deleteDNA( populationDNA[p]);
  delete populationDNA;
	populationDNA = newGenerationDNA;
}
 
// merge all parents to new dna
// merge with delete
// version 2.01
geneticOptimizer::dna *geneticOptimizer::mergeDNA() {
	dna *d = createDNA();
	// step 1:
	// insert all coeffs from parent to child
	unsigned int dummy;
	map< unsigned int, gen>::iterator iter;
	iter = parentDNA[0]->genLine[ genLines-1]->begin();
	while( iter != parentDNA[0]->genLine[ genLines-1]->end()) {
		dummy = rand() % parentPerIndividuum;
		(*d->genLine[ genLines-1])[iter->first].mC = new moduleComponent;
		(*d->genLine[ genLines-1])[iter->first].mC->alpha = (*parentDNA[dummy]->genLine[ genLines-1])[iter->first].mC->alpha;
		(*d->genLine[ genLines-1])[iter->first].mC->beta = (*parentDNA[dummy]->genLine[ genLines-1])[iter->first].mC->beta;
		(*d->genLine[ genLines-1])[iter->first].mC->gamma = (*parentDNA[dummy]->genLine[ genLines-1])[iter->first].mC->gamma;
		(*d->genLine[ genLines-1])[iter->first].mC->klasse = (*parentDNA[dummy]->genLine[ genLines-1])[iter->first].mC->klasse;
		(*d->genLine[ genLines-1])[iter->first].active = true;
		if ( genLines > 1) {
			(*d->genLine[ genLines-2])[ (*parentDNA[dummy]->genLine[ genLines-1])[iter->first].mC->alpha].active = true;
			(*d->genLine[ genLines-2])[ (*parentDNA[dummy]->genLine[ genLines-1])[iter->first].mC->beta].active = true;
		}
		iter++;
	}
	if( genLines > 1) {
		unsigned int parentCnt;
		unsigned int choosenParent;
		for ( int l=(genLines-2); l>=0; l--) {
			iter = d->genLine[l]->begin();
			while( iter != d->genLine[l]->end()) {
				parentCnt = 0;
				for ( int p=0; p<parentPerIndividuum; p++) {
					*parentIter[p] = (*parentDNA[p]->genLine[l]).find( iter->first);
					if ( *parentIter[p] != parentDNA[p]->genLine[l]->end()) parentCnt++;
				}
				dummy = rand() % parentCnt;
				choosenParent = 0;
				// get parent
				for ( int p=0; p<parentPerIndividuum; p++) {
					if ( *parentIter[p] != parentDNA[p]->genLine[l]->end()) {
						if ( choosenParent == dummy) {choosenParent = p;break;}
						choosenParent++;
					}
				}
				(*d->genLine[ l])[iter->first].mC = new moduleComponent;
				(*d->genLine[ l])[iter->first].mC->alpha = (*parentDNA[choosenParent]->genLine[ l])[iter->first].mC->alpha;
				(*d->genLine[ l])[iter->first].mC->beta = (*parentDNA[choosenParent]->genLine[ l])[iter->first].mC->beta;
				(*d->genLine[ l])[iter->first].mC->gamma = (*parentDNA[choosenParent]->genLine[ l])[iter->first].mC->gamma;
				(*d->genLine[ l])[iter->first].mC->klasse = (*parentDNA[choosenParent]->genLine[ l])[iter->first].mC->klasse;
				if ( l > 0) {
					(*d->genLine[ l-1])[ (*parentDNA[choosenParent]->genLine[ l])[iter->first].mC->alpha].active = true;
					(*d->genLine[ l-1])[ (*parentDNA[choosenParent]->genLine[ l])[iter->first].mC->beta].active = true;
				}
				iter++;
			}
		}
	}
	// merge mutationRate
	float sumMutationRate = 0;
	for ( int p=0; p<parentPerIndividuum; p++) {
		sumMutationRate += parentDNA[p]->mutationRate;
	}
	d->mutationRate = sumMutationRate / parentPerIndividuum;
	return d;
}
 
 
void geneticOptimizer::mutate() {
	map< unsigned int, gen>::iterator iter;
	float mRate = mutationRate;
	for ( int p=0; p<populationSize; p++) {
		// if variable mutation
		if ( mutationRate < 0 || mutationRate > 1)
			mRate = populationDNA[p]->mutationRate;
 
		for ( int l=genLines-1; l>=0; l--) {
			iter = populationDNA[p]->genLine[l]->begin();
			while ( iter != populationDNA[p]->genLine[l]->end()) {
				if ( ((float)rand() / (float)RAND_MAX) < mRate )	{
					delete iter->second.mC;
					iter->second.mC = ng->getModul( l+1, iter->first);
					if ( !iter->first || !iter->second.mC->alpha || !iter->second.mC->beta) {
						printf("aerger bei p: %d\n", p);
					}
					if (l) {
						insertGen( l-1, iter->second.mC->alpha, populationDNA[p]);
						insertGen( l-1, iter->second.mC->beta , populationDNA[p]);
					}
				}
				iter++;
			}
		}
		// mutate mutationrate
		if ( mutationRate < 0 || mutationRate > 1) {
			if ( ((float)rand() / (float)RAND_MAX) < mRate) {
				populationDNA[p]->mutationRate += (float)(rand() - RAND_MAX/2) / (float)(RAND_MAX) / 10;
				if ( populationDNA[p]->mutationRate < 0)
					populationDNA[p]->mutationRate = -populationDNA[p]->mutationRate;
			}
		}
	}
}
 
void geneticOptimizer::initializePopulation() {
	typedef dna* pdna;
  int cnt=0;
	cost = new unsigned int[populationSize];
	ranking = new unsigned int[populationSize];
	parentDNA = new pdna [parentPerIndividuum];
	parentIter = new map< unsigned int, gen>::iterator*;
	for ( int p=0; p<parentPerIndividuum; p++)
		parentIter[p] = new map< unsigned int, gen>::iterator;
 
 
	populationDNA = new pdna [populationSize];
	for ( int i=0; i<populationSize; i++) {
		// create individuum with genLines
		populationDNA[i] = createDNA();
		// fill nodeLines
		// step 1: insert coeffs
		for ( int c=0; c<bestDNA->getCoefCnt(); c++) {
		// live out
			if ( bestDNA->getCoef( c) == 0) continue;
		  if ( populationDNA[i]->genLine[ genLines-1]->find( bestDNA->getCoef( c)) ==
  			populationDNA[i]->genLine[genLines-1]->end())
  				insertGen( genLines-1, bestDNA->getCoef(c), populationDNA[i]);	
		}
		if (plotFile)
		{
 
		  if ((cnt%50)==0) fprintf(plotFile,"\n... genOpt progress: ");
 
		  fprintf(plotFile,".");
		  fflush(plotFile);
		  cnt++;
		};
 
	}
	bestDNA->cost = UINT_MAX;
 
};
 
void geneticOptimizer::analyzeCost() {
	map< unsigned int, gen>::iterator iter;
	for ( int p=0; p<populationSize; p++) {
		cost[p] = 0;
		for ( int l=genLines-1; l>=0; l--) {
			iter = populationDNA[p]->genLine[l]->begin();
			while ( iter != populationDNA[p]->genLine[l]->end()) {
				cost[p] += ng->getCost( iter->second.mC);
				iter++;
			}
		}
	}
}
 
 
bool geneticOptimizer::saveBestDNA() {
	int bestPos = 0;
	float averageCost = 0;
	float averageMr = 0;	
	map< unsigned int, gen>::iterator dummyIter;
  // search best dna in population
  for (int p=0;p<populationSize;p++) {
  	averageCost += cost[p];
  	averageMr += populationDNA[p]->mutationRate;
    if ( cost[p] < cost[bestPos])
      bestPos = p;
  }
  averageCost /= populationSize;
  averageMr /= populationSize;
  if ( bestDNA->cost > cost[bestPos]) {
  	bestDNA->clear();
  	bestDNA->cost = cost[bestPos];
  	map< unsigned int, gen>::iterator iter;
		for ( int l=genLines-1; l>=0; l--) {
			iter = populationDNA[bestPos]->genLine[l]->begin();
			while( iter != populationDNA[bestPos]->genLine[l]->end()) {
			  if (l) {
					dummyIter = (*populationDNA[bestPos]->genLine[l-1]).find( iter->first);
					// is coef contain in previous line
					if ( dummyIter != populationDNA[bestPos]->genLine[l-1]->end()) {
						iter->second.mC->alpha = iter->first;
						iter->second.mC->beta = iter->first;
						iter->second.mC->gamma = 0;
						iter->second.mC->klasse = DELAY;
						//iter++;
						//continue;
					}
				}
				else {
					if (iter->first == 1) {
						iter->second.mC->alpha = 1;
						iter->second.mC->beta = 1;
						iter->second.mC->gamma = 0;
						iter->second.mC->klasse = DELAY;
						//iter++;
						//continue;
					}
				}
				bestDNA->setModule( l, iter->first, iter->second.mC);
				iter++;
			}
		}
	  	return true;
  }
	return false;
}
 
void geneticOptimizer::insertGen( unsigned int line, unsigned int node, dna *DNA) {
	map< unsigned int, gen>::iterator dIter;
	if ( line < 0 || line >= (unsigned int)genLines) return;
	dIter = DNA->genLine[line]->find( node);
	if ( dIter != DNA->genLine[line]->end()) return;
	(*DNA->genLine[line])[node].mC = ng->getModul( line+1, node);
	(*DNA->genLine[line])[node].active = true;
	if ( line) {
		insertGen( line - 1, (*DNA->genLine[line])[node].mC->alpha, DNA);
		insertGen( line - 1, (*DNA->genLine[line])[node].mC->beta, DNA);
	}
}
 
geneticOptimizer::dna *geneticOptimizer::createDNA() {
	dna *rt = new dna;
	rt->genLine = new map< unsigned int, gen>*[genLines];
	for ( int l=0; l<genLines; l++)
			rt->genLine[l] = new map< unsigned int, gen>;
	if ( mutationRate < 0 || mutationRate > 1) {
		rt->mutationRate = -mutationRate;
	}
	else rt->mutationRate = mutationRate;
	return rt;
}
 
void geneticOptimizer::deleteDNA( dna *DNA) {
	map< unsigned int, gen>::iterator iter;
	for ( int l=genLines-1; l>=0; l--) {
			iter = DNA->genLine[l]->begin();
			while ( iter != DNA->genLine[l]->end()) {
				delete iter->second.mC;
				iter++;
			}
			delete DNA->genLine[l];
		}
	delete DNA->genLine;
	delete DNA;
}
 
void geneticOptimizer::printDNA( dna *DNA, int mode ) {
	map< unsigned int, gen>::iterator iter;
	 cout << "--" << endl;
	for ( int l=genLines-1; l>=0; l--) {
		printf("line %d: \n", l + 1);
		iter = DNA->genLine[l]->begin();
		while( iter != DNA->genLine[l]->end()) {
			cout << iter->first;
			//if ( mode & 1 && iter->second.active) cout << "! " <<	iter->second.mC->beta << "]";
			if ( mode & 8)	cout << "[" << iter->second.mC->alpha << " " << iter->second.mC->beta << "]";
			if ( mode & 4) {
				switch ( iter->second.mC->klasse) {
					case 1:  cout<< "=[R] "; break;
					case 2:  cout<< "=" << iter->second.mC->alpha <<"*(1+2^"<<iter->second.mC->gamma<<") "; break;
					case 3:  cout<<"="<<iter->second.mC->alpha<<"*(2^"<<iter->second.mC->gamma<<"-1) "; break;
					case 4:  cout<<"="<<iter->second.mC->alpha<<"+"<<iter->second.mC->beta<<"*2^"<<iter->second.mC->gamma<<" "; break;
					case 5:  cout<<"="<<iter->second.mC->alpha<<"*2^"<<iter->second.mC->gamma<<"-"<<iter->second.mC->beta<<" "; break;
					case 6:  cout<<"="<<iter->second.mC->alpha<<"-"<<iter->second.mC->beta<<"*2^"<<iter->second.mC->gamma<<" "; break;
				}
			}
			if ( mode & 16) cout <<	"(" << iter->second.mC->gamma << ") ";
			iter++;
		}
		cout << endl;
	}
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.