    001    package calhoun.analysis.crf;
    002
    003    import java.io.Serializable;
    004    import java.util.List;
    005
    006    import calhoun.util.DenseBooleanMatrix2D;
    007
    008    /** a useful base class for creating model beans.  Defines internal Node and Edge class that can be used to define a hidden state model for the CRF.
    009     * The actual state diagram could be implemented through a derived class or through setup of the model in the XML model file.  Because XML configuration of
    010     * a state model is verbose and because the state diagram is central to most models, we recommend using a derived class to set up the model, as we have
    011     * done with gene calling.
    012     */
    013    public class BeanModel extends CompositeFeatureManager implements ModelManager {
    014            private static final long serialVersionUID = -6641426879906871691L;
    015
    016            /** a hidden state.  Each state has a name and states are numbered beginning from 0.
    017             * The state index is used when the engine predicts hidden sequences.
    018             */
    019            public static class Node implements Serializable {
    020                    private static final long serialVersionUID = 1550966522391566799L;
    021
    022                    int index;
    023                    String name;
    024
    025                    public Node() { }
    026                    public Node(int index, String name) {
    027                            this.index = index;
    028                            this.name = name;
    029                    }
    030
    031                    public int getIndex() { return index; }
    032                    public void setIndex(int index) { this.index = index; }
    033                    public String getName() { return name; }
    034                    public void setName(String name) { this.name = name; }
    035            }
    036
    037            /** an edge in the hidden state diagram.  Presence of an edge indicates that a transition between two states is valid. *
    038             */
    039            public static class Edge implements Serializable {
    040                    private static final long serialVersionUID = 5429589777288279645L;
    041
    042                    Node from;
    043                    Node to;
    044
    045                    public Edge() { }
    046                    public Edge(Node from, Node to) {
    047                            this.from = from;
    048                            this.to = to;
    049                    }
    050
    051                    public Node getFrom() { return from; }
    052                    public void setFrom(Node from) { this.from = from; }
    053                    public Node getTo() { return to; }
    054                    public void setTo(Node to) { this.to = to; }
    055            }
    056
    057            protected List<Node> nodes;
    058            protected List<Edge> edges;
    059
    060            /** sets the list of hidden states in this model.  This will usually be called by a derived class
    061             * or by the Spring configuration.
    062             * @param nodes the list of hidden states in the model
    063             */
    064            public void setNodes(List<Node> nodes) {
    065                    this.nodes = nodes;
    066            }
    067
    068            /** sets the list of legal state transitions in this model.  This will usually be called by a derived class
    069             * or by the Spring configuration.
    070             * @param edges the list of valid state transitions in the model
    071             */
    072            public void setEdges(List<Edge> edges) {
    073                    this.edges= edges;
    074            }
    075
    076            public int getNumStates() {
    077                    return nodes.size();
    078            }
    079
    080            public String getStateName(int state) {
    081                    return nodes.get(state).name;
    082            }
    083
    084            public int getStateIndex(String name) {
    085                    for(Node n : nodes) {
    086                            if(n.name.equals(name))
    087                                    return n.index;
    088                    }
    089                    throw new IllegalArgumentException();
    090            }
    091
    092            public DenseBooleanMatrix2D getLegalTransitions() {
    093                    int nStates = getNumStates();
    094                    DenseBooleanMatrix2D ret = new DenseBooleanMatrix2D(nStates, nStates);
    095                    for(Edge e : edges) {
    096                            ret.setQuick(e.from.index, e.to.index, true);
    097                    }
    098                    return ret;
    099            }
    100    }