-
Notifications
You must be signed in to change notification settings - Fork 3
Description
The documented intention for the Proportional initializer is that you can provide either an NxC-shaped array OR a C-shaped array for the ratios argument. In the case of a C-shaped input, this should be broadcast to NxC (where the input is duplicated across the rows, the N-axis). This mostly works as expected except for the special case where N is equal to C (there are the same number of nodes as IPM compartments). The broadcasting happens in the wrong direction (across the C-axis), which eventually raises an error or returns unexpected results depending on the values used.
We should make sure to explicitly interpret 1-dimensional inputs as C-values when broadcasting.
While we're at it, the error messaging around invalid ratios forms could be improved.
Example 1: raises an error
from epymorph.kit import *
init.Proportional(ratios=[0.9, 0.1, 0.0]).with_context(
scope=CustomScope(["A", "B", "C"]),
ipm=ipm.SIRS(),
params={
"population": [100, 200, 300],
},
).evaluate()---------------------------------------------------------------------------
InitError Traceback (most recent call last)
Cell In[3], line 9
1 from epymorph.kit import *
3 init.Proportional([0.9, 0.1, 0.0]).with_context(
4 scope=CustomScope(["A", "B", "C"]),
5 ipm=ipm.SIRS(),
6 params={
7 "population": [100, 200, 300],
8 },
----> 9 ).evaluate()
File ~/Workspaces/Epymorph/epymorph/simulation.py:528, in SimulationFunctionClass.__new__.<locals>.evaluate(self, *args, **kwargs)
526 @functools.wraps(orig_evaluate)
527 def evaluate(self, *args, **kwargs):
--> 528 result = orig_evaluate(self, *args, **kwargs)
529 self.validate(result)
530 return result
File ~/Workspaces/Epymorph/epymorph/initializer.py:211, in Proportional.evaluate(self)
209 if np.any(row_sums <= 0):
210 err = "One or more rows sum to zero or less."
--> 211 raise InitError(err)
213 pop = self.data(_POPULATION_ATTR)
214 result = pop[:, np.newaxis] * (ratios / row_sums[:, np.newaxis])
InitError: One or more rows sum to zero or less.
Example 2: no error but bad results
from epymorph.kit import *
init.Proportional(ratios=[0.5, 0.3, 0.2]).with_context(
scope=CustomScope(["A", "B", "C"]),
ipm=ipm.SIRS(),
params={
"population": [100, 200, 300],
},
).evaluate()array([[ 33, 33, 33],
[ 67, 67, 67],
[100, 100, 100]])