001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021
022
023package org.biojava.bio.dp;
024
025import org.biojava.bio.dist.Distribution;
026import org.biojava.bio.symbol.Alphabet;
027import org.biojava.bio.symbol.FiniteAlphabet;
028import org.biojava.bio.symbol.IllegalAlphabetException;
029import org.biojava.bio.symbol.IllegalSymbolException;
030import org.biojava.utils.ChangeType;
031import org.biojava.utils.ChangeVetoException;
032import org.biojava.utils.Changeable;
033
034/**
035 * A markov model.
036 * <p>
037 * All probablities are in log space.
038 * <p>
039 * This interface models a subset of hidden markov models with an explicit start
040 * and end state. In principle, these can be combined together, so that a state
041 * within one model may be an entire model in its own right, wired via
042 * container->start and end->container. For the sample methods to work, the log
043 * scores must be probabilities (sum to 1).
044 */
045public interface MarkovModel extends Changeable {
046  /**
047   * Signals that the architecture of the model is changing.
048   * <p>
049   * For a transition creation, the changed field should be a two element
050   * array containing the source and destination states of the new transition,
051   * and the previous field should be null. Likewise for the removal of a
052   * transition, the previos should hold the array, and changed should be null.
053   */
054  public static final ChangeType ARCHITECTURE = new ChangeType(
055    "create or destroy a transition",
056    "org.biojava.bio.dp.MarkovModel",
057    "ARCHITECTURE"
058  );
059  
060  /**
061   * Signals that one or more parameters have altered.
062   * <p>
063   * If it is clear which parameter has changed, then this should be in the
064   * current and/or previous field. Otherwise, these should be null.
065   */
066  public static final ChangeType PARAMETER = new ChangeType(
067    "parameter altered",
068    "org.biojava.bio.dp.MarkovModel",
069    "PARAMETER"
070  );
071  
072  /**
073   * Alphabet that is emitted by the emission states.
074   */
075  Alphabet emissionAlphabet();
076
077  /**
078   * FiniteAlphabet of the states.
079   * <p>
080   * We are modeling a finite-state-machine, so there will be a finite set of
081   * states.
082   * <p>
083   * The MagicalState returned by getMagicalState is always contained
084   * within this as the start/end state.
085   *
086   * @return the alphabet over states
087   */
088  FiniteAlphabet stateAlphabet();
089  
090  /**
091   * The MagicalState for this model.
092   */
093  MagicalState magicalState();
094  
095  /**
096   * The number of heads on this model.
097   * <p>
098   * Each head consumes a single SymbolList. A single-head model just consumes/
099   * emits a single sequence. A two-head model performs alignment between two
100   * sequences (e.g. smith-waterman). Models with more heads do more interesting
101   * things.</p>
102   *
103   * <p><code>heads()</code> should equal <code>advance().length</code>.
104   *
105   * @return the number of heads in this model.
106   * @deprecated  use <code>advance().length</code>
107   */
108  int heads();
109  
110  /**
111   * The maximum advance for this model.
112   * <p>
113   * Each head consumes a single SymbolList. However, the states that advance
114   * through that SymbolList may emit more than one symbol at a time. This array
115   * give the maximum advance in each direction.
116   * </p>
117   *
118   * Be sure to return a new array each time this is called. This protects the
119   * internal state of the object from someone modifying the advance array.
120   * Be sure to update this as/when states modify their advance arrays and
121   * as/when states are added or removed
122   *
123   * @return the maximum advance of all states for all heads
124   */
125  int[] advance();
126  
127  /**
128   * Get a probability Distribution over the transition from 'source'. 
129   *
130   * @param source  the State currently occupied
131   * @return the probability Distribution over the reachable states
132   * @throws IllegalSymbolException if from is not a legal state
133   */
134  Distribution getWeights(State source)
135  throws IllegalSymbolException;
136
137  /**
138   * Set the probability distribution over the transitions from 'source'.
139   * <p>
140   * This should throw an IllegalAlphabetException if the source alphabet in
141   * 'dist' is not the same alphabet as returned by transitionsFrom(source).
142   *
143   * @param source  the source State
144   * @param dist    the new distribution over transitions from 'source'
145   * @throws IllegalSymbolException if source is not a state in this model
146   * @throws IllegalAlphabetException if the distribution has the wrong source
147   *         alphabet
148   * @throws ChangeVetoException if for any reason the distribution can't be
149   *         replaced at this time
150   */
151  void setWeights(State source, Distribution dist)
152  throws IllegalSymbolException, IllegalAlphabetException, ChangeVetoException;
153  
154  /**
155   * Returns the FiniteAlphabet of all states that have a transition from 'source'.
156   *
157   * @param source  the source State
158   * @return  a FiniteAlphabet of State objects that can reach from 'source'
159   */
160  FiniteAlphabet transitionsFrom(State source) throws IllegalSymbolException;
161  
162  /**
163   * Returns the FiniteAlphabet of all states that have a transition to 'dest'.
164   *
165   * @param dest  the destination state
166   * @return  a FiniteAlphabet of State objects that can reach 'dest'
167   */
168  FiniteAlphabet transitionsTo(State dest) throws IllegalSymbolException;
169
170  /**
171   * Returns wether a transition exists or not.
172   *
173   * @param from the transitin source
174   * @param to the transition destination
175   * @return true/false depending on wether this model has the transition
176   * @throws IllegalSymbolException if either from or to are not states in this
177   *         model
178   */
179  boolean containsTransition(State from, State to)
180  throws IllegalSymbolException;
181  
182  /**
183   * Makes a transition between two states legal.
184   * <p>
185   * This should inform each TransitionListener that a transition is to be
186   * created using preCreateTransition, and if none of the listeners fire a
187   * ChangeVetoException, it should create the transition, and then inform each
188   * TransitionListener with postCreateTransition.
189   *
190   * @param from  the State currently occupied
191   * @param to  the State to move to
192   * @throws IllegalSymbolException if either from or to are not legal states
193   * @throws ChangeVetoException if creating the transition is vetoed
194   */
195  void createTransition(State from, State to)
196  throws IllegalSymbolException, ChangeVetoException;
197   
198  /**
199   * Breaks a transition between two states legal.
200   * <p>
201   * This should inform each TransitionListener that a transition is to be
202   * broken using preDestroyTransition, and if none of the listeners fire a
203   * ChangeVetoException, it should break the transition, and then inform each
204   * TransitionListener with postDestroyTransition.
205   *
206   * @param from  the State currently occupied
207   * @param to  the State to move to
208   * @throws IllegalSymbolException if either from or to are not legal states
209   * @throws ChangeVetoException if breaking the transition is vetoed
210   */
211  void destroyTransition(State from, State to)
212  throws IllegalSymbolException, ChangeVetoException;
213
214  /**
215   * Adds a state to the model.
216   *
217   * @param newState  the state to add
218   * @throws IllegalSymbolException if the state is not valid or is a MagicalState
219   * @throws ChangeVetoException  if either the model does not allow states to
220   *         be added, or the change was vetoed
221   */
222  void addState(State newState)
223  throws IllegalSymbolException, ChangeVetoException;
224
225  /**
226   * Remove a state from the model.
227   * <p>
228   * States should not be removed untill they are involved in no transitions.
229   * This is to avoid producing corrupted models by accident.
230   *
231   * @param toGo  the state to remove
232   * @throws IllegalSymbolException if the symbol is not part of this model
233   *         or a MagicalState
234   * @throws IllegalTransitionException if the state is currently involved in
235   *         any transitions
236   * @throws ChangeVetoException  if either the model does not allow states to
237   *         be removed, or the change was vetoed
238   */
239  void removeState(State toGo)
240  throws IllegalTransitionException,
241  IllegalSymbolException, ChangeVetoException;
242}