-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
created a parameter database that uses JSON input. Tested but not use…
…d yet.
- Loading branch information
1 parent
f7ce7f3
commit b541bca
Showing
8 changed files
with
674 additions
and
41 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
part of lancaster.model; | ||
|
||
/** | ||
* sometimes the user needs a number, but the JSON field is actually a map. The number | ||
* generator is supposed to turn it into a number | ||
*/ | ||
typedef num NumberGenerator(JsonObject leaf, Random random); | ||
|
||
|
||
|
||
final NumberGenerator DEFAULT_UNIFORM = (JsonObject leaf,Random random) | ||
{ | ||
assert(leaf.type == "uniform"); | ||
//read max and min from the list! | ||
num maximum= leaf["max"]; | ||
num minimum= leaf["min"]; | ||
|
||
return random.nextDouble() * (maximum-minimum) + minimum; | ||
}; | ||
|
||
|
||
|
||
final NumberGenerator DEFAULT_NORMAL = (JsonObject leaf,Random random) | ||
{ | ||
|
||
//here I use the ratio-of-uniforms method | ||
//see here: http://stackoverflow.com/questions/13001485/implementing-the-ratio-of-uniforms-for-normal-distribution-in-c | ||
assert(leaf.type == "normal"); | ||
//read the two parameters from the list | ||
num mu= leaf.mean; | ||
num sigma= leaf.sigma; | ||
|
||
while(true) | ||
{ | ||
double u=random.nextDouble(); | ||
double v=1.7156*(random.nextDouble()-0.5); | ||
double x=u-0.449871; | ||
double y=v.abs()+0.386595; | ||
double q=x*x+y*(0.19600*y-0.25472*x); | ||
if(!(q>0.27597 && (q>0.27846 || v*v>-4*log(u)*u*u))) | ||
return mu + sigma * (v/u); | ||
} | ||
|
||
}; | ||
|
||
|
||
/** | ||
* random number generator that chooses at random from a list of numbers | ||
*/ | ||
final NumberGenerator DEFAULT_EMPIRICAL= (JsonObject leaf,Random random) | ||
{ | ||
|
||
//here I use the ratio-of-uniforms method | ||
//see here: http://stackoverflow.com/questions/13001485/implementing-the-ratio-of-uniforms-for-normal-distribution-in-c | ||
assert(leaf.type == "empirical"); | ||
//read the two parameters from the list | ||
List<num> sample = leaf.sample; | ||
assert(sample.length > 0); | ||
|
||
|
||
return sample.elementAt(random.nextInt(sample.length)); | ||
|
||
|
||
|
||
|
||
|
||
|
||
}; | ||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
part of lancaster.model; | ||
|
||
|
||
/** | ||
* Given a json file with all the parameters it organizes it in a simple database. Whatever else is in the parameters, | ||
* "seed" is reserved and used as seed for the randomizer. If "seed" doesn't exist in JSON or is not a | ||
* number then the current time will be used as seed | ||
* | ||
* a facade for a JsonObject tree; I don't let JsonObject out by itself mostly so I can keep a tight log | ||
* on what comes out and in. | ||
*/ | ||
class ParameterDatabase | ||
{ | ||
|
||
|
||
final JsonObject _root; | ||
|
||
|
||
final Map<String,NumberGenerator> _generators = new Map(); | ||
|
||
|
||
Random random; | ||
|
||
|
||
/** | ||
* navigate to [address]; returns null if the address is invalid | ||
*/ | ||
ParameterDatabase(String json): | ||
_root = new JsonObject.fromJsonString(json) | ||
{ | ||
|
||
Object seedParameter = _root["seed"]; | ||
num seed; | ||
if(seedParameter == null || !(seedParameter is num)) | ||
seed = new DateTime.now().millisecondsSinceEpoch; | ||
else | ||
seed = seedParameter; | ||
random = new Random(seed.toInt()); | ||
|
||
//add default generators | ||
_generators["normal"] = DEFAULT_NORMAL; | ||
_generators["uniform"] = DEFAULT_UNIFORM; | ||
_generators["empirical"] = DEFAULT_EMPIRICAL; | ||
|
||
} | ||
/** | ||
* get whatever is at [address]. null if the address is invalid | ||
*/ | ||
Object _getFieldAt(List<String> address) | ||
{ | ||
Object leaf = _root; | ||
for(String path in address) | ||
{ | ||
leaf = leaf[path]; | ||
//if the path doesn't exist, return null | ||
if(leaf == null) | ||
return null; | ||
} | ||
return leaf; | ||
} | ||
|
||
/** | ||
* navigate to [address]; returns null if the address is invalid | ||
*/ | ||
Object _getFieldAtPath(String address) | ||
{ | ||
|
||
return _getFieldAt(address.split(".")); | ||
|
||
} | ||
|
||
Object _lookup(String fieldName, String bestPath, String fallbackPath) | ||
{ | ||
//todo log | ||
|
||
String address = bestPath.isEmpty ? fieldName : "$bestPath.$fieldName"; | ||
Object parameter =_getFieldAtPath(address); | ||
if(parameter == null && fallbackPath != null) | ||
{ | ||
address = "$fallbackPath.$fieldName"; | ||
parameter =_getFieldAtPath(address); | ||
} | ||
return parameter; | ||
} | ||
|
||
/** | ||
* get the parameter as a string, if possible. If you are looking for the parameter in : <br> | ||
* strategy1.strategy2.parameter <br> | ||
* and if you don't find it then look in: <br> | ||
* strategy3.parameter <br> | ||
* then [fieldname] would be "parameter", [bestPath] would be "strategy1.strategy2" and [fallbackPath] would be "strategy3" | ||
* Throws an exception if it's not in either. Throws also an exception if the parameter is not a string but rather a map | ||
*/ | ||
String getAsString(String fieldName, String bestPath, [String fallbackPath=null]) | ||
{ | ||
|
||
Object parameter = _lookup(fieldName,bestPath,fallbackPath); | ||
|
||
if(parameter ==null) | ||
throw new Exception("Couldn't find the field neither as $bestPath.$fieldName nor $fallbackPath.$fieldName"); | ||
|
||
if(parameter is JsonObject) | ||
throw new Exception("The parameter is a map, not a string! ${parameter.toString()}"); | ||
|
||
return parameter.toString(); | ||
|
||
|
||
} | ||
|
||
|
||
/** | ||
* if you need a number but you got a map it might be a random parameter. Check if it has a type and if so feed it to the | ||
* randomizer | ||
*/ | ||
num _generateNumber(JsonObject parameter) | ||
{ | ||
|
||
String type = parameter["type"]; | ||
if(type == null) | ||
throw new Exception(" you are trying to turn $parameter into a number.It iss neither a number nor has a type to randomize"); | ||
|
||
NumberGenerator generator = _generators[type]; | ||
|
||
if(generator == null) | ||
throw new Exception("types of randomizers known: ${_generators.keys} , $type isn't one of them!"); | ||
|
||
return generator(parameter,random); | ||
|
||
|
||
|
||
} | ||
|
||
|
||
|
||
/** | ||
* get the parameter as a number; If the field is a number, then it is returned immediately; if it is a map, it is fed to the number | ||
* generator associated with its "type" field. <br> | ||
* If you are looking for the parameter in : <br> | ||
* strategy1.strategy2.parameter <br> | ||
* and if you don't find it then look in: <br> | ||
* strategy3.parameter <br> | ||
* then [fieldname] would be "parameter", [bestPath] would be "strategy1.strategy2" and [fallbackPath] would be "strategy3" | ||
* Throws an exception if it's not in either. Throws also an exception if the parameter is not a string but rather a map | ||
*/ | ||
num getAsNumber(String fieldName, String bestPath, [String fallbackPath=null]) | ||
{ | ||
|
||
Object parameter = _lookup(fieldName,bestPath,fallbackPath); | ||
|
||
if(parameter ==null) | ||
throw new Exception("Couldn't find the field neither as $bestPath.$fieldName nor $fallbackPath.$fieldName"); | ||
|
||
if(parameter is JsonObject) | ||
return _generateNumber(parameter); | ||
|
||
if(parameter is String) | ||
return num.parse(parameter); | ||
|
||
return parameter; | ||
|
||
|
||
} | ||
|
||
|
||
/** | ||
* set path.fieldName to value. Over-writes with no mercy. [path] must exists, even if [fieldname] doesn't | ||
*/ | ||
void setField(String fieldName, String path, Object value ) | ||
{ | ||
JsonObject json = _getFieldAtPath(path); | ||
json[fieldName] = value; | ||
|
||
} | ||
|
||
/** | ||
* set path.fieldName to json. [path] must exists, even if [fieldname] doesn't | ||
*/ | ||
void setFieldToJson(String fieldName, String path, String jsonValue ) | ||
{ | ||
JsonObject json = _getFieldAtPath(path); | ||
json[fieldName] = new JsonObject.fromJsonString(jsonValue); | ||
|
||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.