page optimising a symbolic problem of sequences of instructions
TRANSCRIPT
Page
Optimising a Symbolic Problem of Optimising a Symbolic Problem of Sequences of InstructionsSequences of Instructions
Page 2
A Program that programs itselfA Program that programs itself
So far, we have seen GAs used for optimisation problems...
What about using GAs for developing programs that program themselves?
e.g. Can we write a GA that implements the following formula using a limited set of instructions? x3 + y3 + z
Page 3
Sample ProblemSample Problem
Consider a Virtual Computer Virtual Computer• a StackStack (or zero address) architecturearchitecture• has no registers, only a stack for which instructions
can manipulate the values on the stack.• has a simple instruction set simple instruction set (6 instructions that
use operands on the stack)
Page 4
Sample ProblemSample Problem
Simple Instruction SetSimple Instruction Set
Instruction Description
DUP Duplicate the top of the stack (stack: A => A A)
SWAP Swap the top two elements of the stack (stack: A B => B A)
MUL Multiply the top two elements of the stack (stack: 2 3 => 6)
ADD Add the top two elements of the stack (stack: 2 3 => 5)
OVER Duplicate the second item on the stack (stack: A B => B A B)
NOP No operation
Page 5
Sample ProblemSample Problem
Simple Instruction SetSimple Instruction Set• Simple and can be used to solve various
functionsfunctions.• Example: Compute the square of the top element
of the stack, assuming the top of the stack contains our input value:
• DUPDUP• MULMUL
This sequence duplicates the top of the stack and then multiplies the two elements together.
(X * X), or X2
Page 6
Solution EncodingSolution Encoding
We encode the solution of the problem, not the problem itself (because the problem is used as the fitness measure for our chromosomes).
Our chromosomechromosome represents a string of instructions in a contiguous block. We assign numerical values to each of the instructions.
DUP = 0DUP = 0SWAP = 1SWAP = 1MUL = 2MUL = 2ADD = 3ADD = 3OVER = 4OVER = 4NOP = 5NOP = 5
Our encoding is a contiguous string contiguous string of bytes representing the stream of stream of instructionsinstructions.
Chromosome = program
Page
Fitness EvaluationFitness Evaluation
7
Evaluating the fitness of a given chromosome is a simple process of executing the string of instructions executing the string of instructions that are contained in the chromosome.
• We prepare a simple stack of some depth.• Load the initial values onto the stack.• Execute each instruction sequentially until the program reaches the end instruction.
The fitnessfitness values is then calculated as the difference between the resulting value on the stack and what was expected per our objective function (predefined for the test).
Page
RecombinationRecombination
8
For this problem, crossover and mutation are used.
• The crossover operator crossover operator breaks an instruction stream at a single point and swaps the tails of each parent.
• The mutation operator mutation operator is a random reassignment of the gene with a new instruction.
• Because the chromosome represents the program, each genegene is a single instruction.
Page
Page
Virtual Machine Virtual Machine ImplementationImplementation
10
• Stack-based operations: SPEEK, SPUSH, SPOP• Assert macros to identify violations in the program
DUP
MULDUP
Stack depth
Integer stack
stackPointer
Page
Virtual Machine Virtual Machine SymbolicsSymbolics
11
//Instruction set//Instruction set#define DUP 0x00#define SWAP 0x01#define MUL 0x02#define ADD 0x03#define OVER 0x04#define NOP 0x05#define MAX_INSTRUCTION (NOP+1)
//Error signals//Error signals#define NONE 0#define STACK_VIOLATION 1#define MATH_VIOLATION 2
Page
Virtual Machine Virtual Machine SymbolicsSymbolics
12
#define STACK_DEPTH 1515
int stack[STACK_DEPTH];int stackPointer;
//Error functions//Error functions#define ASSERT_STACK_ELEMENTS(x) \ if (stackPointer < x) { error = STACK_VIOLATION ; break; }
#define ASSERT_STACK_NOT_FULL \ if (stackPointer == STACK_DEPTH) { \ error = STACK_VIOLATION ; break; }//Stack operators//Stack operators#define SPUSH(x) (stack[stackPointer++] = x)#define SPOP (stack[--stackPointer])#define SPEEK (stack[stackPointer-1])
stackPointer
x
y
z
Tells how many elements are there in the stack.
Page
Virtual Machine Virtual Machine ImplementationImplementation
13
Stack depth
Integer stack
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
• Stack-based operations: SPEEK, SPUSH, SPOP• Assert macros to identify violations in the program
One element higher than the topmost element
Page
Virtual Machine Virtual Machine ImplementationImplementation
14
Instruction: DUPInstruction: DUP
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
ASSERT_STACK_ELEMENTS(1); ASSERT_STACK_ELEMENTS(1); ASSERT_STACK_NOT_FULL; ASSERT_STACK_NOT_FULL; SPUSH(SPEEK); SPUSH(SPEEK);
• Stack-based operations: SPEEK, SPUSH, SPOP• Assert macros to identify violations in the program
Page
Virtual Machine Virtual Machine ImplementationImplementation
15
• Stack-based operations: SPEEK, SPUSH, SPOP• Assert macros to identify violations in the program
Instruction: SWAPInstruction: SWAP
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
ASSERT_STACK_ELEMENTS(2); ASSERT_STACK_ELEMENTS(2); a = stack[stackPointer-1]; a = stack[stackPointer-1]; stack[stackPointer-1] = stack[stackPointer-2]; stack[stackPointer-1] = stack[stackPointer-2]; stack[stackPointer-2] = a; stack[stackPointer-2] = a;
Page
Virtual Machine Virtual Machine ImplementationImplementation
16
• Stack-based operations: SPEEK, SPUSH, SPOP• Assert macros to identify violations in the program
Instruction: MULInstruction: MUL
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
ASSERT_STACK_ELEMENTS(2); ASSERT_STACK_ELEMENTS(2); a = SPOP; a = SPOP; b = SPOP; b = SPOP; SPUSH(a * b);SPUSH(a * b);
Page
Virtual Machine Virtual Machine ImplementationImplementation
17
• Stack-based operations: SPEEK, SPUSH, SPOP• Assert macros to identify violations in the program
Instruction: ADDInstruction: ADD
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
ASSERT_STACK_ELEMENTS(2); ASSERT_STACK_ELEMENTS(2); a = SPOP; a = SPOP; b = SPOP; b = SPOP; SPUSH(a + b);SPUSH(a + b);
Page
Virtual Machine Virtual Machine ImplementationImplementation
18
• Stack-based operations: SPEEK, SPUSH, SPOP• Assert macros to identify violations in the program
Instruction: OVERInstruction: OVER
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
ASSERT_STACK_ELEMENTS(2); ASSERT_STACK_ELEMENTS(2); SPUSH(stack[stackPointer-2]);SPUSH(stack[stackPointer-2]);
Page
Virtual Machine Virtual Machine ImplementationImplementation
19
•The function operates on the arguments according to the program fed to it.
Inputs: Inputs:
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
•ProgramProgram•Length of the programLength of the program•Arguments (operands)Arguments (operands)•Length of the argumentsLength of the arguments
For testing, fitness calculations
Page
Virtual Machine Virtual Machine ImplementationImplementation
20
•The function operates on the arguments based on the program fed to it.
Sequence of Operations: Sequence of Operations:
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
1.1. Load the passed arguments (operands) on Load the passed arguments (operands) on the stack. This is done in a reverse the stack. This is done in a reverse fashion. That is, element 0 will be placed fashion. That is, element 0 will be placed at the top of the stack.at the top of the stack.
Page
Virtual Machine Virtual Machine ImplementationImplementation
21
Sequence of Operations: Sequence of Operations:
stackPointer
Function: Function: interpretStackMachineinterpretStackMachine
x
y
z
1.1. Load the passed arguments (operands) on Load the passed arguments (operands) on the stack. This is done in a reverse the stack. This is done in a reverse fashion. That is, element 0 will be placed fashion. That is, element 0 will be placed at the top of the stack.at the top of the stack.
2.2. Execute each of the instructions until the Execute each of the instructions until the end of the program is reached. Return an end of the program is reached. Return an errorerror if one is encountered to allow if one is encountered to allow another program to be generated.another program to be generated.
Page
Source CodeSource Code
22
int interpretSTM(const int *program, int progLength, const int *args, int argsLength){
int pc = 0; int i, error = NONE; int a, b; stackPointer = 0;
/* Load the arguments onto the stack */ for (i = argsLength-1 ; i >= 0 ; i--) { SPUSH(args[i]); }
/* Execute the program */ while ((error == NONE) && (pc < progLength)) {
switch(program[pc++]) { case DUP: ASSERT_STACK_ELEMENTS(1);
ASSERT_STACK_NOT_FULL; SPUSH(SPEEK); break;
case SWAP: ASSERT_STACK_ELEMENTS(2); a = stack[stackPointer-1]; stack[stackPointer-1] = stack[stackPointer-2]; stack[stackPointer-2] = a; break;
case MUL: ASSERT_STACK_ELEMENTS(2); a = SPOP; b = SPOP; SPUSH(a * b); break; case ADD: ASSERT_STACK_ELEMENTS(2); a = SPOP; b = SPOP; SPUSH(a + b); break; case OVER: ASSERT_STACK_ELEMENTS(2); SPUSH(stack[stackPointer-2]); break;
} /* Switch opcode */
} /* Loop */ return(error);}
Page
Page
GAGA
24
stackPointer
Declaration of PopulationsDeclaration of Populations
x
y
z
typedef struct populationpopulation { float fitness; int progSize; int program[MAX_PROGRAM];} POPULATION_TYPEPOPULATION_TYPE;
POPULATION_TYPEPOPULATION_TYPE populations[22][MAX_CHROMS];
int curPop;
Old and New Populations
3000
Page
Initialising a chromosomeInitialising a chromosome
25
We assign each of the genes a random instruction.We assign each of the genes a random instruction.
void initMember( pop, index ){ int progIndex; populations[pop][index].fitness = 0.0; populations[pop][index].progSize = MAX_PROGRAM-1; progIndex = 0; while (progIndex < MAX_PROGRAM) { populations[pop][index].program[progIndex+
+] = getRand(MAX_INSTRUCTION); }}
see init.c
Page
Initialising the populationInitialising the population
26
Initialize all of the chromosomes in the population Initialize all of the chromosomes in the population (potential * solutions to the given problem).(potential * solutions to the given problem).
void initPopulation( void ){ int index; for (index = 0 ; index < MAX_CHROMS ; index++) { initMember(curPop, index); }}
see init.c
Page
GAGA
27
stackPointer
During the process of During the process of RecombinationRecombination
x
y
z
POPULATION_TYPEPOPULATION_TYPE populations[22][MAX_CHROMS];
curPop
!curPop
Where the Selection of Parents is performed
Where the children are placed
Also referred to as the nextPop see main.c
Page
GAGA
28
Basic Flow Basic Flow 1.1. Seed the random number generator.Seed the random number generator.2.2. Initialise the population with random chromosomes.Initialise the population with random chromosomes.3.3. Calculate fitness values for the chromosomes. Calculate fitness values for the chromosomes.
(performFitnessCheck).(performFitnessCheck).4.4. Use sum of fitness for probabilistic selection of parents.Use sum of fitness for probabilistic selection of parents.5.5. Apply recombination operations = crossover + mutation.Apply recombination operations = crossover + mutation.6.6. Switch between the old and the new populations of Switch between the old and the new populations of
chromosomes.chromosomes.7.7. Calculate fitness values.Calculate fitness values.8.8. Check for premature convergence.Check for premature convergence.9.9. Check if the desired solution has been found already (by Check if the desired solution has been found already (by
way of best fitness)way of best fitness)10.10. If (solution is found), show best chromosome, else go If (solution is found), show best chromosome, else go
back to step 4.back to step 4.
Same as conventional GAs
Page
Basic FlowBasic Flow
29
srand(time(NULL)); initPopulation(); performFitnessCheck( fp );
while (generation < MAX_GENERATIONS) {
curCrossovers = curMutations = 0; performSelection(); /* Switch the populations *//* Switch the populations */ curPop = (curPop == 0) ? 1 : 0; performFitnessCheck( fp )
check for premature convergence, if so, break check if the desired solution has been found already, if so, break
} show the best chromosome (solution)
Page
performperformFitnessCheckFitnessCheck
30
1. Define the arguments (operands) for testing.2. Calculate the evaluation of the target equation = target equation =
correct answercorrect answer.3. Feed the same arguments to the
interpretStackMachine to evaluate the fitness.Go back to Step 1: the fitness is calculated (10 times10 times)
based on a three-tiered measurethree-tiered measure:
If the program exited gracefully (no math error or program error), we give it a TIER1 Value = 1TIER1 Value = 1
see fitness.c
If only one element was left on the stack, then TIER2 Value = 20TIER2 Value = 20
If the top of the stack contains the correct value, then TIER3 Value = 50TIER3 Value = 50
To ensure correctness of program generated
Page
Check for premature convergenceCheck for premature convergence
31
Check Check diversitydiversity of population after of population after ¼¼ of the of the generations has completed. If the population has generations has completed. If the population has prematurely converged, exit to allow the user to prematurely converged, exit to allow the user to restart.restart.
if ( generation > (MAX_GENERATIONS * 0.25) ) { if ((avgFitness / maxFitness) > 0.98)
{ printf("converged\n"); break; }
}
see main.c
Page
Sample RunsSample Runs
32
Equation: XEquation: X88
Resulting program evolved:
DUP MUL DUP MUL DUP MUL
Page
Sample RunsSample Runs
33
Equation: (x*2) + (y*2) + zEquation: (x*2) + (y*2) + z
Resulting program evolved:
ADD DUP ADD SWAP ADD
Page
Sample RunsSample Runs
34
Equation: (x*y)+(y*y)+zEquation: (x*y)+(y*y)+z
Resulting program evolved:
OVER ADD MUL ADD
Page
Sample RunsSample Runs
35
Equation: xEquation: x33+y+y22+z+z
Resulting program evolved:
DUP DUP MUL MUL SWAP DUP MUL SWAP ADD SWAP SWAP ADD
Page
Plot of fitness over timePlot of fitness over time
36time (1 = 100 generations)
Page