⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simpleoscillatorexperiment.java

📁 Java遗传算法库
💻 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 + -