Closed WJSchakel closed 3 months ago
TJunctionDemo
has 2 scenarios implemented:
<ots:ShortestRouteMix Id="S" GtuType="NL.CAR">
<ots:ShortestRoute Weight="{sw}" Id="SW" />
<ots:ShortestRoute Weight="{1.0 - sw}" Id="SE" />
</ots:ShortestRouteMix>
...
<ots:Scenarios>
<ots:DefaultInputParameters>
<ots:Fraction Id="{sw}">0.5</ots:Fraction>
</ots:DefaultInputParameters>
<ots:Scenario Id="1" />
<ots:Scenario Id="2">
<ots:InputParameters>
<ots:Fraction Id="{sw}">0.05</ots:Fraction>
</ots:InputParameters>
</ots:Scenario>
</ots:Scenarios>
The first scenario implements no non-default value. The scenarios can be run using the line: new XmlParser(this.network).setUrl(xmlURL).setScenario("1").build();
in TJunctionDemo
for scenario 1
.
Three issues remain:
ExpressionType
parses the above XML examples ad-hoc.<ots:Fraction>
results in a double
. This is also the data type required in Weight
where the parameter {sw}
is used. DJUTILS eval however only supports DJUNITS types (including Dimensionless
).The method ExpressionType.get()
now reads:
public T get(final Eval eval)
{
return this.expression == null ? this.value : this.toType.apply(eval.evaluate(this.expression));
}
Eval eval
is created at the start of parsing XML and contains the input parameters (as RetrieveValue
object). It is given fourth through the various parser functions. The local field Function<Object, T> toType
is used to convert output of the evaluator to the right value type. This is defined depending on the subclass of ExpressionType
as:
ColorType
, EstimationType
and SpeedUnitType
) are unchanged. Their call to super
in the constructor uses constructors of ExpressionType
that use a standard static function that keeps expression output as is:
Function<Object, ?> AS_IS = (o) -> o;
AccelerationType
, LengthType
and SpeedType
) define a specific static function, and give this in the super
call in their constructors. For example for acceleration:
Function<Object, Acceleration> TO_TYPE = (o) -> Acceleration.instantiateSI(((Number) o).doubleValue())
Note that this will neatly convert any Number
including: Acceleration
, Dimensionless
and Double
.DoubleType
, IntegerType
and LongType
do something similar for any Number
, calling their respectively appropriate method of Number
. For example for IntegerType
:
Function<Object, Integer> TO_TYPE = (o) -> ((Number) o).intValue()
There are several issues with random input parameters.
1. Circular dependency Circular dependency remains an issue. We have the following circular dependency:
random streams > # replications > input parameters > random streams
Note that # replications is something one would quite likely want to vary between scenarios. An expression (using input parameters) is a good way to do this. Alternatively we could specify # replications with each scenario as a field. However that makes things unclear. The # replications is then defined in both Scenario and Run. Moreover, this is typically Run information.
2. Randomness before and during simulation Random input variables are randomness before simulation. Random streams are designed to introduce randomness during simulation. Having randomness in both phases is overly complex and confusing.
3. What replication to use?
Each replication of a scenario has its individual seed. Suppose we have a stream default
with 3 different seeds for 3 replications. If random input parameters are also assigned to stream default
, which should they use?
Note that XML parsing results in a single scenario, ready for multiple replications where only the random seeds are different. We do not parse per run, but per scenario.
4. Ambiguity How should random input parameters behave? There are several options:
The latter option is not possible with our current way of parsing. We could change that, but there seems to be little point to that. This is essentially randomness during simulation, so it is better located as randomness in the behavior of simulation components.
The first option essentially amounts to a fixed value. Why not just specify that, at some random value determined externally?
The middle option remains. To me this is insufficient reason against all the complexity, ambiguity, and work-arounds for circular dependencies.
Suggestion My suggestion would be to scrap random input parameters. It keeps randomness neatly on the simulation side, rather than also on the input side. It will be difficult to communicate to users how random input parameters behave. And the input in to the editor will become more complicated and redundant.
@averbraeck , @OTSim what do you think?
In light of the above we will not include random input parameters.
Expressions need input parameters, which are currently not parsed. In order to know which input parameters to use, the parser needs a scenario name. The parser already has various methods bases on different input. This is all static. The class will become instantiable with a factory design pattern.