Return to Appendix B.

ESMAIN.CPP
// Matt Streeter
// 2/27/00
// ESMAIN.CPP
// Implementation of class TESMainWindow; window class for main program window.
// Copyright Matt Streeter, 2000.  All rights reserved

#include <owl\edit.h>
#include <owl\choosefo.h>
#include <fstream.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

#include "esmain.h"
#include "eswin.rh"
#include "Network.h"
#include "Cross.hpp"
#include "Mutate.hpp"
#include "nvis.h"
#include "genwin.h"
#include "ids.h"
#include "esbutton.h"
#include "esstatic.h"

// TESGraphWindow will be redrawn every 'PLOT_INTERVAL' generations.
#define PLOT_INTERVAL 1

// Range of mutation slider.
#define MAX_MUTATION_SLIDER_POS 1000

// Set to 0 to disable saving of networks in every generation.
#define SAVE_GENERATIONS 1

static Network TestNet;

double Eval(double *weights, int count)
{
	return (TestNet.NetEval(weights,count));
}

TNetworkConfigDialog::TNetworkConfigDialog(TWindow *pParent,
	TNetworkConfigStruct *pTransfer): TDialog(pParent,EDIT_NETWORK_ARCHITECTURE,
	::Module)
{
	new TRadioButton(this,IDC_RADIOBUTTON3,0);
	new TRadioButton(this,IDC_RADIOBUTTON4,0);
	new TEdit(this,IDC_EDIT3,sizeof(pTransfer->pLayers));
	new TEdit(this,IDC_EDIT4,sizeof(pTransfer->pNodesPerLayer));
	new TEdit(this,IDC_EDIT5,sizeof(pTransfer->pTotalNodes));
	new TCheckBox(this,IDC_CHECKBOX2);
	SetTransferBuffer((void*)pTransfer);
}

TESConfigDialog::TESConfigDialog(TWindow *pParent,TESConfigStruct *pTransfer):
	TDialog(pParent,ES_CONFIGURATION,::Module)
{
	new TEdit(this,IDC_EDIT1,sizeof(pTransfer->pMu));
	new TEdit(this,IDC_EDIT2,sizeof(pTransfer->pLambda));
	new TRadioButton(this,IDC_RADIOBUTTON1,0);
	new TRadioButton(this,IDC_RADIOBUTTON2,0);
	SetTransferBuffer((void *)pTransfer);
}

DEFINE_RESPONSE_TABLE1(TESMainWindow, TESWindow)
	EV_COMMAND(ID_ES_BUTTON,HandleESButtonMsg),
   EV_COMMAND(CM_MAIN_ESOPTIONS,HandleESButtonMsg),
	EV_COMMAND(ID_PROBLEM_BUTTON,HandleProblemButtonMsg),
	EV_COMMAND(CM_MAIN_LOADPROBLEM,HandleProblemButtonMsg),
	EV_COMMAND(ID_RUN_BUTTON,HandleRunButtonMsg),
	EV_COMMAND(CM_MAIN_RUN,HandleRunButtonMsg),
	EV_COMMAND(ID_PAUSE_BUTTON,HandlePauseButtonMsg),
	EV_COMMAND(CM_MAIN_PAUSE,HandlePauseButtonMsg),
	EV_COMMAND(ID_PLOT_BUTTON,HandlePlotButtonMsg),
	EV_COMMAND(CM_MAIN_FITNESSPLOT,HandlePlotButtonMsg),
	EV_COMMAND(ID_RESET_BUTTON,HandleResetButtonMsg),
	EV_COMMAND(CM_MAIN_RESET,HandleResetButtonMsg),
	EV_COMMAND(ID_NETWORK_BUTTON,HandleNetworkButtonMsg),
	EV_COMMAND(CM_MAIN_NETWORKOPTIONS,HandleNetworkButtonMsg),
	EV_COMMAND(ID_BEST_BUTTON,HandleBestButtonMsg),
	EV_COMMAND(CM_MAIN_CURRENTBESTNETWORK,HandleBestButtonMsg),
	EV_COMMAND(ID_GENERATION_BUTTON,HandleGenerationButtonMsg),
	EV_COMMAND(CM_MAIN_GENERATIONS,HandleGenerationButtonMsg),
	EV_CHILD_NOTIFY_ALL_CODES(ID_MUTATION_SLIDER,HandleMutationSlider),
END_RESPONSE_TABLE;

TESMainWindow::TESMainWindow(char *pTitle): TESWindow(0,pTitle)
{
	Attr.X=100;
	Attr.Y=100;
	Attr.W=775;
	Attr.H=600;

  	mGenerationState=NO_STATE;
	mpPlotWindow = 0;
	mbUseBackpropagation=0;
	mpScoreList=0;
	mpGenerationList=0;
	mbPlus=1;

	LoadConfigFile();
	CreateChildren();

	TestNet.InitNetwork(mES);
	mES.param.InitParameter(mPInfo.GetNParams());
	mES.param.InitPInfo(mPInfo);
	mES.param.SetEval(Eval);

	mpLBSigma=new double[mES.nsigma];
	mpUBSigma=new double[mES.nsigma];

	Reset();

	AssignMenu(MAIN_MENU);
}

#define NEW_LAYOUT (USE_PRETTY_BUTTONS && USE_ES_STATICS)

#define ES_BUTTON_X 25
#define ES_BUTTON_Y 25
#define PROBLEM_BUTTON_X ES_BUTTON_X //275
#define PROBLEM_BUTTON_Y iProblemY // 50
#define NETWORK_BUTTON_X ES_BUTTON_X // 50
#define NETWORK_BUTTON_Y iNetworkY // 100
#define RUN_BUTTON_X iRunX
#define RUN_BUTTON_Y ES_BUTTON_Y
#define PAUSE_BUTTON_X iPauseX
#define PAUSE_BUTTON_Y ES_BUTTON_Y
#define RESET_BUTTON_X iRunX
#define RESET_BUTTON_Y NETWORK_BUTTON_Y
#define PLOT_BUTTON_X iPauseX
#define PLOT_BUTTON_Y NETWORK_BUTTON_Y
#define GENERATION_BUTTON_X iGenerationX
#define GENERATION_BUTTON_Y ES_BUTTON_Y
#define BEST_BUTTON_X iGenerationX
#define BEST_BUTTON_Y NETWORK_BUTTON_Y

#define RUN_BUTTON_WIDTH 60
#define GENERATION_HPADDING 50

#define GENERATION_NUM_STATIC_WIDTH 50
#define ES_STATIC_WIDTH 75
#define NETWORK_STATIC_WIDTH 150
#define BEST_SCORE_STATIC_WIDTH 125
#define PROBLEM_STATIC_WIDTH 300

#define MUTATION_STATIC_X ES_BUTTON_X
#define MUTATION_STATIC_Y 500
#define MUTATION_SLIDER_X ES_BUTTON_X+60
#define MUTATION_SLIDER_Y 500

// tbd: move
void TESMainWindow::CreateChildren()
{
#if(!NEW_LAYOUT)
	// create buttons
	mpESButton = new TESButton(this,ID_ES_BUTTON,"ES:",50,50,30,25);
	mpProblemButton = new TESButton(this,ID_PROBLEM_BUTTON,"Problem:",
		275,50,100,25);
	mpNetworkButton = new TESButton(this,ID_NETWORK_BUTTON,"Network:",
		50,100,100,25);
	mpRunButton = new TESButton(this,ID_RUN_BUTTON,"Run",400,100,50,25);
	mpPauseButton = new TESButton(this,ID_PAUSE_BUTTON,"Pause",475,100,50,25);
	mpPlotButton = new TESButton(this,ID_PLOT_BUTTON,"Plot",550,100,50,25);
	mpResetButton = new TESButton(this,ID_RESET_BUTTON,"Reset",625,100,50,25);
	mpBestButton = new TESButton(this,ID_BEST_BUTTON,"Best:",475,150,50,25);
	mpGenerationButton = new TESButton(this,ID_GENERATION_BUTTON,"Generation:",
		50,150,100,25);

	// create statics
	new TESStatic(this,ID_MUTATION_STATIC,"Mutation:",50,500,75,25);
	mpGenerationNumStatic=new TESStatic(this,ID_GENERATION_NUM_STATIC,"0",175,150,
		50,25);
	char temp[200];
	GetESStaticStr(temp);
	mpESStatic=new TESStatic(this,ID_ES_STATIC,temp,100,50,75,25);
	GetNetworkStaticStr(temp);
	mpNetworkStatic = new TESStatic(this,ID_NETWORK_STATIC,temp,175,100,200,25);
	mpBestScoreStatic=new TESStatic(this,ID_BEST_SCORE_STATIC,
		"NA",550,150,125,25);
	GetProblemStaticStr(temp);
	mpProblemStatic=new TESStatic(this,ID_PROBLEM_STATIC,temp,400,50,275,25);

	mpMutationSlider = new THSlider(this,ID_MUTATION_SLIDER,150,500,300,25);
#else
	// create buttons
	mpESButton = new TESButton(this,ID_ES_BUTTON,"ES:",ES_BUTTON_X,ES_BUTTON_Y);
	int iNetworkY=ES_BUTTON_Y+mpESButton->GetHeight()+1;
	mpNetworkButton = new TESButton(this,ID_NETWORK_BUTTON,"Network:",
		NETWORK_BUTTON_X,NETWORK_BUTTON_Y);
	int iProblemY=NETWORK_BUTTON_Y+mpNetworkButton->GetHeight()+1;
	mpProblemButton = new TESButton(this,ID_PROBLEM_BUTTON,"Problem:",
		PROBLEM_BUTTON_X,PROBLEM_BUTTON_Y);
	int iRunX=PROBLEM_BUTTON_X+mpProblemButton->GetWidth()+NETWORK_STATIC_WIDTH;
	mpRunButton = new TESButton(this,ID_RUN_BUTTON,"Run",
		RUN_BUTTON_X,RUN_BUTTON_Y,RUN_BUTTON_WIDTH,mpESButton->GetHeight());
	int iPauseX=iRunX+RUN_BUTTON_WIDTH;
	mpPauseButton = new TESButton(this,ID_PAUSE_BUTTON,"Pause",
		PAUSE_BUTTON_X,PAUSE_BUTTON_Y,RUN_BUTTON_WIDTH,mpESButton->GetHeight());
	mpResetButton = new TESButton(this,ID_RESET_BUTTON,"Reset",
		RESET_BUTTON_X,RESET_BUTTON_Y,
		RUN_BUTTON_WIDTH,mpNetworkButton->GetHeight());
	mpPlotButton = new TESButton(this,ID_PLOT_BUTTON,"Plot",
		PLOT_BUTTON_X,PLOT_BUTTON_Y,
		RUN_BUTTON_WIDTH,mpNetworkButton->GetHeight());
	int iGenerationX=iPauseX+RUN_BUTTON_WIDTH+GENERATION_HPADDING;
	mpGenerationButton = new TESButton(this,ID_GENERATION_BUTTON,"Generation:",
		GENERATION_BUTTON_X,GENERATION_BUTTON_Y);
	mpBestButton = new TESButton(this,ID_BEST_BUTTON,"Best:",
		BEST_BUTTON_X,BEST_BUTTON_Y);

	// create statics
	mpGenerationNumStatic=new TESStatic(this,ID_GENERATION_NUM_STATIC,"0",
		GENERATION_BUTTON_X+mpGenerationButton->GetWidth(),GENERATION_BUTTON_Y,
		GENERATION_NUM_STATIC_WIDTH,mpGenerationButton->GetHeight());
	char temp[200];
	GetESStaticStr(temp);
	mpESStatic=new TESStatic(this,ID_ES_STATIC,temp,
		ES_BUTTON_X+mpESButton->GetWidth(),ES_BUTTON_Y,
		ES_STATIC_WIDTH,mpESButton->GetHeight());
	GetNetworkStaticStr(temp);
	mpNetworkStatic = new TESStatic(this,ID_NETWORK_STATIC,temp,
		NETWORK_BUTTON_X+mpNetworkButton->GetWidth(),NETWORK_BUTTON_Y,
		NETWORK_STATIC_WIDTH,mpNetworkButton->GetHeight());
	mpBestScoreStatic=new TESStatic(this,ID_BEST_SCORE_STATIC,
		"NA",BEST_BUTTON_X+mpBestButton->GetWidth(),BEST_BUTTON_Y,
		BEST_SCORE_STATIC_WIDTH,mpBestButton->GetHeight());
	GetProblemStaticStr(temp);
	mpProblemStatic=new TESStatic(this,ID_PROBLEM_STATIC,temp,
		PROBLEM_BUTTON_X+mpProblemButton->GetWidth(),PROBLEM_BUTTON_Y,
		PROBLEM_STATIC_WIDTH,mpProblemButton->GetHeight());
//	int iMutationX=PROBLEM_BUTTON_X+mpProblemButton->GetWidth()
//		+PROBLEM_STATIC_WIDTH;
	new TESStatic(this,ID_MUTATION_STATIC,"Mutation:",MUTATION_STATIC_X,
		MUTATION_STATIC_Y,75,mpProblemButton->GetHeight());

	mpMutationSlider = new THSlider(this,ID_MUTATION_SLIDER,
		MUTATION_SLIDER_X,MUTATION_SLIDER_Y,300,mpProblemButton->GetHeight());
#endif
}

void TESMainWindow::SetupWindow()
{
	TWindow::SetupWindow();
	mpMutationSlider->SetRange(0,MAX_MUTATION_SLIDER_POS);
	mpMutationSlider->SetRuler(0,FALSE);
	mpMutationSlider->SetPosition(0);
}

bool TESMainWindow::IdleAction(long lIdleCount)
{
	ChildrenIdleAction(lIdleCount);

	if(mbRunning)
	{
		if(!mGenerationState)
		{
			InitGenerationCycle();
		}

		if(GenerationCycle()!=1)
			return(true);

		mGenerationState=NO_STATE;
		UpdateBestScoreStatic();
		UpdateGenerationNumStatic();
		AddGenerationStats();
#if(PLOT_INTERVAL!=1) // avoid "conditional always true" warning
		if(!(mES.generation%PLOT_INTERVAL))
#endif
		{
			RedrawPlotWindow();
			UpdateMutationSlider();
		}
	}
	return(true);
}

void TESMainWindow::HandleESButtonMsg()
{
TESConfigStruct Config;

	// copy workspace parameters to transfer struct
	itoa(mES.mu,Config.pMu,10);
	itoa(mES.lambda,Config.pLambda,10);
	Config.bPlus=mbPlus;
	Config.bComma=!mbPlus;

	TESConfigDialog Dialog(this,&Config);

	if(Dialog.Execute()==IDOK)
	{
		// copy window parameters to workspace
		// tbd: validate
		mES.mu=atoi(Config.pMu);
		mES.lambda=atoi(Config.pLambda);
		mbPlus=Config.bPlus;

		UpdateESStatic();
		Reset();
	}
}

void TESMainWindow::HandleProblemButtonMsg()
{
TOpenSaveDialog::TData FilenameData(OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST,
	"Training Sets (*.ts)|*.ts|All Files (*.*)|*.*|",0,"","*");

	if(TFileOpenDialog(this, FilenameData, 0, "Open Training File").Execute()
		== IDOK)
	{
		if(TestNet.LoadTrainingSet(FilenameData.FileName)<0)
		{
      	MessageBox("File load failed!","Error!");
		}
      SetChromosomeLength(TestNet.NumWeights());
		Reset();
		UpdateProblemStatic();
	}
}

void TESMainWindow::HandleRunButtonMsg()
{
	if (!mbPlus && mES.mu > mES.lambda)
		 return;

	StartRunning();
}

void TESMainWindow::HandlePauseButtonMsg()
{
	PauseRunning();
}

void TESMainWindow::HandlePlotButtonMsg()
{
	if(!mpPlotWindow)
		(new TESGraphWindow(this,"ES Graph",&mpScoreList,&mpPlotWindow))
			->Create();
}

void TESMainWindow::HandleResetButtonMsg()
{
	Reset();
}

void TESMainWindow::HandleNetworkButtonMsg()
{
TNetworkConfigStruct Config;
int n;

	// copy workspace parameters to transfer struct
	Config.bFeedforward=1;
	Config.bHopfield=0;
	itoa(TestNet.GetHiddenLayers(),Config.pLayers,10);

	int iHiddenNodesPerLayer=-1;
	byte bAllHiddenLayersEqual=1;
	for(n=1;n<TestNet.GetLayers()-1;n++)
	{
		if(iHiddenNodesPerLayer==-1)
		{
			iHiddenNodesPerLayer=TestNet.GetLayerSize(n);
		}
		else
		{
			if(iHiddenNodesPerLayer!=TestNet.GetLayerSize(n))
			{
				bAllHiddenLayersEqual=0;
				break;
			}
		}
	}

	if(bAllHiddenLayersEqual)
	{
		itoa(iHiddenNodesPerLayer,Config.pNodesPerLayer,10);
	}
	else
	{
		Config.pNodesPerLayer[0]='\0';
		for(n=1;n<TestNet.GetLayers()-1;n++)
		{
			if(n>1)
         	strcat(Config.pNodesPerLayer,", ");
			itoa(TestNet.GetLayerSize(n),
				&(Config.pNodesPerLayer[strlen(Config.pNodesPerLayer)]),10);
		}
	}

	itoa(TestNet.GetTotalHiddenNodes(),Config.pTotalNodes,10);
	Config.bUseBackpropagation=mbUseBackpropagation;

	TNetworkConfigDialog Dialog(this,&Config);

	if(Dialog.Execute()==IDOK)
	{
		// assign parameters to network
		// tbd: validate

		TestNet.SetNumLayers(atoi(Config.pLayers)+2);
		strcat(Config.pNodesPerLayer,",");
		char *pToken=strtok(Config.pNodesPerLayer,",");
		int iLayer=1;
		while(pToken && iLayer<TestNet.GetLayers()-1)
		{
			char *pPos=&(pToken[strlen(pToken)-1]);
			while(pPos>pToken)
			{
				char c=toupper(*pPos);
				if(c=='S'||c=='T'||c=='L')
				{
					switch(c)
					{
					case 'S':
						TestNet.SetActivation(iLayer,ACTIVATION_SIGMOID);
						break;

					case 'T':
						TestNet.SetActivation(iLayer,ACTIVATION_TANH);
						break;

					case 'L':
						TestNet.SetActivation(iLayer,ACTIVATION_LINEAR);
						break;
					};
					*pPos=0;
				}
				pPos--;
			}
			iHiddenNodesPerLayer=atoi(pToken);
			TestNet.SetLayerSize(iLayer++,iHiddenNodesPerLayer);
			pToken=strtok(0,",");
		}
		for(;iLayer<TestNet.GetLayers()-1;iLayer++)
		{
			TestNet.SetLayerSize(iLayer,iHiddenNodesPerLayer);
		}
		TestNet.AllocWeights();

		SetChromosomeLength(TestNet.NumWeights());

		mbUseBackpropagation=Config.bUseBackpropagation;

		UpdateNetworkStatic();
		Reset();
	}
}

void TESMainWindow::HandleBestButtonMsg()
{
	TNVisWindow *pNVisWindow=new TNVisWindow(this,&TestNet,
		&(mParent.GetMember(0)),&(mES.param));
	if(pNVisWindow)
		pNVisWindow->Create();
}

void TESMainWindow::HandleGenerationButtonMsg()
{
TGenerationWindow *pWin;

	pWin = new TGenerationWindow(this,"Generations",mpGenerationList,&TestNet,
		mES.param.GetUpper(0),&(mES.param));
	pWin->Create();
}

void TESMainWindow::HandleMutationSlider(UINT /*code*/)
{
int n,m;
//long double ldSpillover=0;

//	double dAvgSigma=GetAverageSigma();
	double dNewAvgSigma=((double)mpMutationSlider->GetPosition()
		/(double)MAX_MUTATION_SLIDER_POS)*mpUBSigma[0];

	for(n=0;n<mParent.size;n++)
	{
		for(m=mES.nvars;m<mES.nvars+mES.nsigma;m++)
		{
			mParent.GetMember(n).SetGene(m,dNewAvgSigma);
/*
			double dNewSigma=mParent.GetMember(n).GetGene(m)*dNewAvgSigma
				/dAvgSigma;

			if(dNewSigma<mpLBSigma[0])
			{
				ldSpillover+=mpLBSigma[0]-dNewSigma;
				dNewSigma=mpLBSigma[0];
			}
			else if(dNewSigma>mpUBSigma[0])
			{
				ldSpillover+=dNewSigma-mpUBSigma[0];
				dNewSigma=mpUBSigma[0];
			}

			mParent.GetMember(n).SetGene(m,dNewSigma);
*/
		}
	}

	/*
	if(ldSpillover>0)
	{
		for(n=0;n<mParent.size;n++)
		{
			for(m=mES.nvars;m<mES.nvars+mES.nsigma;m++)
			{
			}
		}
	}
   */
}

void TESMainWindow::StartRunning()
{
	mbRunning=1;
}

void TESMainWindow::PauseRunning()
{
	mbRunning=0;
}

void TESMainWindow::StopRunning()
{
	mbRunning=0;
}

void TESMainWindow::SetChromosomeLength(int iLen)
{
	mES.SetNumVars(iLen);
	mPInfo.SetNumParameters(iLen);

	TestNet.InitNetwork(mES);
	mES.param.InitParameter(mPInfo.GetNParams());
	mES.param.InitPInfo(mPInfo);
	mES.param.SetEval(Eval);

	// re-allocate sigmas
	delete(mpLBSigma);
	delete(mpUBSigma);
	mpLBSigma=new double[mES.nsigma];
	mpUBSigma=new double[mES.nsigma];
}

void TESMainWindow::Reset()
{
	mES.generation=0;
	mbRunning=0;
   mGenerationState=NO_STATE;

	InitES();
	InitGenerationStats();

	RedrawPlotWindow();
	UpdateGenerationNumStatic();
	UpdateBestScoreStatic();
	mpMutationSlider->SetPosition(0);

	DeleteGenerationList();
   SaveCurrentGeneration();
}

void TESMainWindow::RedrawPlotWindow()
{
	if(mpPlotWindow)
		mpPlotWindow->RedrawWindow(0,0,RDW_INVALIDATE);
}

void TESMainWindow::InitGenerationStats()
{
GenerationScore *pCurScore;

	pCurScore=mpScoreList;
	while(pCurScore)
	{
	GenerationScore *pTemp=pCurScore;

		pCurScore=pCurScore->pNext;
		delete(pTemp);
	}

	mpScoreList=0;
}

void TESMainWindow::AddGenerationStats()
{
GenerationScore *pNewScore=new GenerationScore,*pCurrent;

	pNewScore->iGeneration=(int)mES.generation;
	pNewScore->dDiversity=mParent.Diversity();
	pNewScore->dMin=sqrt(mParent.stats.Min());
	pNewScore->dMax=sqrt(mParent.stats.Max());
	pNewScore->dAverage=sqrt(mParent.stats.Average());
	pNewScore->dMedian=sqrt(mParent.stats.Median());
	pNewScore->pNext=0;

	if(!mpScoreList)
	{
		mpScoreList=pNewScore;
	}
	else
	{
		pCurrent=mpScoreList;
		while(pCurrent->pNext)
		{
			pCurrent=pCurrent->pNext;
		}
		pCurrent->pNext=pNewScore;
	}
}

int TESMainWindow::InitES()
{
int i;

	mParent.InitPopulation(mES.mu, mES.clen);
	mChild.InitPopulation(mES.lambda, mES.clen);

	for (i=0; i<mES.nsigma; i++)
	{
//		mpLBSigma[i] = (mPInfo.GetUpper(i))*mES.lbsigma;
//		mpUBSigma[i] = (mPInfo.GetUpper(i))*mES.ubsigma;
		mpLBSigma[i] = mES.lbsigma;
		mpUBSigma[i] = mES.ubsigma;
	}

	for (i=0; i<mES.mu; i++)
	{
		(mParent.GetMember(i)).Randomize(mES.rn,mES.nvars,
			mES.nvars+mES.nsigma,mpLBSigma,mpUBSigma);

		if (mES.usealpha)
			(mParent.GetMember(i)).Randomize(mES.rn, mES.nvars
				+mES.nsigma,mES.clen,-M_PI,M_PI);
	}

	// Randomize the X portion of the population
	mParent.Randomize(mES.rn, mES.param);

	mParent.Sort();

	// index the parent population
	for(i=0;i<mES.mu;i++)
	{
		mParent.GetMember(i).miIndex=i;
		mParent.GetMember(i).miGeneration=0;
	}

	return(0);
}

int TESMainWindow::InitGenerationCycle()
{
	mGenerationState=START;
	miChildrenGenerated=0;
   return(0);
}

int TESMainWindow::GenerationCycle()
{
int i;

	switch(mGenerationState)
	{
	case START:

		// each member of the parent population will be "its own parent" if it
		// survives into the next generation
		for(i=0;i<mES.mu;i++)
		{
			mParent.GetMember(i).miWeightParent1=mParent.GetMember(i).miIndex;
			mParent.GetMember(i).miWeightParent2=-1;
			mParent.GetMember(i).miSigmaParent1=mParent.GetMember(i).miIndex;
			mParent.GetMember(i).miSigmaParent2=-1;
		}

		mGenerationState++;
		break;

	case GENERATE_CHILD:

		if(!mbPlus)
		{
			ESCrossover(mES,mParent);
		}
		else
		{
			if (mES.mu > 1)
			  ESCrossover(mES,mParent);
			else
			  mParent.CopyMember(0,mES.child);
		}

		ESMutate (mES, mpLBSigma, mpUBSigma);
		mChild.AddMember(miChildrenGenerated, mES.child, mES.param);

		miChildrenGenerated++;
		if(miChildrenGenerated>=mES.lambda)
		{
			mGenerationState++;
		}
		break;

	case MERGE:

		if(!mbPlus)
		{
			mChild.Sort();

			for (i=0; i<mES.mu; i++)
				mParent.AddMember(i, mChild.GetMember(i));
		}
		else
		{
			// Now merge the children into parent population
			for (i=0; i<mES.lambda; i++)
				mParent.AddMember(mChild.GetMember(i));
		}

		mGenerationState++;
		break;

	case INDEX:

		// index the new generation
		for(i=0;i<mES.mu;i++)
		{
			mParent.GetMember(i).miIndex=i;
			mParent.GetMember(i).miGeneration=(int)(mES.generation+1);
		}

		mGenerationState++;
		break;

	case SAVE:

		mES.generation++;
		SaveCurrentGeneration();

		mGenerationState++;
		break;

	case DONE:
   	return(1);

	default:
		return(-1);
	};
	return(0);
}

int TESMainWindow::Generation()
{
int iResult;

	InitGenerationCycle();
	while(!(iResult=GenerationCycle()));
	return(iResult<0?iResult:0);
#if(0)
	// each member of the parent population will be "its own parent" if it
	// survives into the next generation
	for(i=0;i<mES.mu;i++)
	{
		mParent.GetMember(i).miWeightParent1=mParent.GetMember(i).miIndex;
		mParent.GetMember(i).miWeightParent2=-1;
		mParent.GetMember(i).miSigmaParent1=mParent.GetMember(i).miIndex;
		mParent.GetMember(i).miSigmaParent2=-1;
	}

	// Generate lambda offspring
	for (i=0; i<mES.lambda; i++)
	{
		if(!mbPlus)
		{
			ESCrossover(mES,mParent);
		}
		else
		{
			if (mES.mu > 1)
			  ESCrossover(mES,mParent);
			else
			  mParent.CopyMember(0,mES.child);
		}

		ESMutate (mES, mpLBSigma, mpUBSigma);
		mChild.AddMember(i, mES.child, mES.param);
	}

	if(!mbPlus)
	{
		mChild.Sort();

		for (i=0; i<mES.mu; i++)
			mParent.AddMember(i, mChild.GetMember(i));
	}
	else
	{
		// Now merge the children into parent population
		for (i=0; i<mES.lambda; i++)
			mParent.AddMember(mChild.GetMember(i));
	}

	// index the new generation
	for(i=0;i<mES.mu;i++)
	{
		mParent.GetMember(i).miIndex=i;
		mParent.GetMember(i).miGeneration=mES.generation+1;
	}

	mES.generation++;

	SaveCurrentGeneration();

	return(0);
#endif
}

int TESMainWindow::LoadConfigFile()
{
	ifstream ifile("default.cfg");

	ifile >> mParams;
	ifile >> mES;
	ifile >> mPInfo;
	ifile >> TestNet;

	ifile.close();

	return(0);
}

void TESMainWindow::UpdateMutationSlider()
{
	double dAvgSigma=GetAverageSigma();

	// for now assume all parameters have the same range, so that all mpUBsigmas
	// are the same.  Also assume |mpUBSigma|>=|mpLBSigma|, and that
	// mpUBSigma>0.
	float fNormMutation=dAvgSigma/mpUBSigma[0];
	if(fNormMutation<0.0f)
		fNormMutation=0.0f;
	if(fNormMutation>1.0f)
		fNormMutation=1.0f;

	mpMutationSlider->SetPosition(fNormMutation*(float)MAX_MUTATION_SLIDER_POS);
}

void TESMainWindow::UpdateESStatic()
{
char temp[200];

	GetESStaticStr(temp);
	mpESStatic->SetText(temp);
}

void TESMainWindow::UpdateGenerationNumStatic()
{
char temp[200];

	itoa((int)mES.generation,temp,10);
	mpGenerationNumStatic->SetText(temp);
}

void TESMainWindow::UpdateBestScoreStatic()
{
char temp[200];

	if(!mES.generation)
	{
		mpBestScoreStatic->SetText("NA");
	}
	else
	{
#if(!ATTRIBUTE_EVAL)
		sprintf(temp,"%lf",sqrt(mParent.GetWorth(0)));
#else
		double dFitness=mParent.GetWorth(0);
		dFitness=100.0f-100.0f*dFitness;
		sprintf(temp,"%lf",dFitness);
		strcat(temp,"%");
#endif
		mpBestScoreStatic->SetText(temp);
	}
}

void TESMainWindow::UpdateProblemStatic()
{
char temp[200];

	GetProblemStaticStr(temp);
	mpProblemStatic->SetText(temp);
}

double TESMainWindow::GetAverageSigma()
{
long double ldSigmaSum=0;

	// calculate sigma sum
	for(int n=0;n<mParent.size;n++)
	{
		for(int m=mES.nvars;m<mES.nvars+mES.nsigma;m++)
		{
			double dSigma=mParent.GetMember(n).GetGene(m);
			ldSigmaSum+=fabs(dSigma);
		}
	}

	return((double)(ldSigmaSum/(long double)mParent.size
		/(long double)mES.nsigma));
}

void TESMainWindow::UpdateNetworkStatic()
{
char temp[200];

	GetNetworkStaticStr(temp);
   mpNetworkStatic->SetText(temp);
}

void TESMainWindow::GetESStaticStr(char *pDest)
{
	strcpy(pDest,"(");
	itoa(mES.mu,&(pDest[strlen(pDest)]),10);
	if(mbPlus)
		strcat(pDest,"+");
	else
		strcat(pDest,",");
	itoa(mES.lambda,&(pDest[strlen(pDest)]),10);
	strcat(pDest,")");
}

void TESMainWindow::GetProblemStaticStr(char *pDest)
{
	strcpy(pDest,TestNet.GetProblemName());
	strcat(pDest," (");
	itoa(TestNet.GetNumInputs(),&(pDest[strlen(pDest)]),10);
	strcat(pDest,"i,");
	itoa(TestNet.GetNumOutputs(),&(pDest[strlen(pDest)]),10);
	strcat(pDest,"o,");
	itoa(TestNet.GetNumSamples(),&(pDest[strlen(pDest)]),10);
	strcat(pDest,"s)");
}

void TESMainWindow::GetNetworkStaticStr(char *pDest)
{
	strcpy(pDest,"Feedforward");
	strcat(pDest," ");
	itoa(TestNet.GetHiddenLayers(),&(pDest[strlen(pDest)]),10);
	strcat(pDest,"x");
	itoa(TestNet.GetLayerSize(1),&(pDest[strlen(pDest)]),10);
}

void TESMainWindow::SaveCurrentGeneration()
{
int n;

#if(SAVE_GENERATIONS)
	TGeneration *pNext=new TGeneration;
	pNext->pSurvivors=new Chromosome[mParent.size];
	int iChromLen=mParent.GetMember(0).GetLength();
	for(n=0;n<mParent.size;n++)
	{
		pNext->pSurvivors[n].InitChromosome(iChromLen);
		pNext->pSurvivors[n]=mParent.GetMember(n);
	}
	pNext->iSurvivors=mParent.size;
	pNext->pDead=0;
	pNext->iDead=0;
	pNext->pNext=0;

	// add this generation to the list
	if(!mpGenerationList)
	{
		mpGenerationList=pNext;
	}
	else
	{
		TGeneration *pLastGeneration=mpGenerationList;
		while(pLastGeneration->pNext)
			pLastGeneration=pLastGeneration->pNext;
		pLastGeneration->pNext=pNext;
	}
#endif
}

void TESMainWindow::DeleteGenerationList()
{
TGeneration *pCurNode=mpGenerationList;

	while(pCurNode)
	{
		TGeneration *pTemp=pCurNode;
		pCurNode=pCurNode->pNext;
		delete(pTemp);
	}
   mpGenerationList=0;
}

void TESWinApp::InitMainWindow()
{
	MainWindow = new TESMainWindow("NVIS - Neural Network Visualization Tool");
}

Return to Appendix B.