Skip to content

Commit

Permalink
Cleanups and minor fixes:
Browse files Browse the repository at this point in the history
Raising exception from ??? in ipm exec.
Remove unused mm_exec function.
Remove namespace function that was moved to code.py.
Fix devlog import for dtypes refactor.
  • Loading branch information
Tyler Coles committed May 23, 2024
1 parent 815c3b0 commit 8104bae
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 128 deletions.
11 changes: 6 additions & 5 deletions doc/devlog/2023-08-17.ipynb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions epymorph/engine/ipm_exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def _events(self, node: int, tick: Tick, effective_pop: NDArray[SimDType]) -> ND
raise IpmSimNaNException(
self._get_zero_division_args(
rate_args, node, tick, t)
)
) from None
# check for < 0 rate, throw error in this case
if rate < 0:
raise IpmSimLessThanZeroException(
Expand All @@ -204,7 +204,7 @@ def _events(self, node: int, tick: Tick, effective_pop: NDArray[SimDType]) -> ND
raise IpmSimNaNException(
self._get_zero_division_args(
rate_args, node, tick, t)
)
) from None
# check for < 0 base, throw error in this case
if rate < 0:
raise IpmSimLessThanZeroException(
Expand Down
69 changes: 0 additions & 69 deletions epymorph/engine/mm_exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,72 +197,3 @@ def apply(self, world: World, tick: Tick) -> None:

self.on_movement_finish.publish(
OnMovementFinish(tick.index, tick.day, tick.step, total))

def _travelers(self, clause: TravelClause, tick: Tick, local_cohorts: NDArray[SimDType]) -> NDArray[SimDType]:
"""
Calculate the number of travelers resulting from this movement clause for this tick.
This evaluates the requested number movers, modulates that based on the available movers,
then selects exactly which individuals (by compartment) should move.
Returns an (N,N,C) array; from-source-to-destination-by-compartment.
"""
_, N, C, _ = self._ctx.dim.TNCE

clause_movers = clause.requested(self._ctx, self._predef, tick)
np.fill_diagonal(clause_movers, 0)
clause_sum = clause_movers.sum(axis=1, dtype=SimDType)

available_movers = local_cohorts * self._clause_masks[clause]
available_sum = available_movers.sum(axis=1, dtype=SimDType)

# If clause requested total is greater than the total available,
# use mvhg to select as many as possible.
if not np.any(clause_sum > available_sum):
throttled = False
requested_movers = clause_movers
requested_sum = clause_sum
else:
throttled = True
requested_movers = clause_movers.copy()
for src in range(N):
if clause_sum[src] > available_sum[src]:
requested_movers[src, :] = self._ctx.rng.multivariate_hypergeometric(
colors=requested_movers[src, :],
nsample=available_sum[src]
)
requested_sum = requested_movers.sum(axis=1, dtype=SimDType)

# The probability a mover from a src will go to a dst.
requested_prb = row_normalize(requested_movers, requested_sum, dtype=SimDType)

travelers_cs = np.zeros((N, N, C), dtype=SimDType)
for src in range(N):
if requested_sum[src] == 0:
continue

# Select which individuals will be leaving this node.
mover_cs = self._ctx.rng.multivariate_hypergeometric(
available_movers[src, :],
requested_sum[src]
).astype(SimDType)

# Select which location they are each going to.
# (Each row contains the compartments for a destination.)
travelers_cs[src, :, :] = self._ctx.rng.multinomial(
mover_cs,
requested_prb[src, :]
).T.astype(SimDType)

self.on_movement_clause.publish(
OnMovementClause(
tick.index,
tick.day,
tick.step,
clause.name,
clause_movers,
travelers_cs,
requested_sum.sum(),
throttled,
)
)

return travelers_cs
52 changes: 0 additions & 52 deletions epymorph/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,55 +238,3 @@ def enable_logging(filename: str = 'debug.log', movement: bool = True) -> None:
logging.basicConfig(filename=filename, filemode='w')
if movement:
logging.getLogger('movement').setLevel(logging.DEBUG)


def epymorph_namespace() -> dict[str, Any]:
"""
Make a safe namespace for user-defined functions,
including utilities that functions might need in epymorph.
"""
return {
'SimDType': SimDType,
# our utility functions
'pairwise_haversine': pairwise_haversine,
'row_normalize': row_normalize,
# numpy namespace
'np': ImmutableNamespace({
# numpy utility functions
'array': partial(np.array, dtype=SimDType),
'zeros': partial(np.zeros, dtype=SimDType),
'zeros_like': partial(np.zeros_like, dtype=SimDType),
'ones': partial(np.ones, dtype=SimDType),
'ones_like': partial(np.ones_like, dtype=SimDType),
'full': partial(np.full, dtype=SimDType),
'arange': partial(np.arange, dtype=SimDType),
'concatenate': partial(np.concatenate, dtype=SimDType),
'sum': partial(np.sum, dtype=SimDType),
'newaxis': np.newaxis,
'fill_diagonal': np.fill_diagonal,
# numpy math functions
'radians': np.radians,
'degrees': np.degrees,
'exp': np.exp,
'log': np.log,
'sin': np.sin,
'cos': np.cos,
'tan': np.tan,
'arcsin': np.arcsin,
'arccos': np.arccos,
'arctan': np.arctan,
'arctan2': np.arctan2,
'sqrt': np.sqrt,
'add': np.add,
'subtract': np.subtract,
'multiply': np.multiply,
'divide': np.divide,
'maximum': np.maximum,
'minimum': np.minimum,
'absolute': np.absolute,
'floor': np.floor,
'ceil': np.ceil,
'pi': np.pi,
}),
**base_namespace(),
}

0 comments on commit 8104bae

Please sign in to comment.