@@ -10,10 +10,10 @@ def __init__(
1010 X0 : int = 30 ,
1111 Y0 : int = 1 ,
1212 T : int | None = 20 ,
13- subsample : int = 10 ,
13+ subsample : int | str = "original" ,
1414 flatten : bool = True ,
1515 obs_noise : float = 0.1 ,
16- dt : float = None ,
16+ dt : float = 0.1 ,
1717 rng : np .random .Generator = None ,
1818 ):
1919 """Lotka Volterra simulated benchmark.
@@ -27,14 +27,17 @@ def __init__(
2727 Initial number of predator species.
2828 T: int, optional, default: 20
2929 The duration (time horizon) of the simulation.
30- subsample: int or None, optional, default: 10
30+ subsample: int, str or None, optional, default: 'original'
3131 The number of evenly spaced time points to return.
3232 If None, no subsampling will be performed and all T timepoints will be returned.
33+ If 'original', the original benchmark task subsampling of 20 points is used.
3334 flatten: bool, optional, default: True
3435 A flag to indicate whether a 1D (`flatten=True`) or 2D (`flatten=False`)
3536 representation of the simulated data is returned.
3637 obs_noise: float, optional, default: 0.1
3738 The standard deviation of the log-normal likelihood.
39+ dt: float, optional, default: 0.1
40+ The time step size for the ODE solver.
3841 rng: np.random.Generator or None, optional, default: None
3942 An optional random number generator to use.
4043 """
@@ -95,21 +98,23 @@ def observation_model(self, params: np.ndarray) -> np.ndarray:
9598 # Unpack parameter vector into scalars
9699 alpha , beta , gamma , delta = params
97100
98- # Prepate time vector between 0 and T of length T
99- t_vec = np .linspace (0 , self .T , int ( 1 / self .dt ) )
101+ # Prepare time vector between 0 and T of length T
102+ t_vec = np .arange (0 , self .T + self . dt , self .dt )
100103
101104 # Integrate using scipy and retain only infected (2-nd dimension)
102105 pp = odeint (self ._deriv , x0 , t_vec , args = (alpha , beta , gamma , delta ))
103106
104107 # Subsample evenly the specified number of points, if specified
105- if self .subsample is not None :
108+ if self .subsample == "original" :
109+ pp = pp [::21 ]
110+ elif self .subsample is not None :
106111 pp = pp [:: (self .T // self .subsample )]
107112
108- # Ensure minimum count is 0, which will later pass by log(0 + 1)
109- pp [ pp < 0 ] = 0.0
113+ # Ensure minimum count is 0
114+ pp = np . clip ( pp , a_min = 1e-10 , a_max = 10000.0 )
110115
111116 # Add noise, decide whether to flatten and return
112- x = self .rng .lognormal (np . log1p ( pp ) , sigma = self .obs_noise )
117+ x = self .rng .lognormal (pp , sigma = self .obs_noise )
113118 if self .flatten :
114119 return x .flatten ()
115120 return x
0 commit comments