离散事件模拟(java)

时间:2016-03-30 00:17:14

标签: java

我有两个类,Neuron和Synapse(突触有子类主要,次要)。当一个神经元的电压超过其阈值时,它会发射,但也会向所有突触发送一个脉冲。我创建了一种在电压> 1时创建事件的方法。阈。 我的问题是:如何创建一个事件来触发另一个类的对象事件? (我的代码给出了一个错误:不是封闭的类)如果需要,我可以发布我的代码。

import java.io.File;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.regex.Pattern;
import java.util.Scanner;

// Simulation classes
class Simulator {

    /**
     * Framework for discrete event simulation.
     */

    public interface Action {

        // actions contain the specific code of each event

        void trigger(float time);
    }

    private static class Event {

        public float time; // the time of this event
        public Action act; // what to do at that time
    }

    private static PriorityQueue<Event> eventSet
            = new PriorityQueue<Event>(
                    (Event e1, Event e2) -> Float.compare(e1.time, e2.time)
            );

    static void schedule(float time, Action act) {
        /**
         * Call schedule to make act happen at time. Users typically pass the
         * action as a lambda expression:
         * <PRE>
         *  Simulator.schedule(t,(float time)->method(params,time))
         * </PRE>
         */
        Event e = new Event();
        e.time = time;
        e.act = act;
        eventSet.add(e);
    }

    static void run() {
        /**
         * Call run after scheduling some initial events to run the simulation.
         */
        while (!eventSet.isEmpty()) {
            Event e = eventSet.remove();
            e.act.trigger(e.time);
        }
    }
}

// Utility classes
/**
 * Error reporting methods
 */
class Errors {

    static void fatal(String message) {
        System.err.println("Fatal error: " + message);
        System.exit(1);
    }

    static void warning(String message) {
        System.err.println("Error: " + message);
    }
}

/**
 * Input scanning support methods
 */
class ScanSupport {

    /**
     * Interface allowing error messages passed as lambda expressions
     */
    public interface ErrorMessage {

        abstract String myString();
    }

    /**
     * Force there to be a line end here, complain if not
     */
    static void lineEnd(Scanner sc, ErrorMessage message) {
        String skip = sc.nextLine();
        if (!"".equals(skip)) {
// Bug:  do we want to allow comments here
            Errors.warning(
                    message.myString()
                    + " -- expected a newline"
            );
        }
// Bug:  should we allow comments here?
// Bug:  what if sc.nextLine() was illegal (illegal state)
    }

    /* really private to nextName */
    private static final Pattern name = Pattern.compile("[A-Za-z]\\w*");

    /**
     * Get the next float, or complain if there isn't one
     */
    static String nextName(Scanner sc, ErrorMessage message) {
        if (sc.hasNext(name)) {
            return sc.next(name);
        } else {
            Errors.warning(
                    message.myString()
                    + " -- expected a name"
            );
            return null;
        }
    }

    /**
     * Get the next float, or complain if there isn't one
     */
    static float nextFloat(Scanner sc, ErrorMessage message) {
        if (sc.hasNextFloat()) {
            return sc.nextFloat();
        } else {
            Errors.warning(
                    message.myString()
                    + " -- expected a number"
            );
            return 99.99f;
        }
    }
}

// Simulation classes
/**
 * Neurons are joined by synapses
 *
 * @see Synapse
 */
class Neuron {

    String name; // name of this neuron

    public static class IllegalNameEx extends Exception {
    }

// default values below for errors with incompletely defined neurons
    private float threshold = 99.99f;// voltage at which the neuron fires
    public float voltage = 99.99f; // voltage at the given time
    private float time = 0.0f; // (see above)

    private LinkedList<Synapse> synapses; // the outputs of this neuron

// initializer
    public Neuron(Scanner sc) throws IllegalNameEx {
// scan and process one neuron
        String name = ScanSupport.nextName(
                sc,
                () -> "Neuron ???"
        );
        if (name == null) { // nextName() already reported syntax error
            sc.nextLine();
            throw new IllegalNameEx();
        }
        this.name = name;
        if ((NeuronNetwork.findNeuron(name) != null)
                || (NeuronNetwork.findSynapse(name) != null)) {
            Errors.warning(
                    "Neuron " + name
                    + " -- duplicate declaration"
            );
            sc.nextLine();
            throw new IllegalNameEx();
        }
        threshold = ScanSupport.nextFloat(
                sc,
                () -> Neuron.this.toString()
        );
        voltage = ScanSupport.nextFloat(
                sc,
                () -> Neuron.this.toString()
        );
        ScanSupport.lineEnd(
                sc,
                () -> Neuron.this.toString()
        );
    }

// other methods
    public String toString() {
        return (time + " "
                + "Neuron "
                + name);
    }

// simulation methods
    public void fireNeuron(float t) {
        if (this.voltage > this.threshold) {
            Simulator.schedule(
                    t,
                    (float time) -> this.voltageZero(time)
            );
            Simulator.schedule(
                    t,
                    (float time) -> Synapse.this.impulse(time)
            );
        }
    }

    public void voltageZero(float t) {
        voltage = 0.0f;
        System.out.println(this.toString());
    }
}

/**
 * Synapses come in several flavors
 *
 * @see Neuron
 * @see PrimarySynapse
 * @see SecondarySynapse
 */
abstract class Synapse {
// default values below for errors with incompletely defined synapses

    Neuron source; // source for this synapse
    Float delay = 99.99f;
    Float strength = 99.99f;
    String name = null; // name of this synapse, if it has one

    public static class IllegalNameEx extends Exception {
    }

// really private to Synapse initializer
    private static final Pattern noName = Pattern.compile("-");

// generic initializer
    static Synapse newSynapse(Scanner sc) throws IllegalNameEx {
// proxies for fields until we know the type of this synapse
        String myName = null;
        Neuron mySource = null;

// only one of the following proxies will be non-null
        Neuron myPrimaryDest = null;
        Synapse mySecondaryDest = null;

// the Synapse we're allocating
        Synapse mySynapse = null;
// scan and process one synapse
        if (sc.hasNext(noName)) { // unnamed synapse
            sc.next(noName);
        } else { // named synapse, process the name
            myName = ScanSupport.nextName(
                    sc,
                    () -> "Synapse ???"
            );
            if (myName == null) {
// nextName() already reported syntax error
                sc.nextLine();
                throw new IllegalNameEx();
            }
            if ((NeuronNetwork.findNeuron(myName) != null)
                    || (NeuronNetwork.findSynapse(myName) != null)) {
                Errors.warning(
                        "Synapse " + myName
                        + " -- duplicate declaration"
                );
                sc.nextLine();
                throw new IllegalNameEx();
            }
        }

// the following is needed because of limits of java lambda
        final String finalName = myName;

        String sourceName = ScanSupport.nextName(
                sc,
                () -> ("Synapse "
                + (finalName != null ? finalName : "-")
                + " ???")
        );
        String dstName = ScanSupport.nextName(
                sc,
                () -> ("Synapse "
                + (finalName != null ? finalName : "-")
                + " "
                + (sourceName != null ? sourceName : "---")
                + " ???")
        );
        mySource = NeuronNetwork.findNeuron(sourceName);
        myPrimaryDest = NeuronNetwork.findNeuron(dstName);
        if (myPrimaryDest == null) {
            mySecondaryDest = NeuronNetwork.findSynapse(dstName);
            mySynapse = new SecondarySynapse(mySecondaryDest);
        } else {
            mySynapse = new PrimarySynapse(myPrimaryDest);
        }

// the following is needed because of limits of java lambda
        final Synapse finalSynapse = mySynapse;

        finalSynapse.name = finalName;
        finalSynapse.source = mySource;
        finalSynapse.delay = ScanSupport.nextFloat(
                sc,
                () -> finalSynapse.toString()
        );
        finalSynapse.strength = ScanSupport.nextFloat(
                sc,
                () -> finalSynapse.toString()
        );
        ScanSupport.lineEnd(
                sc,
                () -> finalSynapse.toString()
        );

// check correctness of fields
        if ((sourceName != null) && (mySource == null)) {
            Errors.warning(
                    finalSynapse.toString()
                    + " -- no such source"
            );
        }
        if ((dstName != null)
                && (myPrimaryDest == null)
                && (mySecondaryDest == null)) {
            Errors.warning(
                    finalSynapse.toString()
                    + " -- no such destination"
            );
        }
        if (finalSynapse.delay < 0.0f) {
            Errors.warning(
                    finalSynapse.toString()
                    + " -- illegal negative delay"
            );
            finalSynapse.delay = 99.99f;
        }
        return finalSynapse;
    }

// other methods
    public abstract String toString();

// simulation
    public void impulse(float t) {
        Simulator.schedule(
                t + delay,
                (float time) -> this.synapseFire(time)
        );
    }

    public abstract void synapseFire(float t);
}

/**
 * Primary Synapses join neurons to neurons
 *
 * @see Neuron
 * @see Synapse
 */
class PrimarySynapse extends Synapse {

    Neuron destination;

    public PrimarySynapse(Neuron dst) {
// Called from Synapse.newSynapse() and nowhere else
// All the field initialization and checking is done there,
// except the following:
        destination = dst;
    }

// other methods
    public String toString() {
        return ("Synapse "
                + (name != null ? name : "-")
                + " "
                + (source != null ? source.name : "---")
                + " "
                + (destination != null ? destination.name : "---")
                + " " + delay + " " + strength);
    }
//simulation methods

    public void synapseFire(float t) {
// when a primary synapse is fired, destination neuron voltage is incremented by strength
        float oldVoltage = destination.voltage; // used to print old voltage vs new
        destination.voltage = destination.voltage + strength;
    }
}

/**
 * Secondary synapses join neurons to primary synapses
 *
 * @see Neuron
 * @see Synapse
 * @see PrimarySynapse
 */
class SecondarySynapse extends Synapse {

    PrimarySynapse destination;

    public SecondarySynapse(Synapse dst) {
// Called from Synapse.newSynapse() and nowhere else
// All the field initialization and checking is done there,
// except the following:

        if ((dst != null)
                && (dst instanceof SecondarySynapse)) {
            Errors.warning(
                    this.toString()
                    + " -- destination is a secondary synapse"
            );
            destination = null;
        } else {
            destination = (PrimarySynapse) dst;
        }
    }

// other methods
    public String toString() {
        return ("Synapse "
                + (name != null ? name : "-")
                + " "
                + (source != null ? source.name : "---")
                + " "
                + (destination != null ? destination.name : "---")
                + " " + delay + " " + strength);
    }
//simulation methods

    public void synapseFire(float t) {
// when a secondary fires, the destination synapses strength is incremented by strength
        float oldStrength = destination.strength; // used to print old strength vs new
        destination.strength = destination.strength + strength;
    }
}

/**
 * NeuronNetwork is the main class that builds the whole model
 *
 * @see Neuron
 * @see Synapse
 */
public class NeuronNetwork {

// the sets of all neurons and synapses
    static LinkedList<Neuron> neurons
            = new LinkedList<Neuron>();
    static LinkedList<Synapse> synapses
            = new LinkedList<Synapse>();

    /**
     * Look up s in neurons, find that Neuron if it exists return null if not.
     */
    public static Neuron findNeuron(String s) {
        /* special case added because scan-support can return null */
        if (s == null) {
            return null;
        }

        /* search the neuron list */
        for (Neuron n : neurons) {
            if (n.name.equals(s)) {
                return n;
            }
        }
        return null;
    }

    /**
     * Look up s in synapses, find that Synapse if it exists return null if not.
     */
    public static Synapse findSynapse(String s) {
        /* special case added because scan-support can return null */
        if (s == null) {
            return null;
        }

        /* search the synapse list */
        for (Synapse sy : synapses) {
            if ((sy.name != null) && (sy.name.equals(s))) {
                return sy;
            }
        }
        return null;
    }

    /**
     * Initialize the neuron network by scanning its description
     */
    static void initializeNetwork(Scanner sc) {
        while (sc.hasNext()) {
            String command = sc.next();
            if ("neuron".equals(command)) {
                try {
                    neurons.add(new Neuron(sc));
                } catch (Neuron.IllegalNameEx e) {
                }
            } else if ("synapse".equals(command)) {
                try {
                    synapses.add(Synapse.newSynapse(sc));
                } catch (Synapse.IllegalNameEx e) {
                }
            } else {
                Errors.warning(command + " -- what is that");
                sc.nextLine();
            }
        }
    }

    /**
     * Print out the neuron network from the data structure
     */
    static void printNetwork() {
        for (Neuron n : neurons) {
            System.out.println(n.toString());
        }
        for (Synapse s : synapses) {
            System.out.println(s.toString());
        }
    }

    /**
     * Main program
     *
     * @see initializeNetwork
     * @see printNetwork
     */
    public static void main(String[] args) {
        if (args.length < 1) {
            Errors.fatal("missing file name");
        }
        if (args.length > 1) {
            Errors.fatal("too many arguments");
        }
        try {
            initializeNetwork(new Scanner(new File(args[0])));
        } catch (FileNotFoundException e) {
            Errors.fatal("file not found: " + args[0]);
        }
        printNetwork();
    }
}

0 个答案:

没有答案