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    }