package LBJ2.classify;
import LBJ2.learn.Lexicon;
import LBJ2.util.ByteString;
import LBJ2.util.ExceptionlessInputStream;
import LBJ2.util.ExceptionlessOutputStream;
/**
* A discrete feature takes on one value from a set of discontinuous values.
* The set of values that a given <code>DiscreteFeature</code> may take is
* defined in the <code>Classifier</code> that produced the feature.
*
* @author Nick Rizzolo
**/
public abstract class DiscreteFeature extends Feature
{
/** Convient access to a common allowable value set. */
public static final String[] BooleanValues = { "false", "true" };
/** Index into the set of allowable values corresponding to this value. */
protected short valueIndex;
/** The total number of allowable values for this feature. */
protected short totalValues;
/**
* For internal use only.
*
* @see Feature#readFeature(ExceptionlessInputStream)
**/
DiscreteFeature() { }
/**
* Sets the identifier, value, value index, and total allowable values.
*
* @param p The new discrete feature's package.
* @param c The name of the classifier that produced this feature.
* @param vi The index corresponding to the value.
* @param t The total allowable values for this feature.
**/
DiscreteFeature(String p, String c, short vi, short t) {
super(p, c);
valueIndex = vi;
totalValues = t;
}
/**
* Determines if this feature is discrete.
*
* @return <code>true</code> iff this is discrete.
**/
public boolean isDiscrete() { return true; }
/**
* Returns the index in the generating classifier's value list of this
* feature's value.
*
* @return A non-negative integer index, or -1 if this feature doesn't have
* a value list.
**/
public short getValueIndex() { return valueIndex; }
/**
* Returns the total number of values this feature might possibly be set
* to.
*
* @return Some integer greater than 1 iff this feature is a discrete
* feature with a specified value list, and 0 otherwise.
**/
public short totalValues() { return totalValues; }
/**
* Returns the strength of this feature if it were to be placed in a
* mathematical vector space.
**/
public double getStrength() { return totalValues == 2 ? valueIndex : 1; }
/**
* Create a feature representing the conjunction of this feature with the
* given argument feature.
*
* @param f The feature to conjunct with.
* @param c The classifier producing the resulting feature.
* @return A feature representing the conjunction of this feature and
* <code>f</code>.
**/
public Feature conjunction(Feature f, Classifier c) {
return f.conjunctWith(this, c);
}
/**
* Create a feature representing the conjunction of this feature with the
* given argument feature.
*
* @param f The feature to conjunct with.
* @param c The classifier producing the resulting feature.
* @return A feature representing the conjunction of this feature and
* <code>f</code>.
**/
protected Feature conjunctWith(DiscreteFeature f, Classifier c) {
return new DiscreteConjunctiveFeature(c, f, this);
}
/**
* Writes a complete binary representation of the feature.
*
* @param out The output stream.
**/
public void write(ExceptionlessOutputStream out) {
super.write(out);
out.writeShort(valueIndex);
out.writeShort(totalValues);
}
/**
* Reads the representation of a feaeture with this object's run-time type
* from the given stream, overwriting the data in this object.
*
* @param in The input stream.
**/
public void read(ExceptionlessInputStream in) {
super.read(in);
valueIndex = in.readShort();
totalValues = in.readShort();
}
/**
* Writes a binary representation of the feature intended for use by a
* lexicon, omitting redundant information when possible.
*
* @param out The output stream.
* @param lex The lexicon out of which this feature is being written.
* @param c The fully qualified name of the assumed class. The runtime
* class of this feature won't be written if it's equivalent to
* <code>c</code>.
* @param p The assumed package string. This feature's package string
* won't be written if it's equivalent to <code>p</code>.
* @param g The assumed classifier name string. This feature's
* classifier name string won't be written if it's equivalent
* to <code>g</code>.
* @param si The assumed identifier as a string. If this feature has a
* string identifier, it won't be written if it's equivalent to
* <code>si</code>.
* @param bi The assumed identifier as a byte string. If this feature
* has a byte string identifier, it won't be written if it's
* equivalent to <code>bi</code>.
* @return The name of the runtime type of this feature.
**/
public String lexWrite(ExceptionlessOutputStream out, Lexicon lex, String c,
String p, String g, String si, ByteString bi) {
String result = super.lexWrite(out, lex, c, p, g, si, bi);
out.writeShort(valueIndex);
out.writeShort(totalValues);
return result;
}
/**
* Reads the representation of a feature with this object's run-time type
* as stored by a lexicon, overwriting the data in this object.
*
* <p> This method is appropriate for reading features as written by
* {@link #lexWrite(ExceptionlessOutputStream,Lexicon,String,String,String,String,ByteString)}.
*
* @param in The input stream.
* @param lex The lexicon we are reading in to.
* @param p The assumed package string. If no package name is given in
* the input stream, the instantiated feature is given this
* package.
* @param g The assumed classifier name string. If no classifier name
* is given in the input stream, the instantiated feature is
* given this classifier name.
* @param si The assumed identifier as a string. If the feature being
* read has a string identifier field and no identifier is
* given in the input stream, the feature is given this
* identifier.
* @param bi The assumed identifier as a byte string. If the feature
* being read has a byte string identifier field and no
* identifier is given in the input stream, the feature is
* given this identifier.
**/
public void lexRead(ExceptionlessInputStream in, Lexicon lex, String p,
String g, String si, ByteString bi) {
super.lexRead(in, lex, p, g, si, bi);
valueIndex = in.readShort();
totalValues = in.readShort();
}
}