📄 simpleoscillatorexperiment.java
字号:
/*
* SimpleOscillatorExperiment.java
*
* Created on 06 February 2001, 14:18
*/
package jaga.pj.circuits.experiment;
import jaga.*;
import jaga.experiment.*;
import debug.DebugLib;
/**
*
* @author Michael Garvie
* @version
*/
public class SimpleOscillatorExperiment implements Experiment {
private int period;
// sample enough so that we try and achieve what number of rising edges:
// ie. if we are looking for 1 rising edge every 10 samples then we have to
// generate a test of 200 samples to expect to find 20 rising edges.
private int periodsToTest = 20;
// defines in how many pieces we will subdivide our test. If the pieces are
// too large then we may have a lot of edges at beginning and none at end
// and we don't want that!
private int testChunks = 4;
// how long output has to stay stable for it to count as a 1 or 0
// shorter glitches will be punished..
private int logicThreshold = 4;
// how much having short rising edges affects the fitness
// from 0 to inf, recommended at 0.6
private final double SHORT_PENALTY = 0.1;
/** Creates new SimpleOscillatorExperiment
* @param period how often we want a rising edge to appear in the output measured in sampleData elements (the smallest simulator time slice)
*/
public SimpleOscillatorExperiment( int period ) {
this.period = period;
}
/** Creates new SimpleOscillatorExperiment
* @param period how often we want a rising edge to appear in the output measured in sampleData elements
* @param periodsToTest sample enough so that we try and achieve what number of rising edges: ie. if we are looking for 1 rising edge every 10 samples then we have to generate a test of 200 samples to expect to find 20 rising edges.
* @param testChunks defines in how many pieces we will subdivide our test. If the pieces are too large then we may have a lot of edges at beginning and none at end and we don't want that!
* @param how long output has to stay stable for it to count as a 1 or 0 horter glitches will be punished..
*/
public SimpleOscillatorExperiment( int period, int periodsToTest, int testChunks, int logicThreshold )
{
this.period = period;
this.periodsToTest = periodsToTest;
this.testChunks = testChunks;
this.logicThreshold = logicThreshold;
}
/** returns a fitness associated to a given input/output pair for
* this experiment. The fitness is a double and is in adjusted
* fitness format. From 0 to 1, 1 being perfectly fit.
*
* There should be periodsToTest rising edges in the output because of the length it
* has been set to in the generateInput function. So now a good fitness
* function looks like:
*
* fitness = 1 / ( abs( risingEdges - periodsToTest ) + 1 )
*
* which looks like a big circus tent with its roof at (periodsToTest, 1)
*
* This is calculated for each chunks and their average fitness taken.
*
* Rising edges which result around 1s and 0s that don't meet the
* logicThreshold criteria are counted as bad edges and they contribute
* to a penalty which is multiplied to the fitness:
*
* penalty = 1 / ( badEdges + 1 )
*
* @param in array of inputs
* @param out array of outputs
*/
public double getFitness(SampleData[] in,SampleData[] out)
{
double totalFitness = 0d; // fitness of chunks seen so far
int iss = in[ 0 ].getSampleSeparation(); // this is how long each chunk is ( see generateInputs() method )
SampleData output = out[ 0 ]; // our output data, hopefully oscilates!
StringBuffer debugText = null;
if( DebugLib.trcLogger.isLogging )
{
debugText = new StringBuffer( "\nidl actQ\n" );
}
if( DebugLib.trcLogger.isLogging )
{
// other loop too optimized to show all output values
for( int ol = 0; ol < output.length(); ol++ )
{
debugText.append( output.get( ol ) + "" );
}
}
// do each chunk separately
for( int chl = 0; chl < testChunks; chl++ )
{
// 1) Find out how many valid and invalid rising edges there are.
int niceRisingEdges = 0; // # found that meet thresh_hold criteria
int shortRisingEdges = 0; // # found that don't meet thresh_hold criteria
int oPos = chl * iss; // our position in the output data
for( int ol = oPos + logicThreshold; ol < oPos + iss; ol++ )
{
boolean riseEdgeDetected = output.get( ol ) && !output.get( ol - 1 );
if( riseEdgeDetected )
{
// check if edge meets threshold criteria
boolean niceRiseEdge = true;
// check that exists a long enough logic 1 at current position
// and long enough 0 before it
for( int rdl = 1; rdl < logicThreshold; rdl++ )
{
niceRiseEdge &= output.get( ol + rdl );
niceRiseEdge &= !output.get( ol - rdl - 1 );
}
if( niceRiseEdge )
{
niceRisingEdges++;
ol += logicThreshold * 2; // we know LOGIC_THRESHOLD bits ahead are all high
}else
{
shortRisingEdges++;
ol += logicThreshold; // we know current position is high
}
}
}
// 2) Now calculate the fitness for current chunk based on edge #s
// 2.1) Calculate fitness of this chunk based on valid rising edges only.
double thisChunksFitness = 1d / ( Math.abs( niceRisingEdges - periodsToTest / testChunks ) + 1d );
// 2.2) Calculate penalty due to short invalid rising edges
double shortRisingEdgesPenalty = 1d / ( shortRisingEdges * SHORT_PENALTY + 1d );
//double shortRisingEdgesPenalty = 1;
// 2.3) Add this chunk's fitness to the accumulated one
totalFitness += shortRisingEdgesPenalty * thisChunksFitness;
}
if( DebugLib.trcLogger.isLogging )
{
DebugLib.trcLogger.text( com.ibm.logging.IRecordType.TYPE_MISC_DATA, this.getClass().getName(), "getFitness", debugText.toString() );
}
return totalFitness / testChunks;
}
/** generates an array of inputs suitable for this experiment
* using default input sample separation.
*/
public SampleData[] generateInput()
{
SampleData[] rv = new SampleData[ 1 ];
rv[ 0 ] = new SampleData( period * periodsToTest / testChunks, testChunks );
return rv;
}
/** generates an array of inputs suitable for this experiment.
* @param inputSampleSeparation relative frequency of input to output samples. If this is n, then n outputs will be sampled for every change in inputs.
*/
public SampleData[] generateInput(int inputSampleSeparation)
{
return generateInput();
}
public int getNumOfInputs()
{
return 1;
}
public int getNumOfOutputs()
{
return 1;
}
public String toString()
{
String rv = "SimpleOscillatorExperiment with period = " + period;
return rv;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -