package parameters;
import java.lang.*;
import java.io.*;
import main.BetterTokenizer;
import affectors.Affector;
import main.GeneralInput;
/**
This class holds the value of a given parameter, its upper and lower bounds, and whether it should vary linearly or logarithmically.
To hold sets of parameters, use the ParameterSet class.
To hold the current state of the model, use the Parameters class.
Note that this class only works well after a model is loaded.
*/
public class Parameter extends Object {
/** The name of this parameter. Needs to be the same as the name of a parameter in the currently loaded model */
public String name;
/** The value of the parameter. */
public float value;
/** The lowest value this parameter can every have. */
public float upperBound;
/** The highest value this parameter can every have. */
public float lowerBound;
/** Can be either LINEAR or LOGARITHMIC */
public int variationMode;
public final static int LINEAR=0, LOGARITHMIC=1, NOT_SET=-1;
public Parameter() {
name=""; value=0.0f; upperBound=0.0f; lowerBound=0.0f; variationMode=LINEAR;
}
/**
This initializer is for use when reading from a file, where the creation of this
Parameter object will happen after the parameter name is already known.
*/
public Parameter(String n) {
name = n;
Parameter par = Affector.getParameter(name); // Copy from global copy of this parameter
if(par != null) {
value = par.value;
lowerBound = par.lowerBound;
upperBound = par.upperBound;
variationMode = par.variationMode;
}
}
public Parameter(String n, float v, float u, float l, int vM) {
name = n; value = v; upperBound = u; lowerBound = l; variationMode = vM;
}
public Parameter(Parameter p) {
this.name = new String(p.name);
this.value = p.value;
this.upperBound = p.upperBound;
this.lowerBound = p.lowerBound;
this.variationMode = p.variationMode;
}
public Parameter copy() {
return new Parameter(this);
}
/**
* This loadParameters calls the other one with need_all = true
*/
public void loadParameters(BetterTokenizer tokenizer) throws Exception {
loadParameters(tokenizer, true);
}
/**
* This function is for loading parameters from a file. It assumes that the data comes in the form
*
* value upper_bound lower_bound variation_mode
*
* If need_all is false, then only the value of the parameter needs to be present in the file
* otherwise, the value and the bounds need to be present. This function always ignores
* the variation mode in the file and assumes its the same as what's stored in Affector
* Note - this function will throw an exception for any parameter whose name is not found in Affector -
* - so it won't work if a model isn't loaded, or if the wrong model is loaded.
* Not sure if this is a good idea...
* Note that you must set the name of the parameter before calling this (by using appropriate constructor, for instance).
* Thus this function assumes that all values have proper defaults already (or will when I convince myself that doesn't break anything).
* @param need_all true means value, min, and max all must be in file or exception thrown. false means only value needs to be there (but others are read if present).
*/
public void loadParameters(BetterTokenizer tokenizer, boolean need_all) throws Exception {
if(!need_all) {
Parameter par = Affector.getParameter(name); // Modify from global copy of this parameter
if(par != null) {
value = par.value;
lowerBound = par.lowerBound;
upperBound = par.upperBound;
variationMode = par.variationMode;
}
}
//ELI 2/24/99 - made it so that everything is treated as unneeded sequentially, rather than
// only checking after value is loaded.
// If need_all is false, then the rest of the values are not required
// if they aren't here, just return - defaults were set above
int token = GeneralInput.nextToken(tokenizer);
if(!need_all)
if(token == BetterTokenizer.TT_EOL) return;
if(token != BetterTokenizer.TT_NUMBER)
throw new Exception ("Parameter " + name + "was not given a value");
value = (float)tokenizer.nval;
token = GeneralInput.nextToken(tokenizer);
if(!need_all)
if(token == BetterTokenizer.TT_EOL) return;
else if(token != BetterTokenizer.TT_NUMBER)
throw new Exception ("Parameter " + name + "was not given a lower bound");
lowerBound = (float)tokenizer.nval;
// If we get a lower bound, then we also better get an upper bound regardless of whether need_all is true
if(GeneralInput.nextToken(tokenizer) != BetterTokenizer.TT_NUMBER)
throw new Exception ("Parameter " + name + "was not given an upper bound");
upperBound = (float)tokenizer.nval;
token = GeneralInput.nextToken(tokenizer);
if(!need_all)
if(token == BetterTokenizer.TT_EOL) return;
if(token != BetterTokenizer.TT_WORD)
throw new Exception ("Parameter " + name + "was not given a range type");
setVariationMode(tokenizer.sval);
}
public String toString() { return toString(true); }
public String toString(boolean printAll) {
String pdesc = new String("&" + name + "\t" + value);
if(printAll) {
pdesc = pdesc + "\t";
pdesc = pdesc + String.valueOf(lowerBound);
pdesc = pdesc + "\t";
pdesc = pdesc + String.valueOf(upperBound);
pdesc = pdesc + "\t";
if(variationMode == LINEAR) {
pdesc = pdesc + "Linear";
} else pdesc = pdesc + "Logarithmic";
}
return pdesc;
}
public float getValue() { return value; }
public void setValue(float v) { value = v; }
public void setBounds(float l, float u) { upperBound = u; lowerBound = l; }
public void setVariationMode(int v) { variationMode = v; }
public void setVariationMode(String mode) throws Exception {
if(mode.equals("Linear")) variationMode = LINEAR;
else if(mode.equals("Logarithmic")) variationMode = LOGARITHMIC;
else {
throw new Exception("Variation mode " + mode + " for parameter " + name + ": does not compute!");
}
}
public int getVariationMode () { return variationMode; }
public String getName() { return name; }
}