scikit-complexity 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scikit_complexity-0.2.0.dist-info/METADATA +317 -0
- scikit_complexity-0.2.0.dist-info/RECORD +1748 -0
- scikit_complexity-0.2.0.dist-info/WHEEL +4 -0
- scikit_complexity-0.2.0.dist-info/entry_points.txt +4 -0
- scikit_complexity-0.2.0.dist-info/licenses/LICENSE +21 -0
- skcomplex/__init__.py +1 -0
- skcomplex/analysis/__init__.py +101 -0
- skcomplex/analysis/_alignment.py +263 -0
- skcomplex/analysis/_automata.py +658 -0
- skcomplex/analysis/_base.py +841 -0
- skcomplex/analysis/_clusters.py +298 -0
- skcomplex/analysis/_coarse_grain.py +183 -0
- skcomplex/analysis/_collapse.py +318 -0
- skcomplex/analysis/_complexity.py +129 -0
- skcomplex/analysis/_computational_mechanics.py +220 -0
- skcomplex/analysis/_correlation.py +364 -0
- skcomplex/analysis/_defects.py +111 -0
- skcomplex/analysis/_discovery.py +101 -0
- skcomplex/analysis/_displacement.py +135 -0
- skcomplex/analysis/_distribution.py +327 -0
- skcomplex/analysis/_domains.py +220 -0
- skcomplex/analysis/_embedding.py +235 -0
- skcomplex/analysis/_emergence.py +503 -0
- skcomplex/analysis/_entropy.py +425 -0
- skcomplex/analysis/_ergodicity.py +228 -0
- skcomplex/analysis/_events.py +301 -0
- skcomplex/analysis/_fit.py +368 -0
- skcomplex/analysis/_groups.py +205 -0
- skcomplex/analysis/_information.py +488 -0
- skcomplex/analysis/_invariants.py +409 -0
- skcomplex/analysis/_irreversibility.py +421 -0
- skcomplex/analysis/_kramers_moyal.py +104 -0
- skcomplex/analysis/_large_deviations.py +378 -0
- skcomplex/analysis/_linearization.py +231 -0
- skcomplex/analysis/_local_information.py +166 -0
- skcomplex/analysis/_loops.py +394 -0
- skcomplex/analysis/_lyapunov.py +342 -0
- skcomplex/analysis/_markov.py +303 -0
- skcomplex/analysis/_mode_decomposition.py +209 -0
- skcomplex/analysis/_motifs.py +239 -0
- skcomplex/analysis/_neighbors.py +303 -0
- skcomplex/analysis/_networks.py +286 -0
- skcomplex/analysis/_operator.py +312 -0
- skcomplex/analysis/_partial_information.py +118 -0
- skcomplex/analysis/_passage.py +244 -0
- skcomplex/analysis/_recurrence.py +202 -0
- skcomplex/analysis/_reservoirs.py +387 -0
- skcomplex/analysis/_rolling.py +168 -0
- skcomplex/analysis/_scaling.py +370 -0
- skcomplex/analysis/_sections.py +225 -0
- skcomplex/analysis/_signatures.py +250 -0
- skcomplex/analysis/_sparse_identification.py +398 -0
- skcomplex/analysis/_spectrum.py +164 -0
- skcomplex/analysis/_stability.py +547 -0
- skcomplex/analysis/_surrogates.py +127 -0
- skcomplex/analysis/_symbolic.py +639 -0
- skcomplex/analysis/types.py +43 -0
- skcomplex/base.py +159 -0
- skcomplex/core/__init__.py +1 -0
- skcomplex/core/base.py +150 -0
- skcomplex/core/elements/__init__.py +21 -0
- skcomplex/core/elements/_base.py +84 -0
- skcomplex/core/elements/_compartment.py +52 -0
- skcomplex/core/elements/_density.py +52 -0
- skcomplex/core/elements/_element.py +80 -0
- skcomplex/core/elements/_field.py +192 -0
- skcomplex/core/elements/_group.py +241 -0
- skcomplex/core/elements/_lattice.py +115 -0
- skcomplex/core/elements/_point.py +66 -0
- skcomplex/core/interactions/__init__.py +89 -0
- skcomplex/core/interactions/_advection.py +134 -0
- skcomplex/core/interactions/_base.py +361 -0
- skcomplex/core/interactions/_cascade.py +195 -0
- skcomplex/core/interactions/_choice.py +320 -0
- skcomplex/core/interactions/_conservation.py +164 -0
- skcomplex/core/interactions/_coupling.py +741 -0
- skcomplex/core/interactions/_crossing.py +136 -0
- skcomplex/core/interactions/_diffusion.py +99 -0
- skcomplex/core/interactions/_encounter.py +201 -0
- skcomplex/core/interactions/_euler_lagrange.py +183 -0
- skcomplex/core/interactions/_evolution.py +520 -0
- skcomplex/core/interactions/_feedback.py +79 -0
- skcomplex/core/interactions/_gradient.py +293 -0
- skcomplex/core/interactions/_grouping.py +399 -0
- skcomplex/core/interactions/_hamiltonian.py +191 -0
- skcomplex/core/interactions/_hyperedge.py +96 -0
- skcomplex/core/interactions/_imitation.py +357 -0
- skcomplex/core/interactions/_impulse.py +133 -0
- skcomplex/core/interactions/_interaction.py +58 -0
- skcomplex/core/interactions/_jump.py +201 -0
- skcomplex/core/interactions/_life_cycle.py +424 -0
- skcomplex/core/interactions/_local_rule.py +134 -0
- skcomplex/core/interactions/_map.py +239 -0
- skcomplex/core/interactions/_matching.py +701 -0
- skcomplex/core/interactions/_movement.py +377 -0
- skcomplex/core/interactions/_neighbor.py +88 -0
- skcomplex/core/interactions/_optimization.py +206 -0
- skcomplex/core/interactions/_pair.py +82 -0
- skcomplex/core/interactions/_pair_coupling.py +169 -0
- skcomplex/core/interactions/_rate.py +240 -0
- skcomplex/core/interactions/_reaction.py +466 -0
- skcomplex/core/interactions/_reinforcement.py +226 -0
- skcomplex/core/interactions/_relaxation.py +103 -0
- skcomplex/core/interactions/_sampling.py +177 -0
- skcomplex/core/interactions/_satisfiability.py +145 -0
- skcomplex/core/interactions/_sign_adjustment.py +222 -0
- skcomplex/core/interactions/_topology.py +215 -0
- skcomplex/core/interactions/_training.py +184 -0
- skcomplex/core/interactions/_transfer.py +669 -0
- skcomplex/core/interactions/_transition.py +427 -0
- skcomplex/core/laws/__init__.py +60 -0
- skcomplex/core/laws/_base.py +194 -0
- skcomplex/core/laws/_bilinear.py +91 -0
- skcomplex/core/laws/_boundary.py +59 -0
- skcomplex/core/laws/_cascade.py +79 -0
- skcomplex/core/laws/_crossing.py +87 -0
- skcomplex/core/laws/_dissipator.py +79 -0
- skcomplex/core/laws/_drive.py +56 -0
- skcomplex/core/laws/_emission.py +81 -0
- skcomplex/core/laws/_encounter.py +96 -0
- skcomplex/core/laws/_equation.py +105 -0
- skcomplex/core/laws/_extremal.py +94 -0
- skcomplex/core/laws/_flux.py +108 -0
- skcomplex/core/laws/_fractional_noise.py +65 -0
- skcomplex/core/laws/_generator.py +66 -0
- skcomplex/core/laws/_gradient_step.py +89 -0
- skcomplex/core/laws/_jump.py +137 -0
- skcomplex/core/laws/_local_rule.py +92 -0
- skcomplex/core/laws/_match.py +321 -0
- skcomplex/core/laws/_noise.py +125 -0
- skcomplex/core/laws/_rate.py +82 -0
- skcomplex/core/laws/_rule.py +82 -0
- skcomplex/core/laws/_sample.py +65 -0
- skcomplex/core/laws/_transfer.py +165 -0
- skcomplex/core/laws/_transition.py +77 -0
- skcomplex/core/laws/_update.py +121 -0
- skcomplex/core/laws/utils/__init__.py +142 -0
- skcomplex/core/laws/utils/_agents.py +127 -0
- skcomplex/core/laws/utils/_components.py +63 -0
- skcomplex/core/laws/utils/_conditions.py +198 -0
- skcomplex/core/laws/utils/_contractions.py +74 -0
- skcomplex/core/laws/utils/_delays.py +170 -0
- skcomplex/core/laws/utils/_history.py +167 -0
- skcomplex/core/laws/utils/_local_operators.py +68 -0
- skcomplex/core/laws/utils/_lookups.py +40 -0
- skcomplex/core/laws/utils/_moments.py +122 -0
- skcomplex/core/laws/utils/_operators.py +237 -0
- skcomplex/core/laws/utils/_phase.py +126 -0
- skcomplex/core/laws/utils/_pointwise.py +160 -0
- skcomplex/core/laws/utils/_reductions.py +942 -0
- skcomplex/core/laws/utils/_signals.py +214 -0
- skcomplex/core/laws/utils/_tables.py +4 -0
- skcomplex/core/laws/utils/_tensors.py +235 -0
- skcomplex/core/spaces/__init__.py +52 -0
- skcomplex/core/spaces/_adjacency.py +34 -0
- skcomplex/core/spaces/_base.py +218 -0
- skcomplex/core/spaces/_box.py +41 -0
- skcomplex/core/spaces/_cayley.py +352 -0
- skcomplex/core/spaces/_cone.py +65 -0
- skcomplex/core/spaces/_continuous.py +93 -0
- skcomplex/core/spaces/_continuous_time.py +27 -0
- skcomplex/core/spaces/_discrete_time.py +53 -0
- skcomplex/core/spaces/_generator.py +51 -0
- skcomplex/core/spaces/_lattice.py +194 -0
- skcomplex/core/spaces/_lattice_neighborhood.py +50 -0
- skcomplex/core/spaces/_memory.py +45 -0
- skcomplex/core/spaces/_mesh.py +71 -0
- skcomplex/core/spaces/_moore.py +49 -0
- skcomplex/core/spaces/_nearest.py +41 -0
- skcomplex/core/spaces/_network.py +256 -0
- skcomplex/core/spaces/_phase.py +136 -0
- skcomplex/core/spaces/_radius.py +40 -0
- skcomplex/core/spaces/_static_time.py +34 -0
- skcomplex/core/spaces/_triangular.py +37 -0
- skcomplex/core/spaces/_von_neumann.py +51 -0
- skcomplex/core/specs/__init__.py +25 -0
- skcomplex/core/specs/_census_record_spec.py +72 -0
- skcomplex/core/specs/_census_spec.py +40 -0
- skcomplex/core/specs/_compiled_agents_spec.py +62 -0
- skcomplex/core/specs/_compiled_element_spec.py +59 -0
- skcomplex/core/specs/_compiled_interaction_spec.py +33 -0
- skcomplex/core/specs/_lattice_context_spec.py +40 -0
- skcomplex/core/specs/_lattice_state_spec.py +49 -0
- skcomplex/core/specs/_node_spec.py +64 -0
- skcomplex/core/specs/_operator_view_spec.py +135 -0
- skcomplex/core/specs/_scenario_spec.py +45 -0
- skcomplex/core/specs/_subsystem_spec.py +24 -0
- skcomplex/core/system.py +140 -0
- skcomplex/core/types.py +249 -0
- skcomplex/engine/__init__.py +5 -0
- skcomplex/engine/_utils.py +278 -0
- skcomplex/engine/backends/__init__.py +13 -0
- skcomplex/engine/backends/_base.py +329 -0
- skcomplex/engine/backends/_jax.py +285 -0
- skcomplex/engine/backends/_numba.py +601 -0
- skcomplex/engine/backends/_numba_components.py +67 -0
- skcomplex/engine/backends/_numba_loops.py +163 -0
- skcomplex/engine/backends/_numba_neighbours.py +435 -0
- skcomplex/engine/backends/_numba_printer.py +1023 -0
- skcomplex/engine/backends/_numba_stencils.py +66 -0
- skcomplex/engine/backends/_numpy.py +215 -0
- skcomplex/engine/compile/__init__.py +27 -0
- skcomplex/engine/compile/_base.py +582 -0
- skcomplex/engine/compile/_bound_renewal_spec.py +47 -0
- skcomplex/engine/compile/_compilation.py +351 -0
- skcomplex/engine/compile/_compile.py +100 -0
- skcomplex/engine/compile/_complex.py +216 -0
- skcomplex/engine/compile/_draw_lowering.py +373 -0
- skcomplex/engine/compile/_field_lowering.py +1668 -0
- skcomplex/engine/compile/_flows.py +691 -0
- skcomplex/engine/compile/_forms.py +48 -0
- skcomplex/engine/compile/_laws.py +42 -0
- skcomplex/engine/compile/_learning_compiler.py +481 -0
- skcomplex/engine/compile/_member_reductions.py +206 -0
- skcomplex/engine/compile/_members.py +244 -0
- skcomplex/engine/compile/_observables.py +940 -0
- skcomplex/engine/compile/_observer.py +185 -0
- skcomplex/engine/compile/_pass_compiler.py +1534 -0
- skcomplex/engine/compile/_probe.py +78 -0
- skcomplex/engine/compile/_renewal_law.py +70 -0
- skcomplex/engine/compile/passes/__init__.py +34 -0
- skcomplex/engine/compile/passes/_agents.py +111 -0
- skcomplex/engine/compile/passes/_agents_problem.py +143 -0
- skcomplex/engine/compile/passes/_census.py +808 -0
- skcomplex/engine/compile/passes/_check_fractional_noise.py +107 -0
- skcomplex/engine/compile/passes/_collect.py +31 -0
- skcomplex/engine/compile/passes/_compile_encounters.py +301 -0
- skcomplex/engine/compile/passes/_complex.py +198 -0
- skcomplex/engine/compile/passes/_conserved_noise.py +224 -0
- skcomplex/engine/compile/passes/_core.py +116 -0
- skcomplex/engine/compile/passes/_declare_renewals.py +84 -0
- skcomplex/engine/compile/passes/_draws.py +29 -0
- skcomplex/engine/compile/passes/_encounter_functions.py +60 -0
- skcomplex/engine/compile/passes/_encounter_jacobian.py +25 -0
- skcomplex/engine/compile/passes/_encounter_problem.py +32 -0
- skcomplex/engine/compile/passes/_events.py +204 -0
- skcomplex/engine/compile/passes/_expand_flows.py +32 -0
- skcomplex/engine/compile/passes/_field_functions.py +647 -0
- skcomplex/engine/compile/passes/_field_jacobian.py +38 -0
- skcomplex/engine/compile/passes/_field_problem.py +106 -0
- skcomplex/engine/compile/passes/_flatten.py +339 -0
- skcomplex/engine/compile/passes/_flows_problem.py +29 -0
- skcomplex/engine/compile/passes/_form.py +82 -0
- skcomplex/engine/compile/passes/_fractional_form.py +172 -0
- skcomplex/engine/compile/passes/_fractional_problem.py +91 -0
- skcomplex/engine/compile/passes/_functions.py +485 -0
- skcomplex/engine/compile/passes/_hilbert_space_error.py +10 -0
- skcomplex/engine/compile/passes/_hyperedges.py +598 -0
- skcomplex/engine/compile/passes/_jacobian.py +38 -0
- skcomplex/engine/compile/passes/_kernels.py +407 -0
- skcomplex/engine/compile/passes/_lattices.py +818 -0
- skcomplex/engine/compile/passes/_layout.py +667 -0
- skcomplex/engine/compile/passes/_lower_fields.py +225 -0
- skcomplex/engine/compile/passes/_lower_flows.py +28 -0
- skcomplex/engine/compile/passes/_markov.py +329 -0
- skcomplex/engine/compile/passes/_mask_requests.py +121 -0
- skcomplex/engine/compile/passes/_members.py +30 -0
- skcomplex/engine/compile/passes/_noise.py +196 -0
- skcomplex/engine/compile/passes/_operator_compiler.py +843 -0
- skcomplex/engine/compile/passes/_orders.py +409 -0
- skcomplex/engine/compile/passes/_owners.py +90 -0
- skcomplex/engine/compile/passes/_particles.py +69 -0
- skcomplex/engine/compile/passes/_plan.py +130 -0
- skcomplex/engine/compile/passes/_problem.py +802 -0
- skcomplex/engine/compile/passes/_reduction_lowering.py +1193 -0
- skcomplex/engine/compile/passes/_reductions.py +84 -0
- skcomplex/engine/compile/passes/_renewal_problem.py +357 -0
- skcomplex/engine/compile/passes/_request_jumps.py +51 -0
- skcomplex/engine/compile/passes/_residences.py +140 -0
- skcomplex/engine/compile/passes/_rows.py +162 -0
- skcomplex/engine/compile/passes/_set_renewals_apart.py +29 -0
- skcomplex/engine/compile/passes/_set_rules_apart.py +28 -0
- skcomplex/engine/compile/passes/_specs.py +1317 -0
- skcomplex/engine/compile/passes/_split_requests.py +44 -0
- skcomplex/engine/compile/passes/_topology_functions.py +265 -0
- skcomplex/engine/compile/passes/_topology_problem.py +27 -0
- skcomplex/engine/compile/passes/_towards.py +66 -0
- skcomplex/engine/compile/passes/_unpack_matches.py +29 -0
- skcomplex/engine/compile/passes/_unpack_renewals.py +41 -0
- skcomplex/engine/problems/__init__.py +61 -0
- skcomplex/engine/problems/_base.py +150 -0
- skcomplex/engine/problems/_base_problem_spec.py +153 -0
- skcomplex/engine/problems/_block_spec.py +48 -0
- skcomplex/engine/problems/_born_spec.py +24 -0
- skcomplex/engine/problems/_cascade_kernel.py +134 -0
- skcomplex/engine/problems/_collision_kernel.py +147 -0
- skcomplex/engine/problems/_compiled_delay_spec.py +21 -0
- skcomplex/engine/problems/_compiled_request_spec.py +46 -0
- skcomplex/engine/problems/_control_problem_spec.py +90 -0
- skcomplex/engine/problems/_declarations_spec.py +126 -0
- skcomplex/engine/problems/_delayed_state_spec.py +50 -0
- skcomplex/engine/problems/_diffusive_limit_spec.py +50 -0
- skcomplex/engine/problems/_draw_kernel.py +128 -0
- skcomplex/engine/problems/_drive_kernel.py +65 -0
- skcomplex/engine/problems/_dynamics_spec.py +28 -0
- skcomplex/engine/problems/_edge_row_search.py +78 -0
- skcomplex/engine/problems/_edge_search.py +64 -0
- skcomplex/engine/problems/_encounter_kernel.py +200 -0
- skcomplex/engine/problems/_event_kernel.py +70 -0
- skcomplex/engine/problems/_expression_printer.py +410 -0
- skcomplex/engine/problems/_extremal_kernel.py +125 -0
- skcomplex/engine/problems/_field_operator_kernel.py +105 -0
- skcomplex/engine/problems/_finite_volume_kernel.py +423 -0
- skcomplex/engine/problems/_flow_term_spec.py +45 -0
- skcomplex/engine/problems/_frame_spec.py +105 -0
- skcomplex/engine/problems/_jacobian_kernel.py +575 -0
- skcomplex/engine/problems/_kernel_spec.py +130 -0
- skcomplex/engine/problems/_kinetic_problem_spec.py +23 -0
- skcomplex/engine/problems/_law_kernel.py +604 -0
- skcomplex/engine/problems/_learning_problem_spec.py +67 -0
- skcomplex/engine/problems/_linear_term_spec.py +50 -0
- skcomplex/engine/problems/_loop_term_spec.py +44 -0
- skcomplex/engine/problems/_lowered_kernels_spec.py +59 -0
- skcomplex/engine/problems/_markov_kernel.py +68 -0
- skcomplex/engine/problems/_metric_search.py +155 -0
- skcomplex/engine/problems/_monte_carlo_kernel.py +213 -0
- skcomplex/engine/problems/_neighborhood_kernel.py +594 -0
- skcomplex/engine/problems/_noise_term_spec.py +26 -0
- skcomplex/engine/problems/_observed_spec.py +22 -0
- skcomplex/engine/problems/_operator_kernel.py +102 -0
- skcomplex/engine/problems/_operator_lowering.py +323 -0
- skcomplex/engine/problems/_operator_problem_spec.py +138 -0
- skcomplex/engine/problems/_output_spec.py +78 -0
- skcomplex/engine/problems/_pair_search.py +86 -0
- skcomplex/engine/problems/_partials_spec.py +27 -0
- skcomplex/engine/problems/_partition_spec.py +39 -0
- skcomplex/engine/problems/_printed_spec.py +24 -0
- skcomplex/engine/problems/_problem_functions_spec.py +102 -0
- skcomplex/engine/problems/_problem_spec.py +365 -0
- skcomplex/engine/problems/_random_stream.py +49 -0
- skcomplex/engine/problems/_record_spec.py +22 -0
- skcomplex/engine/problems/_recorded_spec.py +21 -0
- skcomplex/engine/problems/_reduction_kernel.py +254 -0
- skcomplex/engine/problems/_reduction_schedule_spec.py +97 -0
- skcomplex/engine/problems/_reference_spec.py +114 -0
- skcomplex/engine/problems/_relation_spec.py +29 -0
- skcomplex/engine/problems/_renewal_kernel.py +250 -0
- skcomplex/engine/problems/_request_spec.py +27 -0
- skcomplex/engine/problems/_rule_kernel.py +227 -0
- skcomplex/engine/problems/_set_symbol_spec.py +28 -0
- skcomplex/engine/problems/_source_loader.py +113 -0
- skcomplex/engine/problems/_static_search.py +42 -0
- skcomplex/engine/problems/_steps.py +39 -0
- skcomplex/engine/problems/_sweep_spec.py +26 -0
- skcomplex/engine/problems/_symmetry_spec.py +29 -0
- skcomplex/engine/problems/_too_dense.py +8 -0
- skcomplex/engine/problems/_topology_kernel.py +589 -0
- skcomplex/engine/problems/_transfer_network.py +4 -0
- skcomplex/engine/problems/_transfer_network_spec.py +50 -0
- skcomplex/engine/problems/_transfer_state_spec.py +68 -0
- skcomplex/engine/runtime/__init__.py +22 -0
- skcomplex/engine/runtime/_as_fast_as_possible.py +17 -0
- skcomplex/engine/runtime/_base.py +137 -0
- skcomplex/engine/runtime/_conservation.py +125 -0
- skcomplex/engine/runtime/_invariants.py +100 -0
- skcomplex/engine/runtime/_real_time.py +55 -0
- skcomplex/engine/runtime/_recorder.py +84 -0
- skcomplex/engine/runtime/_simulations.py +665 -0
- skcomplex/engine/runtime/_trajectories.py +314 -0
- skcomplex/engine/solvers/__init__.py +95 -0
- skcomplex/engine/solvers/_base.py +372 -0
- skcomplex/engine/solvers/_caputo.py +194 -0
- skcomplex/engine/solvers/_collocation.py +334 -0
- skcomplex/engine/solvers/_convolution.py +155 -0
- skcomplex/engine/solvers/_cosimulation.py +400 -0
- skcomplex/engine/solvers/_crank_nicolson.py +32 -0
- skcomplex/engine/solvers/_defaults.py +34 -0
- skcomplex/engine/solvers/_etdrk4.py +86 -0
- skcomplex/engine/solvers/_euler_maruyama.py +161 -0
- skcomplex/engine/solvers/_event_locator.py +249 -0
- skcomplex/engine/solvers/_external.py +94 -0
- skcomplex/engine/solvers/_fractional_abm.py +126 -0
- skcomplex/engine/solvers/_fractional_euler_maruyama.py +322 -0
- skcomplex/engine/solvers/_gillespie.py +135 -0
- skcomplex/engine/solvers/_gradient_descent.py +353 -0
- skcomplex/engine/solvers/_grunwald_letnikov.py +83 -0
- skcomplex/engine/solvers/_heun.py +89 -0
- skcomplex/engine/solvers/_history.py +184 -0
- skcomplex/engine/solvers/_horizon_error.py +10 -0
- skcomplex/engine/solvers/_imex2.py +40 -0
- skcomplex/engine/solvers/_imex_euler.py +35 -0
- skcomplex/engine/solvers/_jump_trajectories.py +98 -0
- skcomplex/engine/solvers/_kinetics.py +242 -0
- skcomplex/engine/solvers/_l1.py +91 -0
- skcomplex/engine/solvers/_lammps.py +745 -0
- skcomplex/engine/solvers/_lammps_fix_spec.py +41 -0
- skcomplex/engine/solvers/_lattice.py +79 -0
- skcomplex/engine/solvers/_lindblad.py +70 -0
- skcomplex/engine/solvers/_maps.py +105 -0
- skcomplex/engine/solvers/_mesa.py +1624 -0
- skcomplex/engine/solvers/_milstein.py +93 -0
- skcomplex/engine/solvers/_monte_carlo.py +43 -0
- skcomplex/engine/solvers/_operator.py +212 -0
- skcomplex/engine/solvers/_optimal_control.py +368 -0
- skcomplex/engine/solvers/_pontryagin.py +298 -0
- skcomplex/engine/solvers/_renewal.py +90 -0
- skcomplex/engine/solvers/_renewals.py +190 -0
- skcomplex/engine/solvers/_rk4.py +263 -0
- skcomplex/engine/solvers/_root.py +176 -0
- skcomplex/engine/solvers/_rows.py +49 -0
- skcomplex/engine/solvers/_scipy_ode.py +602 -0
- skcomplex/engine/solvers/_sde.py +164 -0
- skcomplex/engine/solvers/_semi_lagrangian.py +213 -0
- skcomplex/engine/solvers/_solver.py +159 -0
- skcomplex/engine/solvers/_split.py +394 -0
- skcomplex/engine/solvers/_ssprk.py +147 -0
- skcomplex/engine/solvers/_strang_splitting.py +178 -0
- skcomplex/engine/solvers/_unitary.py +68 -0
- skcomplex/engine/solvers/_velocity_verlet.py +171 -0
- skcomplex/engine/solvers/_yoshida4.py +242 -0
- skcomplex/engine/types.py +90 -0
- skcomplex/engine/viz/__init__.py +35 -0
- skcomplex/engine/viz/_agents.py +223 -0
- skcomplex/engine/viz/_axes.py +146 -0
- skcomplex/engine/viz/_base.py +365 -0
- skcomplex/engine/viz/_bodies.py +334 -0
- skcomplex/engine/viz/_cayley.py +133 -0
- skcomplex/engine/viz/_expectation.py +208 -0
- skcomplex/engine/viz/_histograms.py +218 -0
- skcomplex/engine/viz/_images.py +307 -0
- skcomplex/engine/viz/_matrices.py +141 -0
- skcomplex/engine/viz/_meshes.py +149 -0
- skcomplex/engine/viz/_points.py +238 -0
- skcomplex/engine/viz/_rerun.py +527 -0
- skcomplex/engine/viz/_rings.py +127 -0
- skcomplex/engine/viz/_scalars.py +129 -0
- skcomplex/engine/viz/_sites.py +228 -0
- skcomplex/errors.py +112 -0
- skcomplex/experiments/__init__.py +36 -0
- skcomplex/experiments/_base.py +373 -0
- skcomplex/experiments/_basin_stability.py +153 -0
- skcomplex/experiments/_calibration.py +194 -0
- skcomplex/experiments/_experiment.py +327 -0
- skcomplex/experiments/_grid.py +36 -0
- skcomplex/experiments/_latin_hypercube.py +44 -0
- skcomplex/experiments/_morris.py +50 -0
- skcomplex/experiments/_one_at_a_time.py +28 -0
- skcomplex/experiments/_orbit_diagram.py +146 -0
- skcomplex/experiments/_random.py +44 -0
- skcomplex/experiments/_results.py +148 -0
- skcomplex/experiments/_rows.py +45 -0
- skcomplex/experiments/_saltelli.py +50 -0
- skcomplex/experiments/_sensitivity.py +122 -0
- skcomplex/experiments/_sobol.py +43 -0
- skcomplex/experiments/specs/__init__.py +1 -0
- skcomplex/experiments/specs/_task_spec.py +78 -0
- skcomplex/experiments/types.py +14 -0
- skcomplex/models/__init__.py +18 -0
- skcomplex/models/_catalog.py +243 -0
- skcomplex/models/_model_catalog.py +270 -0
- skcomplex/models/_model_entry.py +170 -0
- skcomplex/models/_model_listing.py +38 -0
- skcomplex/models/biology/__init__.py +1 -0
- skcomplex/models/biology/collective_behaviour/__init__.py +48 -0
- skcomplex/models/biology/collective_behaviour/_alarm.py +99 -0
- skcomplex/models/biology/collective_behaviour/_ant.py +101 -0
- skcomplex/models/biology/collective_behaviour/_ant_view.py +24 -0
- skcomplex/models/biology/collective_behaviour/_boid.py +104 -0
- skcomplex/models/biology/collective_behaviour/_boid_view.py +25 -0
- skcomplex/models/biology/collective_behaviour/_branch.py +41 -0
- skcomplex/models/biology/collective_behaviour/_decisions.py +149 -0
- skcomplex/models/biology/collective_behaviour/_flight.py +52 -0
- skcomplex/models/biology/collective_behaviour/_flocking.py +75 -0
- skcomplex/models/biology/collective_behaviour/_flocks.py +169 -0
- skcomplex/models/biology/collective_behaviour/_foraging.py +232 -0
- skcomplex/models/biology/collective_behaviour/_ground.py +67 -0
- skcomplex/models/biology/collective_behaviour/_leadership.py +207 -0
- skcomplex/models/biology/collective_behaviour/_morse_potential.py +87 -0
- skcomplex/models/biology/collective_behaviour/_pheromone.py +55 -0
- skcomplex/models/biology/collective_behaviour/_rats.py +41 -0
- skcomplex/models/biology/collective_behaviour/_schooling.py +102 -0
- skcomplex/models/biology/collective_behaviour/_self_propulsion.py +64 -0
- skcomplex/models/biology/collective_behaviour/_shoal_member_view.py +25 -0
- skcomplex/models/biology/collective_behaviour/_swimming.py +66 -0
- skcomplex/models/biology/collective_behaviour/_trail_choice.py +105 -0
- skcomplex/models/biology/collective_behaviour/_trails.py +245 -0
- skcomplex/models/biology/collective_behaviour/_walker.py +97 -0
- skcomplex/models/biology/collective_behaviour/_walker_view.py +23 -0
- skcomplex/models/biology/common/__init__.py +3 -0
- skcomplex/models/biology/common/excitable/__init__.py +7 -0
- skcomplex/models/biology/common/excitable/_fitzhugh_nagumo.py +121 -0
- skcomplex/models/biology/common/kinetics/__init__.py +7 -0
- skcomplex/models/biology/common/kinetics/_michaelis_menten.py +137 -0
- skcomplex/models/biology/common/networks/__init__.py +9 -0
- skcomplex/models/biology/common/networks/_edge_draw.py +95 -0
- skcomplex/models/biology/common/networks/_weighted_edge.py +48 -0
- skcomplex/models/biology/common/pharmacokinetics/__init__.py +7 -0
- skcomplex/models/biology/common/pharmacokinetics/_dosing.py +125 -0
- skcomplex/models/biology/common/populations/__init__.py +19 -0
- skcomplex/models/biology/common/populations/_exponential_growth.py +66 -0
- skcomplex/models/biology/common/populations/_gompertz_growth.py +75 -0
- skcomplex/models/biology/common/populations/_growth.py +176 -0
- skcomplex/models/biology/common/populations/_logistic_growth.py +92 -0
- skcomplex/models/biology/common/populations/_mortality.py +69 -0
- skcomplex/models/biology/common/populations/_population.py +41 -0
- skcomplex/models/biology/common/populations/_power_law_growth.py +71 -0
- skcomplex/models/biology/common/stigmergy/__init__.py +7 -0
- skcomplex/models/biology/common/stigmergy/_evaporation.py +95 -0
- skcomplex/models/biology/ecology/__init__.py +128 -0
- skcomplex/models/biology/ecology/_abundance.py +52 -0
- skcomplex/models/biology/ecology/_agent_predation.py +170 -0
- skcomplex/models/biology/ecology/_cell_quota.py +163 -0
- skcomplex/models/biology/ecology/_clustering.py +96 -0
- skcomplex/models/biology/ecology/_communities.py +234 -0
- skcomplex/models/biology/ecology/_competition.py +95 -0
- skcomplex/models/biology/ecology/_cow.py +49 -0
- skcomplex/models/biology/ecology/_cow_view.py +15 -0
- skcomplex/models/biology/ecology/_emotion_marks.py +65 -0
- skcomplex/models/biology/ecology/_factories.py +322 -0
- skcomplex/models/biology/ecology/_forager.py +116 -0
- skcomplex/models/biology/ecology/_forager_view.py +25 -0
- skcomplex/models/biology/ecology/_fronts.py +128 -0
- skcomplex/models/biology/ecology/_generalized_lotka_volterra.py +66 -0
- skcomplex/models/biology/ecology/_grass.py +96 -0
- skcomplex/models/biology/ecology/_grass_view.py +17 -0
- skcomplex/models/biology/ecology/_grazing.py +66 -0
- skcomplex/models/biology/ecology/_habitat_patch.py +49 -0
- skcomplex/models/biology/ecology/_herding.py +84 -0
- skcomplex/models/biology/ecology/_higher_order.py +102 -0
- skcomplex/models/biology/ecology/_hopping.py +68 -0
- skcomplex/models/biology/ecology/_instability.py +180 -0
- skcomplex/models/biology/ecology/_linear_growth.py +70 -0
- skcomplex/models/biology/ecology/_meadow.py +102 -0
- skcomplex/models/biology/ecology/_microbe.py +47 -0
- skcomplex/models/biology/ecology/_microbial_communities.py +90 -0
- skcomplex/models/biology/ecology/_mutualism.py +81 -0
- skcomplex/models/biology/ecology/_neutral.py +144 -0
- skcomplex/models/biology/ecology/_neutral_replacement.py +54 -0
- skcomplex/models/biology/ecology/_organism.py +63 -0
- skcomplex/models/biology/ecology/_organism_view.py +15 -0
- skcomplex/models/biology/ecology/_parasitism.py +78 -0
- skcomplex/models/biology/ecology/_pasture.py +83 -0
- skcomplex/models/biology/ecology/_pasture_view.py +16 -0
- skcomplex/models/biology/ecology/_pioneer_growth.py +101 -0
- skcomplex/models/biology/ecology/_plant.py +56 -0
- skcomplex/models/biology/ecology/_plant_view.py +16 -0
- skcomplex/models/biology/ecology/_predation.py +290 -0
- skcomplex/models/biology/ecology/_predation_interaction.py +71 -0
- skcomplex/models/biology/ecology/_predator.py +63 -0
- skcomplex/models/biology/ecology/_predator_prey_events.py +120 -0
- skcomplex/models/biology/ecology/_predator_view.py +17 -0
- skcomplex/models/biology/ecology/_prey.py +52 -0
- skcomplex/models/biology/ecology/_prey_view.py +15 -0
- skcomplex/models/biology/ecology/_rosenzweig_macarthur.py +91 -0
- skcomplex/models/biology/ecology/_seasonal_logistic_growth.py +71 -0
- skcomplex/models/biology/ecology/_sequential.py +114 -0
- skcomplex/models/biology/ecology/_sheep.py +63 -0
- skcomplex/models/biology/ecology/_sheep_view.py +17 -0
- skcomplex/models/biology/ecology/_speciation.py +71 -0
- skcomplex/models/biology/ecology/_stand.py +47 -0
- skcomplex/models/biology/ecology/_stigmergic_predator.py +98 -0
- skcomplex/models/biology/ecology/_stigmergic_prey.py +54 -0
- skcomplex/models/biology/ecology/_stigmergy.py +413 -0
- skcomplex/models/biology/ecology/_succession.py +92 -0
- skcomplex/models/biology/ecology/_successional_growth.py +88 -0
- skcomplex/models/biology/ecology/_triplet.py +55 -0
- skcomplex/models/biology/ecology/_wolf.py +63 -0
- skcomplex/models/biology/ecology/_wolf_sheep.py +156 -0
- skcomplex/models/biology/ecology/_wolf_view.py +17 -0
- skcomplex/models/biology/epidemiology/__init__.py +53 -0
- skcomplex/models/biology/epidemiology/_active_host.py +61 -0
- skcomplex/models/biology/epidemiology/_adaptive.py +316 -0
- skcomplex/models/biology/epidemiology/_agents.py +484 -0
- skcomplex/models/biology/epidemiology/_carrier.py +66 -0
- skcomplex/models/biology/epidemiology/_degree_class.py +65 -0
- skcomplex/models/biology/epidemiology/_factories.py +186 -0
- skcomplex/models/biology/epidemiology/_host.py +49 -0
- skcomplex/models/biology/epidemiology/_immunity_loss.py +84 -0
- skcomplex/models/biology/epidemiology/_infection.py +93 -0
- skcomplex/models/biology/epidemiology/_networks.py +170 -0
- skcomplex/models/biology/epidemiology/_outbreaks.py +216 -0
- skcomplex/models/biology/epidemiology/_person.py +103 -0
- skcomplex/models/biology/epidemiology/_person_view.py +23 -0
- skcomplex/models/biology/epidemiology/_recovery.py +92 -0
- skcomplex/models/biology/epidemiology/_recurrent.py +149 -0
- skcomplex/models/biology/epidemiology/_spreading.py +144 -0
- skcomplex/models/biology/epidemiology/_subpopulation.py +92 -0
- skcomplex/models/biology/epidemiology/_traveller.py +65 -0
- skcomplex/models/biology/epidemiology/_traveller_view.py +17 -0
- skcomplex/models/biology/epidemiology/_vaccination.py +184 -0
- skcomplex/models/biology/epidemiology/_walker.py +66 -0
- skcomplex/models/biology/epidemiology/_walker_view.py +17 -0
- skcomplex/models/biology/evolution/__init__.py +60 -0
- skcomplex/models/biology/evolution/_adaptive_climbing.py +106 -0
- skcomplex/models/biology/evolution/_catalysis.py +76 -0
- skcomplex/models/biology/evolution/_catalytic_link.py +21 -0
- skcomplex/models/biology/evolution/_chemical.py +111 -0
- skcomplex/models/biology/evolution/_climber.py +125 -0
- skcomplex/models/biology/evolution/_climber_view.py +19 -0
- skcomplex/models/biology/evolution/_coevolution.py +148 -0
- skcomplex/models/biology/evolution/_cyclic_species.py +44 -0
- skcomplex/models/biology/evolution/_dependency_field.py +56 -0
- skcomplex/models/biology/evolution/_finite_populations.py +287 -0
- skcomplex/models/biology/evolution/_games.py +143 -0
- skcomplex/models/biology/evolution/_genotype_class.py +42 -0
- skcomplex/models/biology/evolution/_individual.py +54 -0
- skcomplex/models/biology/evolution/_individual_view.py +16 -0
- skcomplex/models/biology/evolution/_locus.py +47 -0
- skcomplex/models/biology/evolution/_master_sequence.py +55 -0
- skcomplex/models/biology/evolution/_molecule.py +47 -0
- skcomplex/models/biology/evolution/_moran_step.py +83 -0
- skcomplex/models/biology/evolution/_networks.py +194 -0
- skcomplex/models/biology/evolution/_prebiotic.py +169 -0
- skcomplex/models/biology/evolution/_replicator.py +109 -0
- skcomplex/models/biology/evolution/_strategy.py +42 -0
- skcomplex/models/biology/evolution/_substitution.py +113 -0
- skcomplex/models/biology/evolution/_substitutions.py +126 -0
- skcomplex/models/biology/evolution/_tangled_nature_life_cycle.py +159 -0
- skcomplex/models/biology/evolution/_taxon.py +49 -0
- skcomplex/models/biology/neuroscience/__init__.py +63 -0
- skcomplex/models/biology/neuroscience/_conductances.py +193 -0
- skcomplex/models/biology/neuroscience/_delayed_synapse.py +70 -0
- skcomplex/models/biology/neuroscience/_excitable.py +178 -0
- skcomplex/models/biology/neuroscience/_fitz_hugh_nagumo_neuron.py +46 -0
- skcomplex/models/biology/neuroscience/_global_inhibition.py +71 -0
- skcomplex/models/biology/neuroscience/_hodgkin_huxley.py +103 -0
- skcomplex/models/biology/neuroscience/_inhibitor.py +62 -0
- skcomplex/models/biology/neuroscience/_inhibitor_drive.py +61 -0
- skcomplex/models/biology/neuroscience/_izhikevich.py +77 -0
- skcomplex/models/biology/neuroscience/_leaky_integrate_and_fire.py +80 -0
- skcomplex/models/biology/neuroscience/_mutual_inhibition.py +55 -0
- skcomplex/models/biology/neuroscience/_networks.py +235 -0
- skcomplex/models/biology/neuroscience/_neural_field_site.py +66 -0
- skcomplex/models/biology/neuroscience/_neural_fields.py +94 -0
- skcomplex/models/biology/neuroscience/_neurons.py +129 -0
- skcomplex/models/biology/neuroscience/_polyhomeostatic_neuron.py +93 -0
- skcomplex/models/biology/neuroscience/_populations.py +333 -0
- skcomplex/models/biology/neuroscience/_pulse_coupling.py +71 -0
- skcomplex/models/biology/neuroscience/_rate_unit.py +67 -0
- skcomplex/models/biology/neuroscience/_spike_reset.py +95 -0
- skcomplex/models/biology/neuroscience/_spiking_neuron.py +67 -0
- skcomplex/models/biology/neuroscience/_synapses.py +226 -0
- skcomplex/models/biology/neuroscience/_terman_wang.py +113 -0
- skcomplex/models/biology/neuroscience/_theta_neuron.py +66 -0
- skcomplex/models/biology/neuroscience/_wilson_cowan.py +122 -0
- skcomplex/models/biology/neuroscience/types.py +8 -0
- skcomplex/models/biology/oncology/__init__.py +212 -0
- skcomplex/models/biology/oncology/_androgen_receptor_prostate.py +240 -0
- skcomplex/models/biology/oncology/_androgen_suppression.py +109 -0
- skcomplex/models/biology/oncology/_angiogenesis.py +306 -0
- skcomplex/models/biology/oncology/_angiogenesis_immunotherapy_tumour.py +247 -0
- skcomplex/models/biology/oncology/_angiogenic_tumour.py +110 -0
- skcomplex/models/biology/oncology/_antiangiogenic.py +227 -0
- skcomplex/models/biology/oncology/_bone_marrow_blood.py +196 -0
- skcomplex/models/biology/oncology/_cell_cycle.py +85 -0
- skcomplex/models/biology/oncology/_cell_kinetics.py +285 -0
- skcomplex/models/biology/oncology/_cell_quota_prostate.py +207 -0
- skcomplex/models/biology/oncology/_cell_survival.py +72 -0
- skcomplex/models/biology/oncology/_checkpoint_tumour.py +161 -0
- skcomplex/models/biology/oncology/_chemoimmunotherapy_tumour.py +251 -0
- skcomplex/models/biology/oncology/_chemotherapy.py +565 -0
- skcomplex/models/biology/oncology/_chemovirotherapy_tumour.py +139 -0
- skcomplex/models/biology/oncology/_clonal_tumour.py +134 -0
- skcomplex/models/biology/oncology/_combination_therapy.py +989 -0
- skcomplex/models/biology/oncology/_delayed_vaccinated_tumour.py +341 -0
- skcomplex/models/biology/oncology/_dormant_cell_cycle.py +95 -0
- skcomplex/models/biology/oncology/_erythropoiesis.py +129 -0
- skcomplex/models/biology/oncology/_exponential_linear_growth.py +66 -0
- skcomplex/models/biology/oncology/_gene_viral_therapy.py +480 -0
- skcomplex/models/biology/oncology/_glioma_brain.py +165 -0
- skcomplex/models/biology/oncology/_growth.py +378 -0
- skcomplex/models/biology/oncology/_her2_tumour.py +156 -0
- skcomplex/models/biology/oncology/_hormone_therapy.py +985 -0
- skcomplex/models/biology/oncology/_immune_competition.py +241 -0
- skcomplex/models/biology/oncology/_immunotherapy.py +1001 -0
- skcomplex/models/biology/oncology/_intermittent_suppression.py +130 -0
- skcomplex/models/biology/oncology/_irradiated_tumour.py +105 -0
- skcomplex/models/biology/oncology/_irradiation.py +97 -0
- skcomplex/models/biology/oncology/_kirschner_panetta_tumour.py +132 -0
- skcomplex/models/biology/oncology/_leukaemia_stem_cells.py +150 -0
- skcomplex/models/biology/oncology/_linear_quadratic_survival.py +112 -0
- skcomplex/models/biology/oncology/_log_kill.py +81 -0
- skcomplex/models/biology/oncology/_metastasis_chemotherapy.py +211 -0
- skcomplex/models/biology/oncology/_multidrug_resistance.py +201 -0
- skcomplex/models/biology/oncology/_oncolytic_virus.py +68 -0
- skcomplex/models/biology/oncology/_oncolytic_virus_dendritic.py +155 -0
- skcomplex/models/biology/oncology/_optimal_chemotherapy.py +157 -0
- skcomplex/models/biology/oncology/_optimal_immunotherapy.py +137 -0
- skcomplex/models/biology/oncology/_optimal_therapy.py +208 -0
- skcomplex/models/biology/oncology/_piecewise_linear_prostate.py +147 -0
- skcomplex/models/biology/oncology/_radiation_competition.py +104 -0
- skcomplex/models/biology/oncology/_radiotherapy.py +311 -0
- skcomplex/models/biology/oncology/_resistance_switching.py +148 -0
- skcomplex/models/biology/oncology/_resting_hunting_chemotherapy.py +136 -0
- skcomplex/models/biology/oncology/_sirna_tgf_beta.py +189 -0
- skcomplex/models/biology/oncology/_sprout.py +65 -0
- skcomplex/models/biology/oncology/_sprout_view.py +17 -0
- skcomplex/models/biology/oncology/_stem_cell_differentiation.py +262 -0
- skcomplex/models/biology/oncology/_stem_cells.py +548 -0
- skcomplex/models/biology/oncology/_suppressed_tumour.py +338 -0
- skcomplex/models/biology/oncology/_tamoxifen_tumour.py +172 -0
- skcomplex/models/biology/oncology/_tcr_gene_therapy.py +98 -0
- skcomplex/models/biology/oncology/_therapy_switch.py +86 -0
- skcomplex/models/biology/oncology/_tissue.py +71 -0
- skcomplex/models/biology/oncology/_tumour_cell.py +85 -0
- skcomplex/models/biology/oncology/_tumour_cell_view.py +21 -0
- skcomplex/models/biology/oncology/_tumour_immune_chemotherapy.py +169 -0
- skcomplex/models/biology/oncology/_vaccinated_tumour.py +180 -0
- skcomplex/models/biology/oncology/_vascular_support.py +71 -0
- skcomplex/models/biology/oncology/_vascularized_spheroid.py +264 -0
- skcomplex/models/biology/oncology/_vasculature.py +42 -0
- skcomplex/models/biology/oncology/_vessel.py +49 -0
- skcomplex/models/biology/oncology/_vessel_view.py +15 -0
- skcomplex/models/biology/physiology/__init__.py +46 -0
- skcomplex/models/biology/physiology/_adaptivity.py +277 -0
- skcomplex/models/biology/physiology/_cardiac.py +167 -0
- skcomplex/models/biology/physiology/_chamber.py +71 -0
- skcomplex/models/biology/physiology/_circulation.py +97 -0
- skcomplex/models/biology/physiology/_coagulation.py +130 -0
- skcomplex/models/biology/physiology/_contour_cell.py +61 -0
- skcomplex/models/biology/physiology/_contour_uptake.py +61 -0
- skcomplex/models/biology/physiology/_exchange.py +165 -0
- skcomplex/models/biology/physiology/_exchanging_cell.py +83 -0
- skcomplex/models/biology/physiology/_fitz_hugh_nagumo.py +46 -0
- skcomplex/models/biology/physiology/_glucose_control.py +136 -0
- skcomplex/models/biology/physiology/_mackey_glass.py +81 -0
- skcomplex/models/biology/physiology/_pharmacokinetics.py +104 -0
- skcomplex/models/biology/physiology/_physiology.py +118 -0
- skcomplex/models/biology/physiology/_regulation.py +251 -0
- skcomplex/models/biology/physiology/_resistive_flow.py +67 -0
- skcomplex/models/biology/physiology/_toxicity.py +164 -0
- skcomplex/models/biology/systems_biology/__init__.py +52 -0
- skcomplex/models/biology/systems_biology/_boolean.py +141 -0
- skcomplex/models/biology/systems_biology/_boolean_function.py +84 -0
- skcomplex/models/biology/systems_biology/_boolean_models.py +206 -0
- skcomplex/models/biology/systems_biology/_boolean_node.py +41 -0
- skcomplex/models/biology/systems_biology/_cascades.py +178 -0
- skcomplex/models/biology/systems_biology/_clocks.py +274 -0
- skcomplex/models/biology/systems_biology/_generalized_mass_action.py +123 -0
- skcomplex/models/biology/systems_biology/_genes.py +296 -0
- skcomplex/models/biology/systems_biology/_min_proteins.py +230 -0
- skcomplex/models/biology/systems_biology/_networks.py +359 -0
- skcomplex/models/biology/systems_biology/_phosphorylation_loop.py +121 -0
- skcomplex/models/biology/systems_biology/_probabilistic.py +75 -0
- skcomplex/models/biology/systems_biology/_probabilistic_function.py +127 -0
- skcomplex/models/biology/systems_biology/_probabilistic_node.py +47 -0
- skcomplex/models/biology/systems_biology/_repression.py +104 -0
- skcomplex/models/biology/systems_biology/_s_system.py +88 -0
- skcomplex/models/biology/systems_biology/_species.py +44 -0
- skcomplex/models/biology/systems_biology/_threshold_function.py +63 -0
- skcomplex/models/biology/systems_biology/types.py +9 -0
- skcomplex/models/chemistry/__init__.py +1 -0
- skcomplex/models/chemistry/common/__init__.py +3 -0
- skcomplex/models/chemistry/common/kinetics/__init__.py +9 -0
- skcomplex/models/chemistry/common/kinetics/_brusselator.py +61 -0
- skcomplex/models/chemistry/common/kinetics/_cubic_autocatalysis.py +80 -0
- skcomplex/models/chemistry/kinetics/__init__.py +38 -0
- skcomplex/models/chemistry/kinetics/_catalyst_pellet.py +60 -0
- skcomplex/models/chemistry/kinetics/_cubic_autocatalysis.py +60 -0
- skcomplex/models/chemistry/kinetics/_cyclic.py +130 -0
- skcomplex/models/chemistry/kinetics/_hodgepodge.py +157 -0
- skcomplex/models/chemistry/kinetics/_nanoparticles.py +103 -0
- skcomplex/models/chemistry/kinetics/_oregonator.py +76 -0
- skcomplex/models/chemistry/kinetics/_oscillators.py +244 -0
- skcomplex/models/chemistry/kinetics/_pulsed_electrode.py +107 -0
- skcomplex/models/chemistry/kinetics/_reactions.py +332 -0
- skcomplex/models/chemistry/kinetics/_reactors.py +144 -0
- skcomplex/models/chemistry/pattern_formation/__init__.py +15 -0
- skcomplex/models/chemistry/pattern_formation/_brusselator.py +62 -0
- skcomplex/models/chemistry/pattern_formation/_gray_scott.py +68 -0
- skcomplex/models/chemistry/pattern_formation/_reaction_diffusion.py +268 -0
- skcomplex/models/chemistry/pattern_formation/_schnakenberg.py +67 -0
- skcomplex/models/computer_science/__init__.py +1 -0
- skcomplex/models/computer_science/automata/__init__.py +56 -0
- skcomplex/models/computer_science/automata/_automata.py +229 -0
- skcomplex/models/computer_science/automata/_automaton.py +202 -0
- skcomplex/models/computer_science/automata/_binary_cell.py +41 -0
- skcomplex/models/computer_science/automata/_codes.py +73 -0
- skcomplex/models/computer_science/automata/_diffusion_cell.py +47 -0
- skcomplex/models/computer_science/automata/_group_automata.py +449 -0
- skcomplex/models/computer_science/automata/_groups.py +132 -0
- skcomplex/models/computer_science/automata/_linear_automaton.py +128 -0
- skcomplex/models/computer_science/automata/_noisy_elementary_cell.py +46 -0
- skcomplex/models/computer_science/automata/_pascal_cell.py +41 -0
- skcomplex/models/computer_science/automata/_subshift.py +192 -0
- skcomplex/models/computer_science/automata/_variants.py +292 -0
- skcomplex/models/computer_science/evolutionary_computation/__init__.py +27 -0
- skcomplex/models/computer_science/evolutionary_computation/_annealed_candidate.py +39 -0
- skcomplex/models/computer_science/evolutionary_computation/_bit_string.py +55 -0
- skcomplex/models/computer_science/evolutionary_computation/_bit_string_view.py +13 -0
- skcomplex/models/computer_science/evolutionary_computation/_genetic_algorithms.py +92 -0
- skcomplex/models/computer_science/evolutionary_computation/_landscapes.py +82 -0
- skcomplex/models/computer_science/evolutionary_computation/_optimisers.py +217 -0
- skcomplex/models/computer_science/evolutionary_computation/_reproduction.py +129 -0
- skcomplex/models/computer_science/evolutionary_computation/_room_cleaning.py +170 -0
- skcomplex/models/computer_science/evolutionary_computation/_running_best.py +30 -0
- skcomplex/models/computer_science/evolutionary_computation/_running_best_update.py +58 -0
- skcomplex/models/computer_science/evolutionary_computation/_search_candidate.py +32 -0
- skcomplex/models/computer_science/evolutionary_computation/_strategy.py +54 -0
- skcomplex/models/computer_science/evolutionary_computation/_strategy_view.py +14 -0
- skcomplex/models/computer_science/neural_networks/__init__.py +34 -0
- skcomplex/models/computer_science/neural_networks/_binary_weight.py +32 -0
- skcomplex/models/computer_science/neural_networks/_diluted.py +159 -0
- skcomplex/models/computer_science/neural_networks/_echo_state.py +173 -0
- skcomplex/models/computer_science/neural_networks/_elman.py +160 -0
- skcomplex/models/computer_science/neural_networks/_hidden_unit.py +51 -0
- skcomplex/models/computer_science/neural_networks/_hopfield.py +134 -0
- skcomplex/models/computer_science/neural_networks/_hopfield_update.py +51 -0
- skcomplex/models/computer_science/neural_networks/_input_coupling.py +63 -0
- skcomplex/models/computer_science/neural_networks/_input_unit.py +39 -0
- skcomplex/models/computer_science/neural_networks/_neuron_view.py +14 -0
- skcomplex/models/computer_science/neural_networks/_output_unit.py +51 -0
- skcomplex/models/computer_science/neural_networks/_perceptron.py +72 -0
- skcomplex/models/computer_science/neural_networks/_readout_coupling.py +69 -0
- skcomplex/models/computer_science/neural_networks/_recurrence_coupling.py +66 -0
- skcomplex/models/economics/__init__.py +1 -0
- skcomplex/models/economics/common/__init__.py +3 -0
- skcomplex/models/economics/common/forecasting/__init__.py +7 -0
- skcomplex/models/economics/common/forecasting/_heuristics.py +51 -0
- skcomplex/models/economics/common/resources/__init__.py +7 -0
- skcomplex/models/economics/common/resources/_regrowth.py +70 -0
- skcomplex/models/economics/econophysics/__init__.py +58 -0
- skcomplex/models/economics/econophysics/_crowd_avoidance.py +80 -0
- skcomplex/models/economics/econophysics/_debt_exchange.py +74 -0
- skcomplex/models/economics/econophysics/_diner.py +59 -0
- skcomplex/models/economics/econophysics/_diner_view.py +17 -0
- skcomplex/models/economics/econophysics/_el_farol.py +114 -0
- skcomplex/models/economics/econophysics/_exchange.py +82 -0
- skcomplex/models/economics/econophysics/_game_state_spec.py +26 -0
- skcomplex/models/economics/econophysics/_kinetic.py +80 -0
- skcomplex/models/economics/econophysics/_kolkata.py +87 -0
- skcomplex/models/economics/econophysics/_minority.py +123 -0
- skcomplex/models/economics/econophysics/_minority_game.py +161 -0
- skcomplex/models/economics/econophysics/_minority_player.py +79 -0
- skcomplex/models/economics/econophysics/_minority_player_view.py +22 -0
- skcomplex/models/economics/econophysics/_patron.py +105 -0
- skcomplex/models/economics/econophysics/_patron_view.py +18 -0
- skcomplex/models/economics/econophysics/_predictor_pool.py +181 -0
- skcomplex/models/economics/econophysics/_predictor_pool_view.py +14 -0
- skcomplex/models/economics/econophysics/_restaurants.py +93 -0
- skcomplex/models/economics/econophysics/_saving_exchange.py +73 -0
- skcomplex/models/economics/econophysics/_saving_trader.py +47 -0
- skcomplex/models/economics/econophysics/_saving_trader_view.py +12 -0
- skcomplex/models/economics/econophysics/_wealth_exchange.py +114 -0
- skcomplex/models/economics/econophysics/_welfare.py +210 -0
- skcomplex/models/economics/econophysics/_welfare_policy.py +99 -0
- skcomplex/models/economics/finance/__init__.py +41 -0
- skcomplex/models/economics/finance/_arbitrage.py +139 -0
- skcomplex/models/economics/finance/_asset.py +42 -0
- skcomplex/models/economics/finance/_assets.py +44 -0
- skcomplex/models/economics/finance/_book.py +115 -0
- skcomplex/models/economics/finance/_contagion.py +116 -0
- skcomplex/models/economics/finance/_correlated_assets.py +69 -0
- skcomplex/models/economics/finance/_debt_rank_cascade.py +86 -0
- skcomplex/models/economics/finance/_geometric_brownian_motion.py +89 -0
- skcomplex/models/economics/finance/_gibrat_firm.py +82 -0
- skcomplex/models/economics/finance/_gibrat_firm_view.py +18 -0
- skcomplex/models/economics/finance/_growth_processes.py +195 -0
- skcomplex/models/economics/finance/_interbank.py +76 -0
- skcomplex/models/economics/finance/_interbank_view.py +14 -0
- skcomplex/models/economics/finance/_kesten_firm.py +88 -0
- skcomplex/models/economics/finance/_kesten_firm_view.py +16 -0
- skcomplex/models/economics/finance/_order_book.py +164 -0
- skcomplex/models/economics/finance/_reflecting_floor.py +66 -0
- skcomplex/models/economics/finance/_stock_trader.py +205 -0
- skcomplex/models/economics/finance/_stock_trader_view.py +24 -0
- skcomplex/models/economics/finance/_wealth.py +143 -0
- skcomplex/models/economics/innovation/__init__.py +23 -0
- skcomplex/models/economics/innovation/_adoption.py +233 -0
- skcomplex/models/economics/innovation/_bass.py +124 -0
- skcomplex/models/economics/innovation/_diversity.py +104 -0
- skcomplex/models/economics/innovation/_household_view.py +20 -0
- skcomplex/models/economics/innovation/_invention.py +140 -0
- skcomplex/models/economics/innovation/_part.py +64 -0
- skcomplex/models/economics/innovation/_part_view.py +12 -0
- skcomplex/models/economics/innovation/_redesign.py +88 -0
- skcomplex/models/economics/innovation/_technology.py +203 -0
- skcomplex/models/economics/innovation/_technology_view.py +14 -0
- skcomplex/models/economics/macroeconomics/__init__.py +70 -0
- skcomplex/models/economics/macroeconomics/_banking.py +148 -0
- skcomplex/models/economics/macroeconomics/_business.py +221 -0
- skcomplex/models/economics/macroeconomics/_business_view.py +24 -0
- skcomplex/models/economics/macroeconomics/_capital.py +122 -0
- skcomplex/models/economics/macroeconomics/_central_bank.py +80 -0
- skcomplex/models/economics/macroeconomics/_central_bank_view.py +13 -0
- skcomplex/models/economics/macroeconomics/_circuit.py +93 -0
- skcomplex/models/economics/macroeconomics/_commons.py +77 -0
- skcomplex/models/economics/macroeconomics/_credit.py +219 -0
- skcomplex/models/economics/macroeconomics/_credit_market.py +83 -0
- skcomplex/models/economics/macroeconomics/_depositor.py +114 -0
- skcomplex/models/economics/macroeconomics/_depositor_view.py +19 -0
- skcomplex/models/economics/macroeconomics/_economy.py +42 -0
- skcomplex/models/economics/macroeconomics/_estate.py +88 -0
- skcomplex/models/economics/macroeconomics/_firm.py +184 -0
- skcomplex/models/economics/macroeconomics/_firm_view.py +27 -0
- skcomplex/models/economics/macroeconomics/_firms.py +208 -0
- skcomplex/models/economics/macroeconomics/_firms_element.py +67 -0
- skcomplex/models/economics/macroeconomics/_food_market.py +84 -0
- skcomplex/models/economics/macroeconomics/_growth.py +109 -0
- skcomplex/models/economics/macroeconomics/_households.py +52 -0
- skcomplex/models/economics/macroeconomics/_income.py +59 -0
- skcomplex/models/economics/macroeconomics/_investing_firm_view.py +21 -0
- skcomplex/models/economics/macroeconomics/_labour_market.py +73 -0
- skcomplex/models/economics/macroeconomics/_lender.py +160 -0
- skcomplex/models/economics/macroeconomics/_lender_view.py +18 -0
- skcomplex/models/economics/macroeconomics/_metaphoria.py +257 -0
- skcomplex/models/economics/macroeconomics/_monetary.py +140 -0
- skcomplex/models/economics/macroeconomics/_monetary_bank.py +57 -0
- skcomplex/models/economics/macroeconomics/_optimal_growth.py +173 -0
- skcomplex/models/economics/macroeconomics/_people_spec.py +26 -0
- skcomplex/models/economics/macroeconomics/_plot.py +69 -0
- skcomplex/models/economics/macroeconomics/_plot_view.py +15 -0
- skcomplex/models/economics/macroeconomics/_policy_switch.py +78 -0
- skcomplex/models/economics/macroeconomics/_reserve_bank.py +118 -0
- skcomplex/models/economics/macroeconomics/_reserve_bank_view.py +14 -0
- skcomplex/models/economics/macroeconomics/_settler.py +291 -0
- skcomplex/models/economics/macroeconomics/_settler_view.py +56 -0
- skcomplex/models/economics/macroeconomics/_solow_growth.py +70 -0
- skcomplex/models/economics/macroeconomics/_trade.py +289 -0
- skcomplex/models/economics/markets/__init__.py +128 -0
- skcomplex/models/economics/markets/_auction_ledger.py +81 -0
- skcomplex/models/economics/markets/_barter.py +232 -0
- skcomplex/models/economics/markets/_barter_networks.py +169 -0
- skcomplex/models/economics/markets/_barter_trader.py +136 -0
- skcomplex/models/economics/markets/_barter_trader_view.py +16 -0
- skcomplex/models/economics/markets/_bilateral_barter.py +150 -0
- skcomplex/models/economics/markets/_brewery.py +67 -0
- skcomplex/models/economics/markets/_brock_hommes.py +115 -0
- skcomplex/models/economics/markets/_car.py +75 -0
- skcomplex/models/economics/markets/_car_view.py +14 -0
- skcomplex/models/economics/markets/_car_wash_operation.py +141 -0
- skcomplex/models/economics/markets/_cobweb.py +109 -0
- skcomplex/models/economics/markets/_commodities.py +286 -0
- skcomplex/models/economics/markets/_consumer_view.py +22 -0
- skcomplex/models/economics/markets/_cournot_adjustment.py +65 -0
- skcomplex/models/economics/markets/_cournot_best_response.py +88 -0
- skcomplex/models/economics/markets/_customer.py +147 -0
- skcomplex/models/economics/markets/_customer_view.py +16 -0
- skcomplex/models/economics/markets/_double_auction.py +141 -0
- skcomplex/models/economics/markets/_duopolist.py +54 -0
- skcomplex/models/economics/markets/_duopolist_view.py +13 -0
- skcomplex/models/economics/markets/_duopoly.py +85 -0
- skcomplex/models/economics/markets/_echelon.py +132 -0
- skcomplex/models/economics/markets/_employer.py +102 -0
- skcomplex/models/economics/markets/_employer_view.py +20 -0
- skcomplex/models/economics/markets/_exchange.py +171 -0
- skcomplex/models/economics/markets/_exchange_interaction.py +134 -0
- skcomplex/models/economics/markets/_factory.py +105 -0
- skcomplex/models/economics/markets/_fair_food.py +205 -0
- skcomplex/models/economics/markets/_forager.py +64 -0
- skcomplex/models/economics/markets/_forager_view.py +14 -0
- skcomplex/models/economics/markets/_goods_trader.py +68 -0
- skcomplex/models/economics/markets/_goods_traders.py +139 -0
- skcomplex/models/economics/markets/_heuristic_pricing.py +122 -0
- skcomplex/models/economics/markets/_heuristic_trader.py +108 -0
- skcomplex/models/economics/markets/_heuristic_trader_view.py +14 -0
- skcomplex/models/economics/markets/_inventory.py +212 -0
- skcomplex/models/economics/markets/_jobseeker.py +144 -0
- skcomplex/models/economics/markets/_jobseeker_view.py +26 -0
- skcomplex/models/economics/markets/_labour.py +188 -0
- skcomplex/models/economics/markets/_market.py +39 -0
- skcomplex/models/economics/markets/_market_state_spec.py +25 -0
- skcomplex/models/economics/markets/_oligopoly.py +167 -0
- skcomplex/models/economics/markets/_patch_map_spec.py +22 -0
- skcomplex/models/economics/markets/_perishables.py +150 -0
- skcomplex/models/economics/markets/_price_point.py +95 -0
- skcomplex/models/economics/markets/_prices.py +151 -0
- skcomplex/models/economics/markets/_pricing_firm.py +48 -0
- skcomplex/models/economics/markets/_pricing_firm_view.py +14 -0
- skcomplex/models/economics/markets/_pricing_game_spec.py +81 -0
- skcomplex/models/economics/markets/_produce.py +94 -0
- skcomplex/models/economics/markets/_product.py +97 -0
- skcomplex/models/economics/markets/_product_view.py +13 -0
- skcomplex/models/economics/markets/_queues.py +101 -0
- skcomplex/models/economics/markets/_resident.py +119 -0
- skcomplex/models/economics/markets/_resident_view.py +20 -0
- skcomplex/models/economics/markets/_retail_demand.py +52 -0
- skcomplex/models/economics/markets/_retailer.py +115 -0
- skcomplex/models/economics/markets/_shopper.py +115 -0
- skcomplex/models/economics/markets/_shopper_view.py +15 -0
- skcomplex/models/economics/markets/_shops.py +199 -0
- skcomplex/models/economics/markets/_stall.py +74 -0
- skcomplex/models/economics/markets/_stall_view.py +14 -0
- skcomplex/models/economics/markets/_store.py +171 -0
- skcomplex/models/economics/markets/_store_view.py +27 -0
- skcomplex/models/economics/markets/_sugar_patch.py +61 -0
- skcomplex/models/economics/markets/_sugar_patch_view.py +14 -0
- skcomplex/models/economics/markets/_sugarscape.py +250 -0
- skcomplex/models/economics/markets/_supply_chains.py +217 -0
- skcomplex/models/economics/markets/_supply_link.py +74 -0
- skcomplex/models/economics/markets/_till.py +79 -0
- skcomplex/models/economics/markets/_till_view.py +15 -0
- skcomplex/models/economics/markets/_washer.py +78 -0
- skcomplex/models/economics/markets/_zero_intelligence_buyer.py +99 -0
- skcomplex/models/economics/markets/_zero_intelligence_buyer_view.py +20 -0
- skcomplex/models/economics/markets/_zero_intelligence_seller.py +100 -0
- skcomplex/models/economics/markets/_zero_intelligence_seller_view.py +20 -0
- skcomplex/models/economics/resources/__init__.py +50 -0
- skcomplex/models/economics/resources/_bid_rent.py +104 -0
- skcomplex/models/economics/resources/_commons.py +218 -0
- skcomplex/models/economics/resources/_cow.py +69 -0
- skcomplex/models/economics/resources/_cow_view.py +13 -0
- skcomplex/models/economics/resources/_extraction.py +230 -0
- skcomplex/models/economics/resources/_farmer.py +93 -0
- skcomplex/models/economics/resources/_farmer_view.py +12 -0
- skcomplex/models/economics/resources/_fisheries.py +384 -0
- skcomplex/models/economics/resources/_fishery.py +91 -0
- skcomplex/models/economics/resources/_food.py +370 -0
- skcomplex/models/economics/resources/_grazing.py +148 -0
- skcomplex/models/economics/resources/_harvest.py +69 -0
- skcomplex/models/economics/resources/_harvesting.py +51 -0
- skcomplex/models/economics/resources/_herder.py +78 -0
- skcomplex/models/economics/resources/_herder_view.py +19 -0
- skcomplex/models/economics/resources/_land_cell.py +39 -0
- skcomplex/models/economics/resources/_land_use.py +73 -0
- skcomplex/models/economics/resources/_oil_economy.py +85 -0
- skcomplex/models/economics/resources/_optimal_harvesting.py +180 -0
- skcomplex/models/economics/resources/_pasture.py +98 -0
- skcomplex/models/economics/resources/_pasture_view.py +15 -0
- skcomplex/models/economics/resources/_plantations.py +359 -0
- skcomplex/models/economics/resources/_quota_regulator.py +84 -0
- skcomplex/models/economics/resources/_stock.py +67 -0
- skcomplex/models/engineering/__init__.py +1 -0
- skcomplex/models/engineering/circuits/__init__.py +23 -0
- skcomplex/models/engineering/circuits/_chua_circuit.py +48 -0
- skcomplex/models/engineering/circuits/_circuit.py +47 -0
- skcomplex/models/engineering/circuits/_circuits.py +387 -0
- skcomplex/models/engineering/circuits/_harvesters.py +150 -0
- skcomplex/models/engineering/circuits/_kicked_circuit.py +43 -0
- skcomplex/models/engineering/circuits/_memristor_circuit.py +48 -0
- skcomplex/models/engineering/circuits/_mixed_mode_chua_circuit.py +54 -0
- skcomplex/models/engineering/circuits/_multiscroll_chua_circuit.py +58 -0
- skcomplex/models/engineering/circuits/_tunnel_diode_circuit.py +45 -0
- skcomplex/models/engineering/common/__init__.py +6 -0
- skcomplex/models/engineering/common/mechanics/__init__.py +7 -0
- skcomplex/models/engineering/common/mechanics/_spring_damper.py +121 -0
- skcomplex/models/engineering/control/__init__.py +23 -0
- skcomplex/models/engineering/control/_cart_pendulum.py +119 -0
- skcomplex/models/engineering/control/_control.py +266 -0
- skcomplex/models/engineering/control/_controlled_process.py +72 -0
- skcomplex/models/engineering/control/_driven_oscillator.py +79 -0
- skcomplex/models/engineering/control/_integrator.py +39 -0
- skcomplex/models/engineering/control/_pid.py +106 -0
- skcomplex/models/engineering/control/_regulation.py +170 -0
- skcomplex/models/engineering/control/_room.py +51 -0
- skcomplex/models/engineering/control/_satellite.py +56 -0
- skcomplex/models/engineering/control/_state_feedback.py +82 -0
- skcomplex/models/engineering/control/_swinging_pendulum.py +60 -0
- skcomplex/models/engineering/power_systems/__init__.py +11 -0
- skcomplex/models/engineering/power_systems/_electromechanics.py +224 -0
- skcomplex/models/engineering/power_systems/_faraday_disk.py +93 -0
- skcomplex/models/engineering/power_systems/_grid_node.py +39 -0
- skcomplex/models/engineering/power_systems/_grids.py +89 -0
- skcomplex/models/engineering/power_systems/_rail_segment.py +80 -0
- skcomplex/models/engineering/power_systems/_regenerative_car.py +55 -0
- skcomplex/models/engineering/power_systems/_transmission_line.py +48 -0
- skcomplex/models/engineering/processes/__init__.py +13 -0
- skcomplex/models/engineering/processes/_irrigation_scheme.py +112 -0
- skcomplex/models/engineering/processes/_processes.py +115 -0
- skcomplex/models/engineering/processes/_relief_pipeline.py +79 -0
- skcomplex/models/engineering/processes/_rice_mill.py +112 -0
- skcomplex/models/engineering/processes/_stage.py +34 -0
- skcomplex/models/engineering/processes/_systems.py +316 -0
- skcomplex/models/engineering/processes/_tub.py +42 -0
- skcomplex/models/engineering/processes/_waste_system.py +101 -0
- skcomplex/models/engineering/robotics/__init__.py +12 -0
- skcomplex/models/engineering/robotics/_light_sensitive_robot.py +125 -0
- skcomplex/models/engineering/robotics/_robots.py +177 -0
- skcomplex/models/engineering/robotics/_swarm_robot.py +211 -0
- skcomplex/models/engineering/robotics/_swarm_robot_view.py +23 -0
- skcomplex/models/engineering/traffic/__init__.py +43 -0
- skcomplex/models/engineering/traffic/_arrival.py +117 -0
- skcomplex/models/engineering/traffic/_cab.py +170 -0
- skcomplex/models/engineering/traffic/_cab_view.py +21 -0
- skcomplex/models/engineering/traffic/_car.py +31 -0
- skcomplex/models/engineering/traffic/_car_following.py +245 -0
- skcomplex/models/engineering/traffic/_careless_braking.py +87 -0
- skcomplex/models/engineering/traffic/_continuum.py +429 -0
- skcomplex/models/engineering/traffic/_delayed_following.py +65 -0
- skcomplex/models/engineering/traffic/_driver.py +140 -0
- skcomplex/models/engineering/traffic/_driver_view.py +18 -0
- skcomplex/models/engineering/traffic/_drivers.py +133 -0
- skcomplex/models/engineering/traffic/_gas_kinetic_traffic.py +96 -0
- skcomplex/models/engineering/traffic/_intelligent_driver.py +90 -0
- skcomplex/models/engineering/traffic/_kerner_konhauser.py +42 -0
- skcomplex/models/engineering/traffic/_langevin.py +170 -0
- skcomplex/models/engineering/traffic/_langevin_driving.py +95 -0
- skcomplex/models/engineering/traffic/_lead_car.py +40 -0
- skcomplex/models/engineering/traffic/_lighthill_whitham_richards.py +30 -0
- skcomplex/models/engineering/traffic/_motorist.py +118 -0
- skcomplex/models/engineering/traffic/_motorist_view.py +18 -0
- skcomplex/models/engineering/traffic/_optimal_velocity.py +72 -0
- skcomplex/models/engineering/traffic/_payne.py +38 -0
- skcomplex/models/engineering/traffic/_rider.py +72 -0
- skcomplex/models/engineering/traffic/_rider_view.py +16 -0
- skcomplex/models/engineering/traffic/_ridesharing.py +179 -0
- skcomplex/models/engineering/traffic/_traffic.py +143 -0
- skcomplex/models/engineering/traffic/_traffic_moments.py +57 -0
- skcomplex/models/mathematics/__init__.py +1 -0
- skcomplex/models/mathematics/common/__init__.py +3 -0
- skcomplex/models/mathematics/common/flows/__init__.py +7 -0
- skcomplex/models/mathematics/common/flows/_lorenz.py +90 -0
- skcomplex/models/mathematics/dynamical_systems/__init__.py +90 -0
- skcomplex/models/mathematics/dynamical_systems/_baker_map.py +59 -0
- skcomplex/models/mathematics/dynamical_systems/_blow_up.py +64 -0
- skcomplex/models/mathematics/dynamical_systems/_cat_map.py +44 -0
- skcomplex/models/mathematics/dynamical_systems/_chaotic_ensembles.py +186 -0
- skcomplex/models/mathematics/dynamical_systems/_circle_map.py +49 -0
- skcomplex/models/mathematics/dynamical_systems/_cubic_walk.py +72 -0
- skcomplex/models/mathematics/dynamical_systems/_cusp.py +64 -0
- skcomplex/models/mathematics/dynamical_systems/_doubling_map.py +65 -0
- skcomplex/models/mathematics/dynamical_systems/_driven_flows.py +158 -0
- skcomplex/models/mathematics/dynamical_systems/_flows.py +179 -0
- skcomplex/models/mathematics/dynamical_systems/_henon_map.py +54 -0
- skcomplex/models/mathematics/dynamical_systems/_hopf.py +77 -0
- skcomplex/models/mathematics/dynamical_systems/_intermittency_map.py +44 -0
- skcomplex/models/mathematics/dynamical_systems/_jerk.py +72 -0
- skcomplex/models/mathematics/dynamical_systems/_koopman.py +118 -0
- skcomplex/models/mathematics/dynamical_systems/_logistic_map.py +44 -0
- skcomplex/models/mathematics/dynamical_systems/_maps.py +465 -0
- skcomplex/models/mathematics/dynamical_systems/_newton_map.py +44 -0
- skcomplex/models/mathematics/dynamical_systems/_normal_forms.py +154 -0
- skcomplex/models/mathematics/dynamical_systems/_rossler.py +83 -0
- skcomplex/models/mathematics/dynamical_systems/_saddle_node.py +59 -0
- skcomplex/models/mathematics/dynamical_systems/_skew_tent_map.py +63 -0
- skcomplex/models/mathematics/dynamical_systems/_standard_map.py +52 -0
- skcomplex/models/mathematics/dynamical_systems/_subcritical_forms.py +160 -0
- skcomplex/models/mathematics/dynamical_systems/_takens_bogdanov.py +74 -0
- skcomplex/models/mathematics/dynamical_systems/_tent_map.py +44 -0
- skcomplex/models/mathematics/dynamical_systems/_towel_map.py +59 -0
- skcomplex/models/mathematics/fractals/__init__.py +61 -0
- skcomplex/models/mathematics/fractals/_affine_spec.py +100 -0
- skcomplex/models/mathematics/fractals/_cantor_element.py +92 -0
- skcomplex/models/mathematics/fractals/_chaos_game.py +140 -0
- skcomplex/models/mathematics/fractals/_geometry_spec.py +84 -0
- skcomplex/models/mathematics/fractals/_geometry_visual.py +190 -0
- skcomplex/models/mathematics/fractals/_group_spec.py +24 -0
- skcomplex/models/mathematics/fractals/_koch_element.py +43 -0
- skcomplex/models/mathematics/fractals/_module_spec.py +47 -0
- skcomplex/models/mathematics/fractals/_patch_element.py +89 -0
- skcomplex/models/mathematics/fractals/_patch_kernel.py +200 -0
- skcomplex/models/mathematics/fractals/_patch_structure_spec.py +108 -0
- skcomplex/models/mathematics/fractals/_production_law.py +105 -0
- skcomplex/models/mathematics/fractals/_prototile_spec.py +53 -0
- skcomplex/models/mathematics/fractals/_quadratic.py +191 -0
- skcomplex/models/mathematics/fractals/_random_affine_map.py +100 -0
- skcomplex/models/mathematics/fractals/_rewriting_compiler.py +300 -0
- skcomplex/models/mathematics/fractals/_rewriting_error.py +10 -0
- skcomplex/models/mathematics/fractals/_rewriting_loops.py +180 -0
- skcomplex/models/mathematics/fractals/_rewriting_problem_spec.py +30 -0
- skcomplex/models/mathematics/fractals/_rewriting_solver.py +125 -0
- skcomplex/models/mathematics/fractals/_sierpinski_element.py +110 -0
- skcomplex/models/mathematics/fractals/_substitution.py +130 -0
- skcomplex/models/mathematics/fractals/_substitution_law.py +76 -0
- skcomplex/models/mathematics/fractals/_successor_spec.py +23 -0
- skcomplex/models/mathematics/fractals/_word_element.py +94 -0
- skcomplex/models/mathematics/fractals/_word_kernel.py +526 -0
- skcomplex/models/mathematics/fractals/_word_structure_spec.py +110 -0
- skcomplex/models/mathematics/fractals/_words.py +38 -0
- skcomplex/models/mathematics/fractals/types.py +12 -0
- skcomplex/models/mathematics/fractional_dynamics/__init__.py +29 -0
- skcomplex/models/mathematics/fractional_dynamics/_fractional.py +338 -0
- skcomplex/models/mathematics/fractional_dynamics/_oscillator.py +71 -0
- skcomplex/models/mathematics/fractional_dynamics/_relaxation.py +59 -0
- skcomplex/models/mathematics/fractional_dynamics/_van_der_pol.py +66 -0
- skcomplex/models/mathematics/networks/__init__.py +61 -0
- skcomplex/models/mathematics/networks/_copying_vertex.py +50 -0
- skcomplex/models/mathematics/networks/_ensemble_node.py +48 -0
- skcomplex/models/mathematics/networks/_ensembles.py +195 -0
- skcomplex/models/mathematics/networks/_failing.py +58 -0
- skcomplex/models/mathematics/networks/_giant_component.py +52 -0
- skcomplex/models/mathematics/networks/_growth.py +223 -0
- skcomplex/models/mathematics/networks/_hypergraphs.py +131 -0
- skcomplex/models/mathematics/networks/_link.py +21 -0
- skcomplex/models/mathematics/networks/_network_measures.py +59 -0
- skcomplex/models/mathematics/networks/_network_node.py +86 -0
- skcomplex/models/mathematics/networks/_network_walker.py +49 -0
- skcomplex/models/mathematics/networks/_network_walker_view.py +12 -0
- skcomplex/models/mathematics/networks/_node_content.py +47 -0
- skcomplex/models/mathematics/networks/_node_rank.py +57 -0
- skcomplex/models/mathematics/networks/_processes.py +148 -0
- skcomplex/models/mathematics/networks/_regulated_link.py +47 -0
- skcomplex/models/mathematics/networks/_regulated_node.py +43 -0
- skcomplex/models/mathematics/networks/_simplex.py +46 -0
- skcomplex/models/mathematics/networks/_simplex_ageing.py +46 -0
- skcomplex/models/mathematics/networks/_size_biased_move.py +44 -0
- skcomplex/models/mathematics/networks/_structure.py +170 -0
- skcomplex/models/mathematics/networks/_triad_vertex.py +64 -0
- skcomplex/models/mathematics/networks/_triadic.py +114 -0
- skcomplex/models/mathematics/networks/_triadic_regulation.py +65 -0
- skcomplex/models/mathematics/networks/_vertex.py +52 -0
- skcomplex/models/mathematics/networks/_walker_density.py +51 -0
- skcomplex/models/mathematics/stochastic_processes/__init__.py +62 -0
- skcomplex/models/mathematics/stochastic_processes/_ageing_walker.py +68 -0
- skcomplex/models/mathematics/stochastic_processes/_ageing_walker_view.py +15 -0
- skcomplex/models/mathematics/stochastic_processes/_bernoulli_trial.py +61 -0
- skcomplex/models/mathematics/stochastic_processes/_bernoulli_trial_view.py +14 -0
- skcomplex/models/mathematics/stochastic_processes/_branching.py +103 -0
- skcomplex/models/mathematics/stochastic_processes/_counting.py +88 -0
- skcomplex/models/mathematics/stochastic_processes/_fragment.py +91 -0
- skcomplex/models/mathematics/stochastic_processes/_fragment_view.py +13 -0
- skcomplex/models/mathematics/stochastic_processes/_hidden_markov_source.py +46 -0
- skcomplex/models/mathematics/stochastic_processes/_individual_view.py +13 -0
- skcomplex/models/mathematics/stochastic_processes/_intermittency.py +115 -0
- skcomplex/models/mathematics/stochastic_processes/_markov_source.py +41 -0
- skcomplex/models/mathematics/stochastic_processes/_memory_walker.py +57 -0
- skcomplex/models/mathematics/stochastic_processes/_persistent_walker.py +52 -0
- skcomplex/models/mathematics/stochastic_processes/_poisson_counter.py +47 -0
- skcomplex/models/mathematics/stochastic_processes/_queues.py +117 -0
- skcomplex/models/mathematics/stochastic_processes/_random_walker.py +52 -0
- skcomplex/models/mathematics/stochastic_processes/_reducing.py +104 -0
- skcomplex/models/mathematics/stochastic_processes/_reducing_ball.py +63 -0
- skcomplex/models/mathematics/stochastic_processes/_reducing_ball_view.py +14 -0
- skcomplex/models/mathematics/stochastic_processes/_reducing_jump.py +44 -0
- skcomplex/models/mathematics/stochastic_processes/_sources.py +90 -0
- skcomplex/models/mathematics/stochastic_processes/_urns.py +112 -0
- skcomplex/models/mathematics/stochastic_processes/_walks.py +280 -0
- skcomplex/models/mathematics/stochastic_processes/_weakening_particle.py +57 -0
- skcomplex/models/mathematics/stochastic_processes/types.py +8 -0
- skcomplex/models/physics/__init__.py +1 -0
- skcomplex/models/physics/active_matter/__init__.py +95 -0
- skcomplex/models/physics/active_matter/_active_particle.py +88 -0
- skcomplex/models/physics/active_matter/_alignment.py +192 -0
- skcomplex/models/physics/active_matter/_angular_alignment.py +98 -0
- skcomplex/models/physics/active_matter/_angular_diffusion.py +67 -0
- skcomplex/models/physics/active_matter/_binary_collisions.py +126 -0
- skcomplex/models/physics/active_matter/_chemotaxis.py +173 -0
- skcomplex/models/physics/active_matter/_cohesive_particle.py +132 -0
- skcomplex/models/physics/active_matter/_collective.py +327 -0
- skcomplex/models/physics/active_matter/_collisions.py +127 -0
- skcomplex/models/physics/active_matter/_contractile_gel_site.py +81 -0
- skcomplex/models/physics/active_matter/_cucker_smale_alignment.py +89 -0
- skcomplex/models/physics/active_matter/_depot_particle.py +103 -0
- skcomplex/models/physics/active_matter/_flocker.py +46 -0
- skcomplex/models/physics/active_matter/_flocker_view.py +20 -0
- skcomplex/models/physics/active_matter/_flocks.py +258 -0
- skcomplex/models/physics/active_matter/_gels.py +141 -0
- skcomplex/models/physics/active_matter/_heading_alignment.py +73 -0
- skcomplex/models/physics/active_matter/_kinetic_flocks.py +111 -0
- skcomplex/models/physics/active_matter/_landau_de_gennes_energy.py +107 -0
- skcomplex/models/physics/active_matter/_model_b.py +170 -0
- skcomplex/models/physics/active_matter/_nematic_density_site.py +78 -0
- skcomplex/models/physics/active_matter/_nematic_gel_site.py +115 -0
- skcomplex/models/physics/active_matter/_nematic_particle.py +61 -0
- skcomplex/models/physics/active_matter/_nematics.py +323 -0
- skcomplex/models/physics/active_matter/_nonreciprocal.py +214 -0
- skcomplex/models/physics/active_matter/_ornstein_uhlenbeck_particle.py +87 -0
- skcomplex/models/physics/active_matter/_particles.py +323 -0
- skcomplex/models/physics/active_matter/_phoretic_attraction.py +80 -0
- skcomplex/models/physics/active_matter/_polar_fluid.py +119 -0
- skcomplex/models/physics/active_matter/_polar_gel_site.py +120 -0
- skcomplex/models/physics/active_matter/_propulsion_step.py +64 -0
- skcomplex/models/physics/active_matter/_self_propulsion.py +73 -0
- skcomplex/models/physics/active_matter/_tumbler.py +100 -0
- skcomplex/models/physics/active_matter/_tumbler_view.py +23 -0
- skcomplex/models/physics/active_matter/_vicsek_particle.py +61 -0
- skcomplex/models/physics/celestial_mechanics/__init__.py +19 -0
- skcomplex/models/physics/celestial_mechanics/_dipoles.py +160 -0
- skcomplex/models/physics/celestial_mechanics/_kepler_body.py +76 -0
- skcomplex/models/physics/celestial_mechanics/_orbits.py +332 -0
- skcomplex/models/physics/celestial_mechanics/_rotating_frame_body.py +72 -0
- skcomplex/models/physics/celestial_mechanics/_sitnikov_body.py +54 -0
- skcomplex/models/physics/celestial_mechanics/types.py +6 -0
- skcomplex/models/physics/climate/__init__.py +60 -0
- skcomplex/models/physics/climate/_carbon_cycle.py +169 -0
- skcomplex/models/physics/climate/_climate_anomaly.py +55 -0
- skcomplex/models/physics/climate/_daisyworld.py +158 -0
- skcomplex/models/physics/climate/_delayed_oscillator.py +68 -0
- skcomplex/models/physics/climate/_early_warning.py +102 -0
- skcomplex/models/physics/climate/_energy_balance.py +207 -0
- skcomplex/models/physics/climate/_geodynamo.py +86 -0
- skcomplex/models/physics/climate/_ice_ages.py +179 -0
- skcomplex/models/physics/climate/_ice_albedo_climate.py +100 -0
- skcomplex/models/physics/climate/_latitude_band.py +156 -0
- skcomplex/models/physics/climate/_lorenz84.py +91 -0
- skcomplex/models/physics/climate/_lorenz96.py +67 -0
- skcomplex/models/physics/climate/_low_order.py +162 -0
- skcomplex/models/physics/climate/_net_energy.py +210 -0
- skcomplex/models/physics/climate/_ramped_fold.py +92 -0
- skcomplex/models/physics/climate/_saltzman_maasch.py +123 -0
- skcomplex/models/physics/climate/_soil.py +116 -0
- skcomplex/models/physics/climate/_stochastic_energy_balance.py +124 -0
- skcomplex/models/physics/climate/_tipping.py +141 -0
- skcomplex/models/physics/climate/_tipping_types.py +159 -0
- skcomplex/models/physics/climate/_van_der_pol_ice_ages.py +101 -0
- skcomplex/models/physics/climate/_variability.py +103 -0
- skcomplex/models/physics/common/__init__.py +6 -0
- skcomplex/models/physics/common/fields/__init__.py +14 -0
- skcomplex/models/physics/common/fields/_landau_energy.py +76 -0
- skcomplex/models/physics/common/fields/_phase_field.py +43 -0
- skcomplex/models/physics/common/fields/_swift_hohenberg_energy.py +74 -0
- skcomplex/models/physics/common/fields/_transports.py +119 -0
- skcomplex/models/physics/common/mechanics/__init__.py +5 -0
- skcomplex/models/physics/common/mechanics/_reflection.py +139 -0
- skcomplex/models/physics/common/oscillators/__init__.py +13 -0
- skcomplex/models/physics/common/oscillators/_kuramoto_coupling.py +140 -0
- skcomplex/models/physics/common/oscillators/_phase_oscillator.py +68 -0
- skcomplex/models/physics/common/oscillators/_sited_oscillator.py +55 -0
- skcomplex/models/physics/common/oscillators/_stuart_landau.py +106 -0
- skcomplex/models/physics/common/particles/__init__.py +28 -0
- skcomplex/models/physics/common/particles/_constant_force.py +65 -0
- skcomplex/models/physics/common/particles/_damping.py +72 -0
- skcomplex/models/physics/common/particles/_gravity.py +74 -0
- skcomplex/models/physics/common/particles/_harmonic_potential.py +77 -0
- skcomplex/models/physics/common/particles/_lammps.py +47 -0
- skcomplex/models/physics/common/particles/_langevin_thermostat.py +103 -0
- skcomplex/models/physics/common/particles/_lennard_jones.py +87 -0
- skcomplex/models/physics/common/particles/_mass_point.py +57 -0
- skcomplex/models/physics/common/particles/_potential_energy.py +56 -0
- skcomplex/models/physics/common/particles/_soft_sphere.py +82 -0
- skcomplex/models/physics/common/particles/_spring.py +78 -0
- skcomplex/models/physics/common/particles/_utils.py +25 -0
- skcomplex/models/physics/common/quantum/__init__.py +18 -0
- skcomplex/models/physics/common/quantum/_mode.py +46 -0
- skcomplex/models/physics/common/quantum/_quantum.py +127 -0
- skcomplex/models/physics/common/quantum/_qubit.py +61 -0
- skcomplex/models/physics/common/quantum/_site.py +49 -0
- skcomplex/models/physics/common/quantum/_spin.py +92 -0
- skcomplex/models/physics/common/spins/__init__.py +15 -0
- skcomplex/models/physics/common/spins/_ising_sampling.py +75 -0
- skcomplex/models/physics/common/spins/_potts_sampling.py +73 -0
- skcomplex/models/physics/common/spins/_spin_sampling.py +100 -0
- skcomplex/models/physics/common/spins/_thermal_sampling.py +105 -0
- skcomplex/models/physics/common/spins/_xy_sampling.py +67 -0
- skcomplex/models/physics/cosmology/__init__.py +8 -0
- skcomplex/models/physics/cosmology/_expansion.py +148 -0
- skcomplex/models/physics/criticality/__init__.py +29 -0
- skcomplex/models/physics/criticality/_absorbing.py +210 -0
- skcomplex/models/physics/criticality/_avalanche.py +69 -0
- skcomplex/models/physics/criticality/_crackling_noise.py +129 -0
- skcomplex/models/physics/criticality/_criticality.py +235 -0
- skcomplex/models/physics/criticality/_evolutionary_learning.py +231 -0
- skcomplex/models/physics/criticality/_fire.py +70 -0
- skcomplex/models/physics/criticality/_forest.py +55 -0
- skcomplex/models/physics/criticality/_learning.py +175 -0
- skcomplex/models/physics/criticality/_sandpile_cell.py +47 -0
- skcomplex/models/physics/fluids/__init__.py +49 -0
- skcomplex/models/physics/fluids/_bhatnagar_gross_krook.py +54 -0
- skcomplex/models/physics/fluids/_boussinesq.py +62 -0
- skcomplex/models/physics/fluids/_burgers.py +39 -0
- skcomplex/models/physics/fluids/_carleman_gas.py +61 -0
- skcomplex/models/physics/fluids/_flows.py +436 -0
- skcomplex/models/physics/fluids/_kinetic_equations.py +327 -0
- skcomplex/models/physics/fluids/_kinetics.py +147 -0
- skcomplex/models/physics/fluids/_kuramoto_sivashinsky.py +41 -0
- skcomplex/models/physics/fluids/_lattice_gases.py +217 -0
- skcomplex/models/physics/fluids/_marangoni.py +136 -0
- skcomplex/models/physics/fluids/_shallow_water.py +55 -0
- skcomplex/models/physics/fluids/_vorticity.py +56 -0
- skcomplex/models/physics/fluids/_wave_number.py +50 -0
- skcomplex/models/physics/heat/__init__.py +13 -0
- skcomplex/models/physics/heat/_cooling.py +96 -0
- skcomplex/models/physics/heat/_heat.py +182 -0
- skcomplex/models/physics/mechanics/__init__.py +93 -0
- skcomplex/models/physics/mechanics/_ballistic_pendulum.py +80 -0
- skcomplex/models/physics/mechanics/_bouncing_ball.py +51 -0
- skcomplex/models/physics/mechanics/_cart_pendulum.py +92 -0
- skcomplex/models/physics/mechanics/_cart_pendulum_interaction.py +57 -0
- skcomplex/models/physics/mechanics/_clock_pendulum.py +94 -0
- skcomplex/models/physics/mechanics/_clock_pendulum_interaction.py +60 -0
- skcomplex/models/physics/mechanics/_disc_billiard.py +90 -0
- skcomplex/models/physics/mechanics/_double_pendulum.py +95 -0
- skcomplex/models/physics/mechanics/_double_pendulum_interaction.py +53 -0
- skcomplex/models/physics/mechanics/_elastic_collision.py +78 -0
- skcomplex/models/physics/mechanics/_gyroscope.py +105 -0
- skcomplex/models/physics/mechanics/_gyroscope_interaction.py +57 -0
- skcomplex/models/physics/mechanics/_hanging_ball.py +65 -0
- skcomplex/models/physics/mechanics/_magnet.py +70 -0
- skcomplex/models/physics/mechanics/_mechanics.py +426 -0
- skcomplex/models/physics/mechanics/_parametric_pendulum.py +75 -0
- skcomplex/models/physics/mechanics/_parametric_pendulum_interaction.py +56 -0
- skcomplex/models/physics/mechanics/_pendulum.py +73 -0
- skcomplex/models/physics/mechanics/_pendulum_interaction.py +52 -0
- skcomplex/models/physics/mechanics/_pendulum_spring.py +68 -0
- skcomplex/models/physics/mechanics/_pendulums.py +547 -0
- skcomplex/models/physics/mechanics/_rotating_ball.py +66 -0
- skcomplex/models/physics/mechanics/_rotating_swing.py +100 -0
- skcomplex/models/physics/mechanics/_rotating_swing_interaction.py +70 -0
- skcomplex/models/physics/mechanics/_rotations.py +244 -0
- skcomplex/models/physics/mechanics/_springs.py +176 -0
- skcomplex/models/physics/mechanics/_support_spring.py +65 -0
- skcomplex/models/physics/mechanics/_wells.py +102 -0
- skcomplex/models/physics/nonlinear_oscillators/__init__.py +26 -0
- skcomplex/models/physics/nonlinear_oscillators/_adler_phase.py +73 -0
- skcomplex/models/physics/nonlinear_oscillators/_billiards.py +137 -0
- skcomplex/models/physics/nonlinear_oscillators/_duffing.py +78 -0
- skcomplex/models/physics/nonlinear_oscillators/_henon_heiles.py +57 -0
- skcomplex/models/physics/nonlinear_oscillators/_mushroom_billiard.py +96 -0
- skcomplex/models/physics/nonlinear_oscillators/_oscillators.py +313 -0
- skcomplex/models/physics/nonlinear_oscillators/_sinai_billiard.py +101 -0
- skcomplex/models/physics/nonlinear_oscillators/_van_der_pol.py +92 -0
- skcomplex/models/physics/oceanography/__init__.py +12 -0
- skcomplex/models/physics/oceanography/_gyres.py +145 -0
- skcomplex/models/physics/oceanography/_quasi_geostrophic_site.py +66 -0
- skcomplex/models/physics/oceanography/_thermohaline.py +133 -0
- skcomplex/models/physics/pattern_formation/__init__.py +18 -0
- skcomplex/models/physics/pattern_formation/_conserved.py +168 -0
- skcomplex/models/physics/pattern_formation/_ginzburg_landau.py +83 -0
- skcomplex/models/physics/pattern_formation/_ordering.py +183 -0
- skcomplex/models/physics/pattern_formation/_pattern_field.py +37 -0
- skcomplex/models/physics/pattern_formation/_patterns.py +135 -0
- skcomplex/models/physics/seismology/__init__.py +11 -0
- skcomplex/models/physics/seismology/_faults.py +118 -0
- skcomplex/models/physics/seismology/_spring_blocks.py +175 -0
- skcomplex/models/physics/soft_matter/__init__.py +76 -0
- skcomplex/models/physics/soft_matter/_anomalous.py +331 -0
- skcomplex/models/physics/soft_matter/_brownian.py +137 -0
- skcomplex/models/physics/soft_matter/_brownian_particle.py +58 -0
- skcomplex/models/physics/soft_matter/_colored_noise.py +137 -0
- skcomplex/models/physics/soft_matter/_continuous_time_walker.py +62 -0
- skcomplex/models/physics/soft_matter/_diffusion.py +418 -0
- skcomplex/models/physics/soft_matter/_double_well.py +57 -0
- skcomplex/models/physics/soft_matter/_flashing_sawtooth.py +82 -0
- skcomplex/models/physics/soft_matter/_fractional_walker.py +54 -0
- skcomplex/models/physics/soft_matter/_friction.py +214 -0
- skcomplex/models/physics/soft_matter/_levy_flier.py +54 -0
- skcomplex/models/physics/soft_matter/_levy_walker.py +67 -0
- skcomplex/models/physics/soft_matter/_modulated_particle.py +76 -0
- skcomplex/models/physics/soft_matter/_optical_trap.py +93 -0
- skcomplex/models/physics/soft_matter/_ratchets.py +163 -0
- skcomplex/models/physics/soft_matter/_scaled_walker.py +57 -0
- skcomplex/models/physics/soft_matter/_speckle_field.py +81 -0
- skcomplex/models/physics/soft_matter/_thermal_noise.py +52 -0
- skcomplex/models/physics/soft_matter/_tilted_washboard.py +70 -0
- skcomplex/models/physics/soft_matter/_transient_walker.py +61 -0
- skcomplex/models/physics/soft_matter/_traps.py +166 -0
- skcomplex/models/physics/soft_matter/_wall_particle.py +72 -0
- skcomplex/models/physics/statistical_mechanics/__init__.py +114 -0
- skcomplex/models/physics/statistical_mechanics/_absorbing_processes.py +156 -0
- skcomplex/models/physics/statistical_mechanics/_boltzmann_average.py +44 -0
- skcomplex/models/physics/statistical_mechanics/_boltzmann_sum.py +83 -0
- skcomplex/models/physics/statistical_mechanics/_bond_sampling.py +46 -0
- skcomplex/models/physics/statistical_mechanics/_bond_spin.py +76 -0
- skcomplex/models/physics/statistical_mechanics/_contact_site.py +85 -0
- skcomplex/models/physics/statistical_mechanics/_dephasing.py +59 -0
- skcomplex/models/physics/statistical_mechanics/_disk.py +36 -0
- skcomplex/models/physics/statistical_mechanics/_driven_particles.py +250 -0
- skcomplex/models/physics/statistical_mechanics/_energy_level.py +30 -0
- skcomplex/models/physics/statistical_mechanics/_exclusion_hops.py +76 -0
- skcomplex/models/physics/statistical_mechanics/_exclusion_site.py +61 -0
- skcomplex/models/physics/statistical_mechanics/_fully_connected_spins.py +232 -0
- skcomplex/models/physics/statistical_mechanics/_gases.py +156 -0
- skcomplex/models/physics/statistical_mechanics/_graph_spins.py +93 -0
- skcomplex/models/physics/statistical_mechanics/_ising_spin.py +63 -0
- skcomplex/models/physics/statistical_mechanics/_kinetic_temperature.py +66 -0
- skcomplex/models/physics/statistical_mechanics/_master_equations.py +171 -0
- skcomplex/models/physics/statistical_mechanics/_mattis_spin.py +79 -0
- skcomplex/models/physics/statistical_mechanics/_maxwell_boltzmann.py +96 -0
- skcomplex/models/physics/statistical_mechanics/_microstate.py +102 -0
- skcomplex/models/physics/statistical_mechanics/_order_parameter.py +90 -0
- skcomplex/models/physics/statistical_mechanics/_particle_site.py +41 -0
- skcomplex/models/physics/statistical_mechanics/_percolation.py +60 -0
- skcomplex/models/physics/statistical_mechanics/_percolation_site.py +73 -0
- skcomplex/models/physics/statistical_mechanics/_potts_spin.py +58 -0
- skcomplex/models/physics/statistical_mechanics/_processes.py +355 -0
- skcomplex/models/physics/statistical_mechanics/_q2r_spin.py +51 -0
- skcomplex/models/physics/statistical_mechanics/_quantum_spins.py +153 -0
- skcomplex/models/physics/statistical_mechanics/_random_energy.py +68 -0
- skcomplex/models/physics/statistical_mechanics/_reservoir.py +81 -0
- skcomplex/models/physics/statistical_mechanics/_spin_glasses.py +203 -0
- skcomplex/models/physics/statistical_mechanics/_spins.py +200 -0
- skcomplex/models/physics/statistical_mechanics/_susceptibility.py +112 -0
- skcomplex/models/physics/statistical_mechanics/_traps.py +135 -0
- skcomplex/models/physics/statistical_mechanics/_tree_node.py +48 -0
- skcomplex/models/physics/statistical_mechanics/_urns.py +107 -0
- skcomplex/models/physics/statistical_mechanics/_walker.py +81 -0
- skcomplex/models/physics/statistical_mechanics/_walker_view.py +20 -0
- skcomplex/models/physics/statistical_mechanics/_xxz_exchange.py +67 -0
- skcomplex/models/physics/statistical_mechanics/_xy_spin.py +58 -0
- skcomplex/models/physics/statistical_mechanics/_zeeman_field.py +56 -0
- skcomplex/models/physics/statistical_mechanics/_zero_range_hop.py +86 -0
- skcomplex/models/physics/statistical_mechanics/_zero_range_hops.py +81 -0
- skcomplex/models/physics/statistical_mechanics/_zone.py +78 -0
- skcomplex/models/physics/synchronization/__init__.py +64 -0
- skcomplex/models/physics/synchronization/_aggregate_averaging.py +63 -0
- skcomplex/models/physics/synchronization/_amplitude_death.py +278 -0
- skcomplex/models/physics/synchronization/_chaos.py +152 -0
- skcomplex/models/physics/synchronization/_diffusive_coupling.py +69 -0
- skcomplex/models/physics/synchronization/_edge_coupling.py +50 -0
- skcomplex/models/physics/synchronization/_hypergraphs.py +166 -0
- skcomplex/models/physics/synchronization/_integrate_and_fire_oscillator.py +80 -0
- skcomplex/models/physics/synchronization/_kuramoto.py +423 -0
- skcomplex/models/physics/synchronization/_link.py +46 -0
- skcomplex/models/physics/synchronization/_logistic_coupling.py +78 -0
- skcomplex/models/physics/synchronization/_logistic_node.py +59 -0
- skcomplex/models/physics/synchronization/_logistic_unit.py +43 -0
- skcomplex/models/physics/synchronization/_networks.py +184 -0
- skcomplex/models/physics/synchronization/_pulses.py +138 -0
- skcomplex/models/physics/synchronization/_rossler_oscillator.py +95 -0
- skcomplex/models/physics/synchronization/_swarmalator.py +48 -0
- skcomplex/models/physics/synchronization/_swarmalators.py +182 -0
- skcomplex/models/physics/synchronization/_utils.py +29 -0
- skcomplex/models/physics/synchronization/_winfree_mean_field.py +62 -0
- skcomplex/models/physics/waves/__init__.py +23 -0
- skcomplex/models/physics/waves/_charged.py +203 -0
- skcomplex/models/physics/waves/_driven_anchor.py +63 -0
- skcomplex/models/physics/waves/_lattice_hamiltonian.py +60 -0
- skcomplex/models/physics/waves/_position_dephasing.py +64 -0
- skcomplex/models/physics/waves/_quantum.py +125 -0
- skcomplex/models/physics/waves/_strings.py +169 -0
- skcomplex/models/physics/waves/_wave_function.py +79 -0
- skcomplex/models/physics/waves/_wave_string.py +52 -0
- skcomplex/models/social/__init__.py +1 -0
- skcomplex/models/social/cooperation/__init__.py +34 -0
- skcomplex/models/social/cooperation/_contributor.py +62 -0
- skcomplex/models/social/cooperation/_dilemma.py +56 -0
- skcomplex/models/social/cooperation/_hyperedge_goods.py +54 -0
- skcomplex/models/social/cooperation/_hypergraph_games.py +249 -0
- skcomplex/models/social/cooperation/_prisoner.py +56 -0
- skcomplex/models/social/cooperation/_prisoners_dilemma.py +126 -0
- skcomplex/models/social/cooperation/_public_goods.py +54 -0
- skcomplex/models/social/cooperation/_simplicial_dilemma.py +119 -0
- skcomplex/models/social/cooperation/_spatial_games.py +159 -0
- skcomplex/models/social/cooperation/_strategist.py +57 -0
- skcomplex/models/social/cooperation/_strategist_view.py +14 -0
- skcomplex/models/social/cooperation/_tournament.py +126 -0
- skcomplex/models/social/cooperation/_tournaments.py +87 -0
- skcomplex/models/social/crowds/__init__.py +46 -0
- skcomplex/models/social/crowds/_criminal_contagion.py +108 -0
- skcomplex/models/social/crowds/_criminality.py +223 -0
- skcomplex/models/social/crowds/_crowding.py +115 -0
- skcomplex/models/social/crowds/_deterrence.py +101 -0
- skcomplex/models/social/crowds/_evacuation.py +196 -0
- skcomplex/models/social/crowds/_guidance.py +69 -0
- skcomplex/models/social/crowds/_motivation.py +67 -0
- skcomplex/models/social/crowds/_pedestrians.py +85 -0
- skcomplex/models/social/crowds/_recruitment.py +90 -0
- skcomplex/models/social/crowds/_security_agents.py +48 -0
- skcomplex/models/social/crowds/_social_repulsion.py +86 -0
- skcomplex/models/social/crowds/_walking.py +186 -0
- skcomplex/models/social/crowds/_walls.py +69 -0
- skcomplex/models/social/language/__init__.py +13 -0
- skcomplex/models/social/language/_language.py +30 -0
- skcomplex/models/social/language/_least_effort.py +69 -0
- skcomplex/models/social/language/_word.py +39 -0
- skcomplex/models/social/language/_word_frequencies.py +48 -0
- skcomplex/models/social/opinion_dynamics/__init__.py +142 -0
- skcomplex/models/social/opinion_dynamics/_adopter.py +61 -0
- skcomplex/models/social/opinion_dynamics/_adopter_view.py +14 -0
- skcomplex/models/social/opinion_dynamics/_adoption.py +83 -0
- skcomplex/models/social/opinion_dynamics/_axelrod.py +160 -0
- skcomplex/models/social/opinion_dynamics/_believer.py +71 -0
- skcomplex/models/social/opinion_dynamics/_believer_view.py +16 -0
- skcomplex/models/social/opinion_dynamics/_bounded_confidence.py +126 -0
- skcomplex/models/social/opinion_dynamics/_citizen.py +49 -0
- skcomplex/models/social/opinion_dynamics/_citizen_view.py +12 -0
- skcomplex/models/social/opinion_dynamics/_club_member.py +78 -0
- skcomplex/models/social/opinion_dynamics/_coevolution.py +187 -0
- skcomplex/models/social/opinion_dynamics/_coevolving_voter.py +63 -0
- skcomplex/models/social/opinion_dynamics/_cognition.py +73 -0
- skcomplex/models/social/opinion_dynamics/_complex_agent.py +58 -0
- skcomplex/models/social/opinion_dynamics/_complex_agent_view.py +13 -0
- skcomplex/models/social/opinion_dynamics/_confidence_coupling.py +76 -0
- skcomplex/models/social/opinion_dynamics/_confident.py +50 -0
- skcomplex/models/social/opinion_dynamics/_conventions.py +44 -0
- skcomplex/models/social/opinion_dynamics/_conversations.py +116 -0
- skcomplex/models/social/opinion_dynamics/_cultural_influence.py +93 -0
- skcomplex/models/social/opinion_dynamics/_diffusion.py +205 -0
- skcomplex/models/social/opinion_dynamics/_discussant.py +60 -0
- skcomplex/models/social/opinion_dynamics/_discussant_view.py +14 -0
- skcomplex/models/social/opinion_dynamics/_discussions.py +51 -0
- skcomplex/models/social/opinion_dynamics/_encounters.py +48 -0
- skcomplex/models/social/opinion_dynamics/_hypergraph_consensus.py +106 -0
- skcomplex/models/social/opinion_dynamics/_influencee.py +70 -0
- skcomplex/models/social/opinion_dynamics/_influencee_view.py +16 -0
- skcomplex/models/social/opinion_dynamics/_kinetic_opinion.py +287 -0
- skcomplex/models/social/opinion_dynamics/_majority_voter.py +43 -0
- skcomplex/models/social/opinion_dynamics/_namer.py +53 -0
- skcomplex/models/social/opinion_dynamics/_namer_view.py +13 -0
- skcomplex/models/social/opinion_dynamics/_naming_games.py +68 -0
- skcomplex/models/social/opinion_dynamics/_opinion.py +39 -0
- skcomplex/models/social/opinion_dynamics/_persuader.py +52 -0
- skcomplex/models/social/opinion_dynamics/_persuader_view.py +12 -0
- skcomplex/models/social/opinion_dynamics/_persuasion.py +247 -0
- skcomplex/models/social/opinion_dynamics/_random_pairs.py +53 -0
- skcomplex/models/social/opinion_dynamics/_schedule.py +39 -0
- skcomplex/models/social/opinion_dynamics/_separation.py +71 -0
- skcomplex/models/social/opinion_dynamics/_social_impact.py +60 -0
- skcomplex/models/social/opinion_dynamics/_standardization.py +212 -0
- skcomplex/models/social/opinion_dynamics/_thinker.py +61 -0
- skcomplex/models/social/opinion_dynamics/_thinker_view.py +15 -0
- skcomplex/models/social/opinion_dynamics/_three_body_consensus.py +71 -0
- skcomplex/models/social/opinion_dynamics/_tie.py +21 -0
- skcomplex/models/social/opinion_dynamics/_variant_voter.py +67 -0
- skcomplex/models/social/opinion_dynamics/_variant_voter_view.py +14 -0
- skcomplex/models/social/opinion_dynamics/_variant_voting.py +63 -0
- skcomplex/models/social/opinion_dynamics/_village.py +61 -0
- skcomplex/models/social/opinion_dynamics/_village_view.py +14 -0
- skcomplex/models/social/opinion_dynamics/_voter.py +49 -0
- skcomplex/models/social/opinion_dynamics/_voter_imitation.py +48 -0
- skcomplex/models/social/opinion_dynamics/_voter_view.py +12 -0
- skcomplex/models/social/opinion_dynamics/_voters.py +197 -0
- skcomplex/models/social/organizations/__init__.py +68 -0
- skcomplex/models/social/organizations/_arms_race.py +34 -0
- skcomplex/models/social/organizations/_burden.py +38 -0
- skcomplex/models/social/organizations/_city_resident.py +41 -0
- skcomplex/models/social/organizations/_contender_view.py +14 -0
- skcomplex/models/social/organizations/_contest.py +32 -0
- skcomplex/models/social/organizations/_daily_movements.py +144 -0
- skcomplex/models/social/organizations/_eater.py +282 -0
- skcomplex/models/social/organizations/_eater_view.py +24 -0
- skcomplex/models/social/organizations/_employee.py +173 -0
- skcomplex/models/social/organizations/_employee_view.py +35 -0
- skcomplex/models/social/organizations/_employment.py +127 -0
- skcomplex/models/social/organizations/_execution.py +79 -0
- skcomplex/models/social/organizations/_gravity_contact.py +69 -0
- skcomplex/models/social/organizations/_hierarchies.py +174 -0
- skcomplex/models/social/organizations/_obesity.py +131 -0
- skcomplex/models/social/organizations/_premises.py +75 -0
- skcomplex/models/social/organizations/_premises_view.py +16 -0
- skcomplex/models/social/organizations/_queues.py +52 -0
- skcomplex/models/social/organizations/_restaurant.py +59 -0
- skcomplex/models/social/organizations/_restaurant_view.py +14 -0
- skcomplex/models/social/organizations/_sabotage.py +183 -0
- skcomplex/models/social/organizations/_supervisor.py +25 -0
- skcomplex/models/social/organizations/_task.py +65 -0
- skcomplex/models/social/organizations/_task_view.py +15 -0
- skcomplex/models/social/organizations/_trafficking.py +184 -0
- skcomplex/models/social/organizations/_traps.py +322 -0
- skcomplex/models/social/organizations/_traveller.py +55 -0
- skcomplex/models/social/organizations/_traveller_view.py +13 -0
- skcomplex/models/social/organizations/_urban_scaling.py +72 -0
- skcomplex/models/social/segregation/__init__.py +21 -0
- skcomplex/models/social/segregation/_block_moves.py +127 -0
- skcomplex/models/social/segregation/_blocks.py +111 -0
- skcomplex/models/social/segregation/_dweller.py +70 -0
- skcomplex/models/social/segregation/_dweller_view.py +16 -0
- skcomplex/models/social/segregation/_relocation.py +60 -0
- skcomplex/models/social/segregation/_resident.py +55 -0
- skcomplex/models/social/segregation/_resident_view.py +13 -0
- skcomplex/models/social/segregation/_schelling.py +75 -0
- skcomplex/models/social/spreading/__init__.py +37 -0
- skcomplex/models/social/spreading/_cascades.py +118 -0
- skcomplex/models/social/spreading/_exposure.py +166 -0
- skcomplex/models/social/spreading/_growing_word.py +55 -0
- skcomplex/models/social/spreading/_growing_word_view.py +13 -0
- skcomplex/models/social/spreading/_growth.py +52 -0
- skcomplex/models/social/spreading/_infective.py +55 -0
- skcomplex/models/social/spreading/_listeners.py +41 -0
- skcomplex/models/social/spreading/_participant.py +50 -0
- skcomplex/models/social/spreading/_rumour_contacts.py +81 -0
- skcomplex/models/social/spreading/_rumours.py +57 -0
- skcomplex/models/social/spreading/_simplicial.py +120 -0
- skcomplex/models/social/spreading/_simplicial_infection.py +64 -0
- skcomplex/models/social/spreading/_threshold_activation.py +50 -0
- skcomplex/models/social/spreading/_threshold_node_view.py +13 -0
- skcomplex/models/social/spreading/_writing.py +86 -0
- skcomplex/models/types.py +10 -0
- skcomplex/specs/__init__.py +198 -0
- skcomplex/specs/_accelerated_spec.py +46 -0
- skcomplex/specs/_agent_snapshot_spec.py +34 -0
- skcomplex/specs/_agent_state_spec.py +26 -0
- skcomplex/specs/_arguments_spec.py +60 -0
- skcomplex/specs/_axis_spec.py +59 -0
- skcomplex/specs/_base_record_spec.py +16 -0
- skcomplex/specs/_base_spec.py +73 -0
- skcomplex/specs/_base_structure_spec.py +173 -0
- skcomplex/specs/_batch_matching_spec.py +23 -0
- skcomplex/specs/_breakpoints_spec.py +58 -0
- skcomplex/specs/_call_spec.py +64 -0
- skcomplex/specs/_capacity_rows_spec.py +120 -0
- skcomplex/specs/_cardinality_spec.py +58 -0
- skcomplex/specs/_cascade_record_spec.py +36 -0
- skcomplex/specs/_clamp_spec.py +54 -0
- skcomplex/specs/_clause_spec.py +42 -0
- skcomplex/specs/_compiled_flow_spec.py +20 -0
- skcomplex/specs/_composed_rule_spec.py +33 -0
- skcomplex/specs/_continuous_matching_spec.py +48 -0
- skcomplex/specs/_control_solution_spec.py +54 -0
- skcomplex/specs/_control_spec.py +21 -0
- skcomplex/specs/_covariance_adaptation_spec.py +25 -0
- skcomplex/specs/_dataset_spec.py +85 -0
- skcomplex/specs/_delay_spec.py +27 -0
- skcomplex/specs/_dialect_spec.py +207 -0
- skcomplex/specs/_differential_evolution_spec.py +33 -0
- skcomplex/specs/_direction_spec.py +44 -0
- skcomplex/specs/_draw_spec.py +273 -0
- skcomplex/specs/_entry_spec.py +403 -0
- skcomplex/specs/_event_record_spec.py +37 -0
- skcomplex/specs/_evolution_strategy_spec.py +25 -0
- skcomplex/specs/_extremal_record_spec.py +32 -0
- skcomplex/specs/_fractional_rows_spec.py +33 -0
- skcomplex/specs/_fractional_state_spec.py +30 -0
- skcomplex/specs/_held_reduction_spec.py +29 -0
- skcomplex/specs/_hilbert_spec.py +75 -0
- skcomplex/specs/_hyperedge_reduction_spec.py +38 -0
- skcomplex/specs/_issue_spec.py +52 -0
- skcomplex/specs/_iterative_matching_spec.py +39 -0
- skcomplex/specs/_jump_channels_spec.py +40 -0
- skcomplex/specs/_jump_path_spec.py +29 -0
- skcomplex/specs/_layer_spec.py +47 -0
- skcomplex/specs/_layout_spec.py +158 -0
- skcomplex/specs/_local_operator_spec.py +72 -0
- skcomplex/specs/_lookup_spec.py +33 -0
- skcomplex/specs/_loop_spec.py +17 -0
- skcomplex/specs/_lowered_functions_spec.py +71 -0
- skcomplex/specs/_match_spec.py +37 -0
- skcomplex/specs/_matrix_law_spec.py +31 -0
- skcomplex/specs/_move_spec.py +69 -0
- skcomplex/specs/_neighbor_read_spec.py +83 -0
- skcomplex/specs/_neighbor_reduction_spec.py +39 -0
- skcomplex/specs/_network_rows_spec.py +124 -0
- skcomplex/specs/_network_snapshot_spec.py +61 -0
- skcomplex/specs/_noise_process_spec.py +41 -0
- skcomplex/specs/_objective_spec.py +39 -0
- skcomplex/specs/_observable_spec.py +79 -0
- skcomplex/specs/_operator_spec.py +170 -0
- skcomplex/specs/_orders_spec.py +16 -0
- skcomplex/specs/_outer_totalistic_spec.py +38 -0
- skcomplex/specs/_owners_spec.py +28 -0
- skcomplex/specs/_pair_read_spec.py +38 -0
- skcomplex/specs/_parameter_spec.py +81 -0
- skcomplex/specs/_parameters_spec.py +26 -0
- skcomplex/specs/_particle_swarm_spec.py +33 -0
- skcomplex/specs/_partner_spec.py +98 -0
- skcomplex/specs/_partner_switch_spec.py +39 -0
- skcomplex/specs/_phase_spec.py +61 -0
- skcomplex/specs/_phases_schedule_spec.py +59 -0
- skcomplex/specs/_plan_spec.py +18 -0
- skcomplex/specs/_planned_partition_spec.py +30 -0
- skcomplex/specs/_queue_spec.py +46 -0
- skcomplex/specs/_radius_spec.py +66 -0
- skcomplex/specs/_random_search_spec.py +51 -0
- skcomplex/specs/_read_spec.py +45 -0
- skcomplex/specs/_reduction_spec.py +48 -0
- skcomplex/specs/_renewal_record_spec.py +49 -0
- skcomplex/specs/_requirement_spec.py +32 -0
- skcomplex/specs/_role_spec.py +54 -0
- skcomplex/specs/_run_result_spec.py +52 -0
- skcomplex/specs/_run_state_spec.py +41 -0
- skcomplex/specs/_sampled_draw_spec.py +32 -0
- skcomplex/specs/_sampler_spec.py +57 -0
- skcomplex/specs/_samples_spec.py +29 -0
- skcomplex/specs/_schedule_spec.py +17 -0
- skcomplex/specs/_sector_spec.py +31 -0
- skcomplex/specs/_segment_spec.py +21 -0
- skcomplex/specs/_series_spec.py +29 -0
- skcomplex/specs/_signature_spec.py +55 -0
- skcomplex/specs/_snapshots_spec.py +56 -0
- skcomplex/specs/_stable_matching_spec.py +58 -0
- skcomplex/specs/_state_spec.py +138 -0
- skcomplex/specs/_step_spec.py +39 -0
- skcomplex/specs/_structure_state_spec.py +30 -0
- skcomplex/specs/_support_spec.py +76 -0
- skcomplex/specs/_symmetry_spec.py +59 -0
- skcomplex/specs/_table_spec.py +42 -0
- skcomplex/specs/_table_values_spec.py +36 -0
- skcomplex/specs/_tensor_spec.py +197 -0
- skcomplex/specs/_topology_request_spec.py +97 -0
- skcomplex/specs/_totalistic_spec.py +37 -0
- skcomplex/specs/_unknown_spec.py +22 -0
- skcomplex/specs/_validation_report_spec.py +62 -0
- skcomplex/specs/_variable_spec.py +124 -0
- skcomplex/specs/_visual_spec.py +30 -0
- skcomplex/specs/_weight_spec.py +16 -0
- skcomplex/specs/_wiener_block_spec.py +31 -0
- skcomplex/specs/_wiener_process_spec.py +54 -0
- skcomplex/types.py +140 -0
|
@@ -0,0 +1,1624 @@
|
|
|
1
|
+
"""Run agent-based problems on the Mesa backend, one Mesa step per unit of time."""
|
|
2
|
+
|
|
3
|
+
# Author: Georgios Douzas <gdouzas@icloud.com>
|
|
4
|
+
# License: MIT
|
|
5
|
+
|
|
6
|
+
import math
|
|
7
|
+
import numbers
|
|
8
|
+
from collections import deque
|
|
9
|
+
from collections.abc import Callable, Hashable, Iterable, Mapping, Sequence
|
|
10
|
+
from typing import overload
|
|
11
|
+
|
|
12
|
+
import mesa
|
|
13
|
+
import networkx as nx
|
|
14
|
+
import numpy as np
|
|
15
|
+
import numpy.typing as npt
|
|
16
|
+
from mesa.discrete_space import CellAgent, Network, OrthogonalMooreGrid, OrthogonalVonNeumannGrid
|
|
17
|
+
from mesa.experimental.continuous_space import ContinuousSpace as MesaContinuousSpace
|
|
18
|
+
from mesa.experimental.continuous_space import ContinuousSpaceAgent
|
|
19
|
+
|
|
20
|
+
from ...core.elements import BaseElement, GroupElement
|
|
21
|
+
from ...core.laws import BaseLaw, BoundaryLaw, MatchLaw, RuleLaw, TransferLaw
|
|
22
|
+
from ...core.spaces import BaseSpace, ContinuousSpace, DiscreteTime, LatticeSpace, NetworkSpace
|
|
23
|
+
from ...core.specs import CompiledAgentsSpec
|
|
24
|
+
from ...core.system import System
|
|
25
|
+
from ...errors import ConservationError, SimulationError, SpaceError, ValidationError
|
|
26
|
+
from ...specs import DEFAULT_PHASE, AgentSnapshotSpec, AgentStateSpec, PhaseSpec, PhasesScheduleSpec, SupportSpec
|
|
27
|
+
from ...types import Array, FormKind, OrderKind, VariableKind
|
|
28
|
+
from .._utils import declarations_of, default_of
|
|
29
|
+
from ..compile import ObservableEvaluator
|
|
30
|
+
from ..problems import ProblemSpec
|
|
31
|
+
from ..types import MesaSpace
|
|
32
|
+
from ._external import ExternalSolver
|
|
33
|
+
|
|
34
|
+
MAX_SEED = 2**31 - 1
|
|
35
|
+
_HISTORY_LENGTH = 10_000
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class _AgentModel(mesa.Model):
|
|
39
|
+
"""Mesa model whose step runs the agent and model rules of a stepper, so Mesa's clock moves with the run."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, run_rules: Callable[[], None], rng: int) -> None:
|
|
42
|
+
self._run_rules = run_rules
|
|
43
|
+
super().__init__(rng=rng)
|
|
44
|
+
|
|
45
|
+
def step(self) -> None:
|
|
46
|
+
"""Run the agent rules in random order and then the model rules."""
|
|
47
|
+
self._run_rules()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ModelView:
|
|
51
|
+
"""Model as rules see it: parameters, random numbers, time, agents, and the space.
|
|
52
|
+
|
|
53
|
+
Every rule receives the view scoped to the interaction or agent group that owns it, so the rule reads the owner's
|
|
54
|
+
parameters by name and the groups bound to the owner's roles by role, also when its system is nested in another.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
stepper:
|
|
58
|
+
The stepper that runs the model.
|
|
59
|
+
|
|
60
|
+
owner:
|
|
61
|
+
The path of the interaction or agent group whose rules receive the view, or `''` for no owner.
|
|
62
|
+
|
|
63
|
+
roles:
|
|
64
|
+
The paths of the elements and groups the owner's roles bind to, by role.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def __init__(
|
|
68
|
+
self,
|
|
69
|
+
stepper: 'MesaSolver',
|
|
70
|
+
owner: str = '',
|
|
71
|
+
roles: Mapping[str, str | tuple[str, ...]] | None = None,
|
|
72
|
+
) -> None:
|
|
73
|
+
self._stepper = stepper
|
|
74
|
+
self._owner = owner
|
|
75
|
+
self._roles = dict(roles or {})
|
|
76
|
+
|
|
77
|
+
def _paths(self, name: str) -> list[str]:
|
|
78
|
+
"""Return the paths of the groups a role of the owner binds to, or of a group by relative or absolute path."""
|
|
79
|
+
bound = self._roles.get(name)
|
|
80
|
+
if bound is not None:
|
|
81
|
+
return [bound] if isinstance(bound, str) else list(bound)
|
|
82
|
+
try:
|
|
83
|
+
return [self._stepper._resolve_group(name, self._owner)]
|
|
84
|
+
except SimulationError as error:
|
|
85
|
+
roles, owner = ', '.join(self._roles) or 'none', self._owner or 'the model'
|
|
86
|
+
error_msg = f'No role or agent group named {name!r} for {owner}. Its roles are: {roles}. {error}'
|
|
87
|
+
raise SimulationError(error_msg) from error
|
|
88
|
+
|
|
89
|
+
def parameter(self, name: str) -> float:
|
|
90
|
+
"""Return the current value of a parameter of the owner, or of one component as `name[i]`.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
name:
|
|
94
|
+
The name of a scalar parameter, such as `threshold`, or of one component, such as `weights[1]`.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
value:
|
|
98
|
+
The value.
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
SimulationError:
|
|
102
|
+
The owner has no such parameter, or the parameter has several components and no index.
|
|
103
|
+
"""
|
|
104
|
+
stepper = self._stepper
|
|
105
|
+
layout = stepper.problem_.parameters
|
|
106
|
+
try:
|
|
107
|
+
entry, indices = layout.locate(f'{self._owner}.{name}')
|
|
108
|
+
except KeyError as error:
|
|
109
|
+
prefix = f'{self._owner}.'
|
|
110
|
+
names = [item.name[len(prefix) :] for item in layout.entries if item.name.startswith(prefix)]
|
|
111
|
+
error_msg = (
|
|
112
|
+
f'{self._owner or "The model"} has no parameter {name!r}. Its parameters are: '
|
|
113
|
+
f'{", ".join(names) or "none"}.'
|
|
114
|
+
)
|
|
115
|
+
raise SimulationError(error_msg) from error
|
|
116
|
+
if entry.size != 1:
|
|
117
|
+
error_msg = f'{entry.name} has {entry.size} components. Read one of them as {name}[i].'
|
|
118
|
+
raise SimulationError(error_msg)
|
|
119
|
+
return float(stepper.parameters_[indices][0])
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def parameters(self) -> dict[str, float]:
|
|
123
|
+
"""Current values of every parameter by dotted name."""
|
|
124
|
+
stepper = self._stepper
|
|
125
|
+
return {
|
|
126
|
+
name: float(np.ravel(value)[0])
|
|
127
|
+
for name, value in stepper.problem_.parameters.values(stepper.parameters_).items()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def inputs(self) -> Mapping[str, object]:
|
|
132
|
+
"""Values of the states of other partitions at the last synchronisation point, by dotted name."""
|
|
133
|
+
return self._stepper.inputs_
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def rng(self) -> np.random.Generator:
|
|
137
|
+
"""Random number generator of the model, seeded by the simulation's random state."""
|
|
138
|
+
return self._stepper.model_.rng
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def time(self) -> float:
|
|
142
|
+
"""Time of Mesa's clock, `k` during the step that produces frame `k`, plus `i / n` at visit `i` of `n`."""
|
|
143
|
+
stepper = self._stepper
|
|
144
|
+
visit, visits = stepper.visit_
|
|
145
|
+
return float(stepper.model_.time) + visit / max(visits, 1)
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def dimensions(self) -> tuple[float, ...] | None:
|
|
149
|
+
"""Extent of the agent space per axis, cells of a grid or lengths of a continuous space, `None` otherwise."""
|
|
150
|
+
space = self._stepper.space_
|
|
151
|
+
if isinstance(space, MesaContinuousSpace):
|
|
152
|
+
return (float(space.width), float(space.height))
|
|
153
|
+
if isinstance(space, OrthogonalMooreGrid | OrthogonalVonNeumannGrid):
|
|
154
|
+
return tuple(int(item) for item in space.dimensions)
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def torus(self) -> bool:
|
|
159
|
+
"""Whether the agent space wraps around at its edges."""
|
|
160
|
+
return bool(getattr(self._stepper.space_, 'torus', False))
|
|
161
|
+
|
|
162
|
+
@overload
|
|
163
|
+
def agents(self, name: str) -> list['AgentView']: ...
|
|
164
|
+
|
|
165
|
+
@overload
|
|
166
|
+
def agents[V: AgentView](self, name: str, view: type[V]) -> list[V]: ...
|
|
167
|
+
|
|
168
|
+
def agents[V: AgentView](self, name: str, view: type[V] | None = None) -> list[V] | list['AgentView']:
|
|
169
|
+
"""Return the views of the agents of a group bound to a role of the owner, or of a group by path.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
name:
|
|
173
|
+
A role of the owner, the path of a group relative to the owner's system, or the path of a group.
|
|
174
|
+
|
|
175
|
+
view:
|
|
176
|
+
The view class of the group, which its element names with `_get_view`, or `None` for `AgentView`.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
agents:
|
|
180
|
+
The views of the agents alive in the group, or in every group of a role that binds several.
|
|
181
|
+
|
|
182
|
+
Raises:
|
|
183
|
+
SimulationError:
|
|
184
|
+
No role or group has that name, or the views of a group are not of the view class.
|
|
185
|
+
"""
|
|
186
|
+
stepper = self._stepper
|
|
187
|
+
views = [MesaSolver._view_of(agent) for path in self._paths(name) for agent in stepper._group_agents(path)]
|
|
188
|
+
wanted = AgentView if view is None else view
|
|
189
|
+
wrong = [item for item in views if not isinstance(item, wanted)]
|
|
190
|
+
if wrong:
|
|
191
|
+
viewed = type(wrong[0]).__mro__[1].__name__
|
|
192
|
+
error_msg = f'The agents of {name} are viewed as {viewed}, not {wanted.__name__}.'
|
|
193
|
+
raise SimulationError(error_msg)
|
|
194
|
+
if view is None:
|
|
195
|
+
return views
|
|
196
|
+
return [item for item in views if isinstance(item, view)]
|
|
197
|
+
|
|
198
|
+
def groups(self, name: str) -> list[str]:
|
|
199
|
+
"""Return the paths of the groups a role of the owner binds, or of a group by relative or absolute path.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
name:
|
|
203
|
+
A role of the owner, the path of a group relative to the owner's system, or the path of a group.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
paths:
|
|
207
|
+
The paths of the groups.
|
|
208
|
+
|
|
209
|
+
Raises:
|
|
210
|
+
SimulationError:
|
|
211
|
+
No role or group has that name.
|
|
212
|
+
"""
|
|
213
|
+
return self._paths(name)
|
|
214
|
+
|
|
215
|
+
def count(self, name: str) -> int:
|
|
216
|
+
"""Return the number of agents of a group bound to a role of the owner, or of a group by path.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
name:
|
|
220
|
+
A role of the owner, the path of a group relative to the owner's system, or the path of a group.
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
count:
|
|
224
|
+
The number of agents alive in the group, or in every group of a role that binds several.
|
|
225
|
+
|
|
226
|
+
Raises:
|
|
227
|
+
SimulationError:
|
|
228
|
+
No role or group has that name.
|
|
229
|
+
"""
|
|
230
|
+
return sum(len(self._stepper._group_agents(path)) for path in self._paths(name))
|
|
231
|
+
|
|
232
|
+
def composition(self, name: str, state: str) -> dict[Hashable, int]:
|
|
233
|
+
"""Return the number of agents of a group that hold every value of a state, for the values some agent holds.
|
|
234
|
+
|
|
235
|
+
The stepper keeps the counts as agents are created, removed, and change the state, so reading them costs no
|
|
236
|
+
pass over the agents.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
name:
|
|
240
|
+
A role of the owner, the path of a group relative to the owner's system, or the path of a group.
|
|
241
|
+
|
|
242
|
+
state:
|
|
243
|
+
The name of a scalar state of the agents of the group.
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
counts:
|
|
247
|
+
The number of agents alive in the group, or in every group of a role that binds several, by value.
|
|
248
|
+
|
|
249
|
+
Raises:
|
|
250
|
+
SimulationError:
|
|
251
|
+
No role or group has that name, or its agents have no such state.
|
|
252
|
+
"""
|
|
253
|
+
counts: dict[Hashable, int] = {}
|
|
254
|
+
for path in self._paths(name):
|
|
255
|
+
for value, count in self._stepper._composition(path, state).items():
|
|
256
|
+
counts[value] = counts.get(value, 0) + count
|
|
257
|
+
return {value: count for value, count in counts.items() if count}
|
|
258
|
+
|
|
259
|
+
def occupancy(self, name: str) -> dict[Hashable, int]:
|
|
260
|
+
"""Return the number of agents of a group in every cell or node that holds one, by the key of the location.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
name:
|
|
264
|
+
A role of the owner, the path of a group relative to the owner's system, or the path of a group.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
counts:
|
|
268
|
+
The number of agents alive in the group, or in every group of a role that binds several, by the
|
|
269
|
+
`location_key` of their cell, node, or position.
|
|
270
|
+
|
|
271
|
+
Raises:
|
|
272
|
+
SimulationError:
|
|
273
|
+
No role or group has that name.
|
|
274
|
+
"""
|
|
275
|
+
counts: dict[Hashable, int] = {}
|
|
276
|
+
for path in self._paths(name):
|
|
277
|
+
for agent in self._stepper._group_agents(path):
|
|
278
|
+
key = self._stepper._view_of(agent).location_key
|
|
279
|
+
counts[key] = counts.get(key, 0) + 1
|
|
280
|
+
return counts
|
|
281
|
+
|
|
282
|
+
def _field_name(self, name: str) -> str:
|
|
283
|
+
"""Return the path of a field state named by its path, or as `<role>.<state>` of a role of the owner."""
|
|
284
|
+
role, _, state = name.rpartition('.')
|
|
285
|
+
bound = self._roles.get(role)
|
|
286
|
+
return f'{bound}.{state}' if isinstance(bound, str) else name
|
|
287
|
+
|
|
288
|
+
def _site(self, name: str, cell: object) -> int:
|
|
289
|
+
"""Return the member index of a field state's site at a cell or network node."""
|
|
290
|
+
problem = self._stepper.problem_
|
|
291
|
+
if not problem.states.has(name):
|
|
292
|
+
names = [entry.name for entry in problem.states.entries if entry.members is not None]
|
|
293
|
+
error_msg = f'No field state named {name!r}. Available group states are: {", ".join(names)}.'
|
|
294
|
+
raise KeyError(error_msg)
|
|
295
|
+
shape = problem.lattice_shape(name)
|
|
296
|
+
if shape is not None:
|
|
297
|
+
return int(np.ravel_multi_index(tuple(int(item) for item in np.atleast_1d(np.asarray(cell))), shape))
|
|
298
|
+
owner = name.rpartition('.')[0]
|
|
299
|
+
element = next(item for item in problem.elements if item.path == owner)
|
|
300
|
+
space = getattr(element.element, 'space', None)
|
|
301
|
+
if space is None or not hasattr(space, 'graph'):
|
|
302
|
+
error_msg = f'{name} is not a state of a field on a lattice or a network.'
|
|
303
|
+
raise KeyError(error_msg)
|
|
304
|
+
return list(space.graph.nodes).index(cell)
|
|
305
|
+
|
|
306
|
+
def field(self, name: str, cell: object) -> float:
|
|
307
|
+
"""Return the value of a field at a cell, as it was at the last synchronisation point.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
name:
|
|
311
|
+
The dotted path of the field state, such as `ground/pheromone.level`, or `<role>.<state>` for a field
|
|
312
|
+
bound to a role of the owner.
|
|
313
|
+
|
|
314
|
+
cell:
|
|
315
|
+
The lattice coordinates of the cell, which match the coordinates of a grid of the same shape, or a
|
|
316
|
+
network node.
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
value:
|
|
320
|
+
The value of the field there.
|
|
321
|
+
|
|
322
|
+
Raises:
|
|
323
|
+
KeyError:
|
|
324
|
+
The name is not a state of a field.
|
|
325
|
+
"""
|
|
326
|
+
name = self._field_name(name)
|
|
327
|
+
site = self._site(name, cell)
|
|
328
|
+
values = self._stepper.inputs_.get(name)
|
|
329
|
+
if values is None:
|
|
330
|
+
error_msg = f'The agents read the field {name}, which no other partition provides. Run it in co-simulation.'
|
|
331
|
+
raise KeyError(error_msg)
|
|
332
|
+
return float(np.ravel(np.asarray(values))[site])
|
|
333
|
+
|
|
334
|
+
def deposit(self, name: str, cell: object, amount: float) -> None:
|
|
335
|
+
"""Add an amount to a field at a cell at the next synchronisation point.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
name:
|
|
339
|
+
The dotted path of the field state, such as `ground/pheromone.level`, or `<role>.<state>` for a field
|
|
340
|
+
bound to a role of the owner.
|
|
341
|
+
|
|
342
|
+
cell:
|
|
343
|
+
The lattice coordinates of the cell or a network node.
|
|
344
|
+
|
|
345
|
+
amount:
|
|
346
|
+
The amount to add.
|
|
347
|
+
|
|
348
|
+
Raises:
|
|
349
|
+
KeyError:
|
|
350
|
+
The name is not a state of a field.
|
|
351
|
+
"""
|
|
352
|
+
name = self._field_name(name)
|
|
353
|
+
site = self._site(name, cell)
|
|
354
|
+
entry = self._stepper.problem_.states.entry(name)
|
|
355
|
+
self._stepper.deposits_[entry.start + site * entry.columns] += amount
|
|
356
|
+
|
|
357
|
+
def random_empty_cell(self) -> object:
|
|
358
|
+
"""Return the coordinates of a random empty cell of the grid or network.
|
|
359
|
+
|
|
360
|
+
Returns:
|
|
361
|
+
location:
|
|
362
|
+
The cell coordinates or the network node.
|
|
363
|
+
"""
|
|
364
|
+
return self._stepper._cells().select_random_empty_cell().coordinate
|
|
365
|
+
|
|
366
|
+
def create(self, group: str, location: object = None, **values: object) -> 'AgentView':
|
|
367
|
+
"""Create an agent of a group, at a location or at a random place.
|
|
368
|
+
|
|
369
|
+
Args:
|
|
370
|
+
group:
|
|
371
|
+
A role of the owner that binds the group, or the path of the group.
|
|
372
|
+
|
|
373
|
+
location:
|
|
374
|
+
The cell coordinates, network node, or position, or `None` for a random place.
|
|
375
|
+
|
|
376
|
+
**values:
|
|
377
|
+
The initial values of states, with the element type's defaults for the others.
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
agent:
|
|
381
|
+
The new agent.
|
|
382
|
+
|
|
383
|
+
Raises:
|
|
384
|
+
SimulationError:
|
|
385
|
+
The group is not variable, so its size cannot change.
|
|
386
|
+
"""
|
|
387
|
+
return MesaSolver._view_of(self._stepper._create_agent(self._paths(group)[0], location, values))
|
|
388
|
+
|
|
389
|
+
@property
|
|
390
|
+
def round(self) -> int:
|
|
391
|
+
"""Index of the current round of a repeated phase, `0` outside repeated phases."""
|
|
392
|
+
return self._stepper.round_
|
|
393
|
+
|
|
394
|
+
@property
|
|
395
|
+
def storage(self) -> dict[str, object]:
|
|
396
|
+
"""Mutable mapping private to the owner that persists across the steps of one run, such as an order book."""
|
|
397
|
+
return self._stepper.storage_.setdefault(self._owner, {})
|
|
398
|
+
|
|
399
|
+
def _report_name(self, name: str) -> str:
|
|
400
|
+
"""Return the reporter name of a name of the owner."""
|
|
401
|
+
return f'{self._owner}.{name}' if self._owner else name
|
|
402
|
+
|
|
403
|
+
def report(self, name: str, value: float) -> None:
|
|
404
|
+
"""Publish a value of the owner as the reporter `<owner>.<name>` and add it to the reporter's history.
|
|
405
|
+
|
|
406
|
+
The owner declares the names it reports in its class variable `reports`, so every frame records them, `NaN`
|
|
407
|
+
before the first report.
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
name:
|
|
411
|
+
The name of the value, such as `price`.
|
|
412
|
+
|
|
413
|
+
value:
|
|
414
|
+
The value.
|
|
415
|
+
|
|
416
|
+
Raises:
|
|
417
|
+
SimulationError:
|
|
418
|
+
The owner does not declare the name in `reports`.
|
|
419
|
+
"""
|
|
420
|
+
full = self._report_name(name)
|
|
421
|
+
if full not in self._stepper.reports_:
|
|
422
|
+
error_msg = (
|
|
423
|
+
f'{self._owner or "The model"} reports {name!r}, which it does not declare. List it in the class '
|
|
424
|
+
'variable `reports` of the interaction or element type.'
|
|
425
|
+
)
|
|
426
|
+
raise SimulationError(error_msg)
|
|
427
|
+
kept = float(value) if isinstance(value, numbers.Real) else value
|
|
428
|
+
self._stepper.reports_[full] = kept
|
|
429
|
+
self._stepper.reported_.setdefault(full, deque(maxlen=_HISTORY_LENGTH)).append(kept)
|
|
430
|
+
|
|
431
|
+
def history(self, name: str, window: int | None = None) -> npt.NDArray[np.float64]:
|
|
432
|
+
"""Return the past values of a reporter, or of an observable at the end of each earlier step, the last one last.
|
|
433
|
+
|
|
434
|
+
Args:
|
|
435
|
+
name:
|
|
436
|
+
The name of a value the owner reports, the full name of any reporter, such as `bar.attendance`, or the
|
|
437
|
+
path of an observable of the run, such as `attendance`.
|
|
438
|
+
|
|
439
|
+
window:
|
|
440
|
+
The number of last values, or `None` for every recorded value.
|
|
441
|
+
|
|
442
|
+
Returns:
|
|
443
|
+
values:
|
|
444
|
+
The values, at most `window` of them.
|
|
445
|
+
"""
|
|
446
|
+
stepper = self._stepper
|
|
447
|
+
history = stepper.reported_
|
|
448
|
+
values = history.get(self._report_name(name), history.get(name, stepper.observed_.get(name, ())))
|
|
449
|
+
array = (
|
|
450
|
+
np.asarray(values, dtype=float)
|
|
451
|
+
if all(isinstance(item, numbers.Real) for item in values)
|
|
452
|
+
else np.fromiter(values, dtype=object, count=len(values))
|
|
453
|
+
)
|
|
454
|
+
return array if window is None else array[len(array) - min(window, len(array)) :]
|
|
455
|
+
|
|
456
|
+
def observable(self, name: str) -> object:
|
|
457
|
+
"""Return the current value of an observable of the system, such as an aggregate of a group.
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
name:
|
|
461
|
+
The path of the observable.
|
|
462
|
+
|
|
463
|
+
Returns:
|
|
464
|
+
value:
|
|
465
|
+
Its value for the current agents and parameters.
|
|
466
|
+
|
|
467
|
+
Raises:
|
|
468
|
+
SimulationError:
|
|
469
|
+
The system has no such observable.
|
|
470
|
+
"""
|
|
471
|
+
return self._stepper._observable(name)
|
|
472
|
+
|
|
473
|
+
def set_parameter(self, name: str, value: float) -> None:
|
|
474
|
+
"""Set a parameter of any group or interaction during the run, recorded in the trajectory like any parameter.
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
name:
|
|
478
|
+
The dotted name of the parameter, such as `bank.rate`, or the name of a parameter of the owner.
|
|
479
|
+
|
|
480
|
+
value:
|
|
481
|
+
The new value.
|
|
482
|
+
|
|
483
|
+
Raises:
|
|
484
|
+
SimulationError:
|
|
485
|
+
No parameter has that name.
|
|
486
|
+
"""
|
|
487
|
+
layout = self._stepper.problem_.parameters
|
|
488
|
+
full = name if layout.has(name) else f'{self._owner}.{name}'
|
|
489
|
+
if not layout.has(full):
|
|
490
|
+
error_msg = f'No parameter named {name!r} to set. Available names are: {", ".join(layout.names)}.'
|
|
491
|
+
raise SimulationError(error_msg)
|
|
492
|
+
self._stepper._set_parameter(full, value)
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
class AgentView:
|
|
496
|
+
"""Agent as rules see it: its states as attributes, its group's parameters, its neighbours, and its location.
|
|
497
|
+
|
|
498
|
+
The stepper gives every agent one view of the class of its group, whose states and parameters are properties, so
|
|
499
|
+
two views of an agent are the same object. Reading a state reads the agent, and setting it sets the agent, at
|
|
500
|
+
the end of the phase in a simultaneous phase. Parameters are read only, and an unknown name raises Python's own
|
|
501
|
+
`AttributeError`.
|
|
502
|
+
|
|
503
|
+
Args:
|
|
504
|
+
agent:
|
|
505
|
+
The Mesa agent.
|
|
506
|
+
|
|
507
|
+
stepper:
|
|
508
|
+
The stepper that runs the model.
|
|
509
|
+
"""
|
|
510
|
+
|
|
511
|
+
__slots__ = ('_agent', '_stepper')
|
|
512
|
+
|
|
513
|
+
def __init__(self, agent: mesa.Agent, stepper: 'MesaSolver') -> None:
|
|
514
|
+
self._agent = agent
|
|
515
|
+
self._stepper = stepper
|
|
516
|
+
|
|
517
|
+
@property
|
|
518
|
+
def id(self) -> int:
|
|
519
|
+
"""Unique id of the agent."""
|
|
520
|
+
return int(self._agent.unique_id)
|
|
521
|
+
|
|
522
|
+
@property
|
|
523
|
+
def group(self) -> str:
|
|
524
|
+
"""Path of the agent's group."""
|
|
525
|
+
return self._stepper._spec_of(self._agent).path
|
|
526
|
+
|
|
527
|
+
@property
|
|
528
|
+
def group_label(self) -> str:
|
|
529
|
+
"""Label of the agent's group, the last part of its path."""
|
|
530
|
+
return self.group.rpartition('/')[2]
|
|
531
|
+
|
|
532
|
+
@property
|
|
533
|
+
def location(self) -> object:
|
|
534
|
+
"""Grid coordinates, network node, or position of the agent."""
|
|
535
|
+
return MesaSolver._location_of(self._agent)
|
|
536
|
+
|
|
537
|
+
@property
|
|
538
|
+
def location_key(self) -> Hashable:
|
|
539
|
+
"""Location of the agent as a key: a tuple of integers for a cell, a tuple of floats for a position, or a node.
|
|
540
|
+
|
|
541
|
+
The key equals the coordinates `neighbor_cells` gives for the agent's cell or node, so rules compare the cells
|
|
542
|
+
around an agent with the places of other agents.
|
|
543
|
+
"""
|
|
544
|
+
location = self.location
|
|
545
|
+
if isinstance(location, tuple | list | np.ndarray):
|
|
546
|
+
values = np.asarray(location)
|
|
547
|
+
if np.issubdtype(values.dtype, np.integer) or np.all(values == np.round(values)):
|
|
548
|
+
return tuple(int(item) for item in values.ravel())
|
|
549
|
+
return tuple(float(item) for item in values.ravel())
|
|
550
|
+
return location if isinstance(location, Hashable) else repr(location)
|
|
551
|
+
|
|
552
|
+
@property
|
|
553
|
+
def alive(self) -> bool:
|
|
554
|
+
"""Whether the agent has not been removed."""
|
|
555
|
+
return not getattr(self._agent, 'removed_', False)
|
|
556
|
+
|
|
557
|
+
def displacement_to(self, other: 'AgentView | object') -> npt.NDArray[np.float64]:
|
|
558
|
+
"""Return the vector from the agent to another agent or a location, the shortest one on a torus.
|
|
559
|
+
|
|
560
|
+
Args:
|
|
561
|
+
other:
|
|
562
|
+
An agent, or grid coordinates or a position.
|
|
563
|
+
|
|
564
|
+
Returns:
|
|
565
|
+
displacement:
|
|
566
|
+
One component per axis of the space.
|
|
567
|
+
|
|
568
|
+
Raises:
|
|
569
|
+
SpaceError:
|
|
570
|
+
The agents live on a network or in no space.
|
|
571
|
+
"""
|
|
572
|
+
model = ModelView(self._stepper)
|
|
573
|
+
dimensions = model.dimensions
|
|
574
|
+
if dimensions is None:
|
|
575
|
+
error_msg = (
|
|
576
|
+
'Displacements need a grid or a continuous space, and the agents live on a network or in no space. '
|
|
577
|
+
'Use `distance_to` for the number of hops on a network.'
|
|
578
|
+
)
|
|
579
|
+
raise SpaceError(error_msg)
|
|
580
|
+
target = other.location if isinstance(other, AgentView) else other
|
|
581
|
+
delta = np.asarray(target, dtype=float) - np.asarray(self.location, dtype=float)
|
|
582
|
+
if not model.torus:
|
|
583
|
+
return delta
|
|
584
|
+
size = np.asarray(dimensions, dtype=float)
|
|
585
|
+
return delta - size * np.round(delta / size)
|
|
586
|
+
|
|
587
|
+
def distance_to(self, other: 'AgentView | object') -> float:
|
|
588
|
+
"""Return the distance to another agent or a location, the number of hops on a network.
|
|
589
|
+
|
|
590
|
+
Args:
|
|
591
|
+
other:
|
|
592
|
+
An agent, or a network node, grid coordinates, or a position.
|
|
593
|
+
|
|
594
|
+
Returns:
|
|
595
|
+
distance:
|
|
596
|
+
The Euclidean length of the shortest displacement, or the length of the shortest path on a network.
|
|
597
|
+
|
|
598
|
+
Raises:
|
|
599
|
+
SpaceError:
|
|
600
|
+
The agents live in no space.
|
|
601
|
+
"""
|
|
602
|
+
space = self._stepper.problem_.agent_space
|
|
603
|
+
if isinstance(space, NetworkSpace):
|
|
604
|
+
target = other.location if isinstance(other, AgentView) else other
|
|
605
|
+
return float(nx.shortest_path_length(space.graph, self.location, target))
|
|
606
|
+
return float(np.linalg.norm(self.displacement_to(other)))
|
|
607
|
+
|
|
608
|
+
def neighbor_cells(self) -> list[object]:
|
|
609
|
+
"""Return the coordinates of the cells or nodes around the agent's cell or node.
|
|
610
|
+
|
|
611
|
+
Returns:
|
|
612
|
+
locations:
|
|
613
|
+
The neighbouring cell coordinates or network nodes.
|
|
614
|
+
"""
|
|
615
|
+
return [cell.coordinate for cell in self._agent.cell.neighborhood]
|
|
616
|
+
|
|
617
|
+
def neighbors(self, radius: float | None = None, layer: str | None = None) -> list['AgentView']:
|
|
618
|
+
"""Return the agents in the cells or nodes around the agent, within a radius, or around it in a layer.
|
|
619
|
+
|
|
620
|
+
Args:
|
|
621
|
+
radius:
|
|
622
|
+
The distance within which agents are neighbours in a continuous space.
|
|
623
|
+
|
|
624
|
+
layer:
|
|
625
|
+
The layer of a network space whose edges join the agent to its neighbours, or `None` for the graph of
|
|
626
|
+
the network.
|
|
627
|
+
|
|
628
|
+
Returns:
|
|
629
|
+
agents:
|
|
630
|
+
The neighbouring agents.
|
|
631
|
+
"""
|
|
632
|
+
if layer is not None:
|
|
633
|
+
graph = getattr(self._stepper.problem_.agent_space, 'graphs_', {})[layer]
|
|
634
|
+
cells = self._stepper._cells()
|
|
635
|
+
return [
|
|
636
|
+
MesaSolver._view_of(agent)
|
|
637
|
+
for node in graph.neighbors(self.location_key)
|
|
638
|
+
for agent in cells[MesaSolver._cell_key(node)].agents
|
|
639
|
+
]
|
|
640
|
+
if radius is not None:
|
|
641
|
+
agents, _ = self._agent.get_neighbors_in_radius(radius)
|
|
642
|
+
return [MesaSolver._view_of(agent) for agent in agents if agent is not self._agent]
|
|
643
|
+
return [MesaSolver._view_of(agent) for agent in self._agent.cell.neighborhood.agents]
|
|
644
|
+
|
|
645
|
+
def agents_here(self, group: str | None = None) -> list['AgentView']:
|
|
646
|
+
"""Return the other agents in the agent's cell or node, of one group or of every group.
|
|
647
|
+
|
|
648
|
+
Args:
|
|
649
|
+
group:
|
|
650
|
+
The path of a group, or `None` for every group.
|
|
651
|
+
|
|
652
|
+
Returns:
|
|
653
|
+
agents:
|
|
654
|
+
The other agents at the same place.
|
|
655
|
+
"""
|
|
656
|
+
stepper = self._stepper
|
|
657
|
+
path = stepper._resolve_group(group, self.group) if group is not None else None
|
|
658
|
+
return [
|
|
659
|
+
MesaSolver._view_of(agent)
|
|
660
|
+
for agent in self._agent.cell.agents
|
|
661
|
+
if agent is not self._agent and (path is None or stepper._spec_of(agent).path == path)
|
|
662
|
+
]
|
|
663
|
+
|
|
664
|
+
def move_to(self, location: object) -> None:
|
|
665
|
+
"""Move the agent to a cell, a node, or a position.
|
|
666
|
+
|
|
667
|
+
Args:
|
|
668
|
+
location:
|
|
669
|
+
The cell coordinates, network node, or position.
|
|
670
|
+
"""
|
|
671
|
+
if isinstance(self._stepper.problem_.agent_space, ContinuousSpace):
|
|
672
|
+
self._agent.position = np.asarray(location, dtype=float)
|
|
673
|
+
return
|
|
674
|
+
self._agent.cell = self._stepper._cells()[MesaSolver._cell_key(location)]
|
|
675
|
+
|
|
676
|
+
def remove(self) -> None:
|
|
677
|
+
"""Remove the agent from the model, after checking that it holds none of a conserved quantity.
|
|
678
|
+
|
|
679
|
+
Raises:
|
|
680
|
+
ConservationError:
|
|
681
|
+
A state tagged with a quantity is not zero, so removing the agent would destroy it. Settle the
|
|
682
|
+
holdings with transfers first.
|
|
683
|
+
|
|
684
|
+
SimulationError:
|
|
685
|
+
The agent's group is not variable, so its size cannot change.
|
|
686
|
+
"""
|
|
687
|
+
spec = self._stepper._spec_of(self._agent)
|
|
688
|
+
MesaSolver._check_variable(spec, 'remove')
|
|
689
|
+
held = {
|
|
690
|
+
name: value
|
|
691
|
+
for name in self._stepper._quantities[spec.path]
|
|
692
|
+
if (value := float(getattr(self._agent, name))) != 0.0
|
|
693
|
+
}
|
|
694
|
+
if self.alive and held:
|
|
695
|
+
error_msg = (
|
|
696
|
+
f'Agent {self.id} of {spec.path} is removed while holding {held}. Settle its holdings with transfers '
|
|
697
|
+
'to other agents before removing it, so conserved quantities are not destroyed.'
|
|
698
|
+
)
|
|
699
|
+
raise ConservationError(error_msg)
|
|
700
|
+
if self.alive:
|
|
701
|
+
self._stepper._recount(self._agent, -1)
|
|
702
|
+
self._agent.removed_ = True
|
|
703
|
+
self._agent.remove()
|
|
704
|
+
|
|
705
|
+
def create(self, group: str | None = None, location: object = None, **values: object) -> 'AgentView':
|
|
706
|
+
"""Create an agent of a group, by default the agent's own group at the agent's location.
|
|
707
|
+
|
|
708
|
+
Args:
|
|
709
|
+
group:
|
|
710
|
+
The path of the group, or `None` for the agent's group.
|
|
711
|
+
|
|
712
|
+
location:
|
|
713
|
+
The location of the new agent, or `None` for the agent's location.
|
|
714
|
+
|
|
715
|
+
**values:
|
|
716
|
+
The initial values of states, with the element type's defaults for the others.
|
|
717
|
+
|
|
718
|
+
Returns:
|
|
719
|
+
agent:
|
|
720
|
+
The new agent.
|
|
721
|
+
|
|
722
|
+
Raises:
|
|
723
|
+
SimulationError:
|
|
724
|
+
The group is not variable, so its size cannot change.
|
|
725
|
+
"""
|
|
726
|
+
stepper = self._stepper
|
|
727
|
+
target = stepper._resolve_group(group, self.group) if group is not None else self.group
|
|
728
|
+
place = location if location is not None else self.location
|
|
729
|
+
return MesaSolver._view_of(stepper._create_agent(target, place, values))
|
|
730
|
+
|
|
731
|
+
def referenced(self, state: str) -> 'AgentView | None':
|
|
732
|
+
"""Return the member of another group that a reference state of the agent names by its id.
|
|
733
|
+
|
|
734
|
+
A state declared with `StateSpec(reference=group)` holds the id of a member of the group, or a negative value
|
|
735
|
+
for none, such as the bank of a customer or the employer of a worker.
|
|
736
|
+
|
|
737
|
+
Args:
|
|
738
|
+
state:
|
|
739
|
+
The name of a reference state.
|
|
740
|
+
|
|
741
|
+
Returns:
|
|
742
|
+
agent:
|
|
743
|
+
The member the state names, or `None` when it names none or the member was removed.
|
|
744
|
+
|
|
745
|
+
Raises:
|
|
746
|
+
KeyError:
|
|
747
|
+
The state of the agent names no member of a group.
|
|
748
|
+
"""
|
|
749
|
+
stepper = self._stepper
|
|
750
|
+
path = stepper._reference_of(stepper._spec_of(self._agent), state)
|
|
751
|
+
value = float(getattr(self._agent, state))
|
|
752
|
+
if value < 0 or path is None:
|
|
753
|
+
return None
|
|
754
|
+
agent = stepper.members_.get(int(value))
|
|
755
|
+
if agent is None or getattr(agent, 'removed_', False) or stepper._spec_of(agent).path != path:
|
|
756
|
+
return None
|
|
757
|
+
return MesaSolver._view_of(agent)
|
|
758
|
+
|
|
759
|
+
def lags(self, state: str, window: int | None = None) -> npt.NDArray[np.float64]:
|
|
760
|
+
"""Return the past values of a state of an agent, the values at the ends of the last steps, the last one last.
|
|
761
|
+
|
|
762
|
+
An agent remembers a state declared with lags, `StateSpec(lags=m)`: the agent stepper keeps its last `m` values
|
|
763
|
+
in the companion states `<state>_lag1` to `<state>_lag<m>`, which rules may also read one by one. Before the
|
|
764
|
+
first steps the lags hold their initial values, the `initial` of the spec or else the initial value of the
|
|
765
|
+
state.
|
|
766
|
+
|
|
767
|
+
Args:
|
|
768
|
+
state:
|
|
769
|
+
The name of a state with lags.
|
|
770
|
+
|
|
771
|
+
window:
|
|
772
|
+
The number of last values, or `None` for every kept value.
|
|
773
|
+
|
|
774
|
+
Returns:
|
|
775
|
+
values:
|
|
776
|
+
The values, the oldest first.
|
|
777
|
+
|
|
778
|
+
Raises:
|
|
779
|
+
KeyError:
|
|
780
|
+
The state of the agent keeps no lags.
|
|
781
|
+
"""
|
|
782
|
+
spec = self._stepper._spec_of(self._agent)
|
|
783
|
+
declaration = declarations_of(MesaSolver._agent_type(spec), VariableKind.STATE).get(state)
|
|
784
|
+
if declaration is None or not declaration.lags:
|
|
785
|
+
error_msg = (
|
|
786
|
+
f'The agents of {spec.path} do not remember {state!r}. Declare the state with lags, such as '
|
|
787
|
+
'`StateSpec(lags=3)`, to keep its last values.'
|
|
788
|
+
)
|
|
789
|
+
raise KeyError(error_msg)
|
|
790
|
+
lags = declaration.lags if window is None else min(window, declaration.lags)
|
|
791
|
+
return np.asarray([getattr(self, f'{state}_lag{index}') for index in range(lags, 0, -1)], dtype=float)
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
class MesaSolver(ExternalSolver):
|
|
795
|
+
"""Mesa backend of agent-based problems, one Mesa step per unit of time.
|
|
796
|
+
|
|
797
|
+
The agents are the members of the elements and groups whose laws include `RuleLaw`s, and of the variable groups.
|
|
798
|
+
Every step advances Mesa's clock by one, activates all agents in random order, or by the phases of the system's
|
|
799
|
+
discrete time, and each agent runs the rules of its element type in declaration order. Interaction rules run once
|
|
800
|
+
after the agents. Rules add and remove members of variable groups only. The class variable `supports` declares
|
|
801
|
+
what the backend runs, which validation checks systems against: discrete time, no space or a lattice, network, or
|
|
802
|
+
continuous space, rule, boundary, transfer, and matching laws, and elements and fixed and variable
|
|
803
|
+
groups with any domain but Hilbert spaces.
|
|
804
|
+
|
|
805
|
+
Attributes:
|
|
806
|
+
model_:
|
|
807
|
+
The Mesa model.
|
|
808
|
+
|
|
809
|
+
members_:
|
|
810
|
+
Every agent created in the run by its id, which reference states name.
|
|
811
|
+
|
|
812
|
+
Examples:
|
|
813
|
+
>>> from typing import Annotated
|
|
814
|
+
>>> from skcomplex.core.elements import Element, GroupElement
|
|
815
|
+
>>> from skcomplex.core.laws import RuleLaw
|
|
816
|
+
>>> from skcomplex.specs import StateSpec
|
|
817
|
+
>>> from skcomplex.core.system import System
|
|
818
|
+
>>> from skcomplex.engine.runtime import Simulation
|
|
819
|
+
>>> from skcomplex.engine.solvers import MesaSolver
|
|
820
|
+
>>> class CounterElement(Element):
|
|
821
|
+
... def __init__(self, label, count: Annotated[float, StateSpec()] = 0.0):
|
|
822
|
+
... super().__init__(label)
|
|
823
|
+
... self.count = count
|
|
824
|
+
...
|
|
825
|
+
... def _get_laws(self, namespace):
|
|
826
|
+
... return [RuleLaw(self.tick)]
|
|
827
|
+
...
|
|
828
|
+
... def tick(self, agent, model):
|
|
829
|
+
... agent.count += 1
|
|
830
|
+
>>> system = System(elements=[GroupElement('counters', element=CounterElement, size=3)])
|
|
831
|
+
>>> trajectory = Simulation(system, solver=MesaSolver()).check().prepare().run(until=4).trajectory_
|
|
832
|
+
>>> trajectory.agents('counters', 4).values['count'].tolist()
|
|
833
|
+
[4.0, 4.0, 4.0]
|
|
834
|
+
"""
|
|
835
|
+
|
|
836
|
+
@classmethod
|
|
837
|
+
def _get_support(cls) -> SupportSpec:
|
|
838
|
+
"""Return the times, spaces, laws, noise, and orders the solver solves."""
|
|
839
|
+
return SupportSpec(
|
|
840
|
+
time={DiscreteTime},
|
|
841
|
+
space={None, LatticeSpace, NetworkSpace, ContinuousSpace},
|
|
842
|
+
laws={RuleLaw, BoundaryLaw, TransferLaw, MatchLaw},
|
|
843
|
+
orders=frozenset({OrderKind.INTEGER}),
|
|
844
|
+
)
|
|
845
|
+
|
|
846
|
+
@classmethod
|
|
847
|
+
def _get_form(cls) -> FormKind:
|
|
848
|
+
"""Return the form the solver solves."""
|
|
849
|
+
return FormKind.AGENT
|
|
850
|
+
|
|
851
|
+
@classmethod
|
|
852
|
+
def _reads_inputs(cls) -> bool:
|
|
853
|
+
"""Return whether the solver reads the inputs of other partitions."""
|
|
854
|
+
return True
|
|
855
|
+
|
|
856
|
+
def _seed(self) -> int:
|
|
857
|
+
"""Return a seed for Mesa drawn from the stepper's random number generator."""
|
|
858
|
+
return int(self.rng_.integers(0, MAX_SEED))
|
|
859
|
+
|
|
860
|
+
@classmethod
|
|
861
|
+
def _get_name(cls) -> str:
|
|
862
|
+
"""Return the name of the library the solver wraps."""
|
|
863
|
+
return 'Mesa'
|
|
864
|
+
|
|
865
|
+
def _unsupported(self, problem: ProblemSpec) -> list[str]:
|
|
866
|
+
"""Return nothing, since Mesa runs every agent-based problem."""
|
|
867
|
+
del problem
|
|
868
|
+
return []
|
|
869
|
+
|
|
870
|
+
def _build(self, problem: ProblemSpec) -> None:
|
|
871
|
+
"""Build the Mesa model of an agent-based problem.
|
|
872
|
+
|
|
873
|
+
Args:
|
|
874
|
+
problem:
|
|
875
|
+
The compiled problem.
|
|
876
|
+
|
|
877
|
+
Raises:
|
|
878
|
+
SolverError:
|
|
879
|
+
The problem is not agent-based.
|
|
880
|
+
"""
|
|
881
|
+
self.parameters_ = problem.initial_parameters.copy()
|
|
882
|
+
self.inputs_: Mapping[str, object] = {}
|
|
883
|
+
self.deposits_ = np.zeros(problem.states.size)
|
|
884
|
+
self.reports_: dict[str, object] = {}
|
|
885
|
+
self.reported_: dict[str, deque[object]] = {}
|
|
886
|
+
self.storage_: dict[str, dict[str, object]] = {}
|
|
887
|
+
self.buffer_: dict[tuple[mesa.Agent, str], object] | None = None
|
|
888
|
+
self.round_ = 0
|
|
889
|
+
self.visit_ = (0, 0)
|
|
890
|
+
self.observed_: dict[str, deque[object]] = {}
|
|
891
|
+
self._compositions: dict[tuple[str, str], dict[Hashable, int]] = {}
|
|
892
|
+
self._live: Array | None = None
|
|
893
|
+
self._state: Array = problem.initial_state
|
|
894
|
+
self._evaluator: ObservableEvaluator | None = None
|
|
895
|
+
self._populating = True
|
|
896
|
+
self._specs = {spec.path: spec for spec in problem.agents}
|
|
897
|
+
self._lags = {
|
|
898
|
+
spec.path: {
|
|
899
|
+
name: declaration.lags
|
|
900
|
+
for name, declaration in declarations_of(self._agent_type(spec), VariableKind.STATE).items()
|
|
901
|
+
if declaration.lags
|
|
902
|
+
}
|
|
903
|
+
for spec in problem.agents
|
|
904
|
+
}
|
|
905
|
+
self._quantities = {
|
|
906
|
+
spec.path: [
|
|
907
|
+
name
|
|
908
|
+
for name, declaration in declarations_of(self._agent_type(spec), VariableKind.STATE).items()
|
|
909
|
+
if declaration.quantity is not None
|
|
910
|
+
]
|
|
911
|
+
for spec in problem.agents
|
|
912
|
+
}
|
|
913
|
+
self._classes: dict[type, CompiledAgentsSpec] = {}
|
|
914
|
+
self._view_classes: dict[type, type[AgentView]] = {}
|
|
915
|
+
self.members_: dict[int, mesa.Agent] = {}
|
|
916
|
+
self.model_ = _AgentModel(self._run_rules, self._seed())
|
|
917
|
+
self.space_ = self._build_space(
|
|
918
|
+
problem.agent_space,
|
|
919
|
+
self.model_,
|
|
920
|
+
sum(spec.size for spec in problem.agents),
|
|
921
|
+
)
|
|
922
|
+
roles = {item.path: item.roles for item in problem.interactions}
|
|
923
|
+
self._views = {spec.path: ModelView(self, spec.path) for spec in problem.agents}
|
|
924
|
+
self._rules: list[tuple[ModelView, RuleLaw]] = []
|
|
925
|
+
self._member_rules: dict[str, list[tuple[ModelView, RuleLaw]]] = {}
|
|
926
|
+
for owner, rule in problem.model_rules:
|
|
927
|
+
if not isinstance(rule, RuleLaw):
|
|
928
|
+
continue
|
|
929
|
+
view = ModelView(self, owner, roles.get(owner))
|
|
930
|
+
if rule.members is None:
|
|
931
|
+
self._rules.append((view, rule))
|
|
932
|
+
continue
|
|
933
|
+
for path in view._paths(rule.members):
|
|
934
|
+
self._member_rules.setdefault(path, []).append((view, rule))
|
|
935
|
+
declared = self._declared_phases(problem.system) if problem.system is not None else []
|
|
936
|
+
self._phases = self._phase_plan(declared, problem)
|
|
937
|
+
owners = [(item.path, type(item.interaction)) for item in problem.interactions] + [
|
|
938
|
+
(spec.path, spec.element.element if isinstance(spec.element, GroupElement) else type(spec.element))
|
|
939
|
+
for spec in problem.agents
|
|
940
|
+
]
|
|
941
|
+
for path, component in owners:
|
|
942
|
+
for name in getattr(component, 'reports', ()):
|
|
943
|
+
self.reports_[f'{path}.{name}'] = math.nan
|
|
944
|
+
for spec in problem.agents:
|
|
945
|
+
self._populate(spec)
|
|
946
|
+
for spec in problem.agents:
|
|
947
|
+
self._resolve_references(spec)
|
|
948
|
+
self._populating = False
|
|
949
|
+
self._collect()
|
|
950
|
+
|
|
951
|
+
def _agent_class(self, spec: CompiledAgentsSpec) -> type:
|
|
952
|
+
"""Return the Mesa agent class of a group, created on first use."""
|
|
953
|
+
for agent_class, known in self._classes.items():
|
|
954
|
+
if known is spec:
|
|
955
|
+
return agent_class
|
|
956
|
+
space = self.problem_.agent_space
|
|
957
|
+
base = (
|
|
958
|
+
CellAgent
|
|
959
|
+
if isinstance(space, LatticeSpace | NetworkSpace)
|
|
960
|
+
else ContinuousSpaceAgent if space else mesa.Agent
|
|
961
|
+
)
|
|
962
|
+
|
|
963
|
+
def step(agent: mesa.Agent) -> None:
|
|
964
|
+
"""Run the rules of the agent's type and its member rules unless the agent was removed earlier."""
|
|
965
|
+
view = self._view_of(agent)
|
|
966
|
+
for model, rule in self._agent_rules(spec):
|
|
967
|
+
if getattr(agent, 'removed_', False):
|
|
968
|
+
return
|
|
969
|
+
rule.function(view, model)
|
|
970
|
+
|
|
971
|
+
agent_class = type(f'{spec.path.replace("/", "_")}_agent', (base,), {'step': step})
|
|
972
|
+
self._classes[agent_class] = spec
|
|
973
|
+
self._view_classes[agent_class] = self._view_class(spec)
|
|
974
|
+
return agent_class
|
|
975
|
+
|
|
976
|
+
def _agent_rules(self, spec: CompiledAgentsSpec) -> list[tuple[ModelView, RuleLaw]]:
|
|
977
|
+
"""Return the rules of an agent with their views, those of its element and then its member rules."""
|
|
978
|
+
own = [(self._views[spec.path], rule) for rule in self._rules_of(spec.rules)]
|
|
979
|
+
return own + self._member_rules.get(spec.path, [])
|
|
980
|
+
|
|
981
|
+
def _place(self, agent: mesa.Agent, location: object) -> None:
|
|
982
|
+
"""Place a new agent at a location, or at a random place that respects the space's capacity."""
|
|
983
|
+
space = self.problem_.agent_space
|
|
984
|
+
if isinstance(space, ContinuousSpace):
|
|
985
|
+
point = location if location is not None else self.model_.rng.uniform([0, 0], space.extent_[:2])
|
|
986
|
+
agent.position = np.asarray(point, dtype=float)
|
|
987
|
+
elif space is not None:
|
|
988
|
+
cells = self._cells()
|
|
989
|
+
if location is not None:
|
|
990
|
+
agent.cell = cells[self._cell_key(location)]
|
|
991
|
+
elif space.capacity is not None:
|
|
992
|
+
agent.cell = cells.select_random_empty_cell()
|
|
993
|
+
else:
|
|
994
|
+
agent.cell = cells.all_cells.select_random_cell()
|
|
995
|
+
|
|
996
|
+
def _cells(self) -> OrthogonalMooreGrid | OrthogonalVonNeumannGrid | Network:
|
|
997
|
+
"""Return the Mesa grid or network the agents live on.
|
|
998
|
+
|
|
999
|
+
Returns:
|
|
1000
|
+
cells:
|
|
1001
|
+
The Mesa grid or network.
|
|
1002
|
+
|
|
1003
|
+
Raises:
|
|
1004
|
+
SimulationError:
|
|
1005
|
+
The agents live in a continuous space or in no space, which has no cells.
|
|
1006
|
+
"""
|
|
1007
|
+
space = self.space_
|
|
1008
|
+
if not isinstance(space, OrthogonalMooreGrid | OrthogonalVonNeumannGrid | Network):
|
|
1009
|
+
error_msg = 'The agents live in no grid or network, which has no cells.'
|
|
1010
|
+
raise SimulationError(error_msg)
|
|
1011
|
+
return space
|
|
1012
|
+
|
|
1013
|
+
def _resolve_group(self, group: str, scope: str = '') -> str:
|
|
1014
|
+
"""Return the path of a group named relative to the system of a component, or by its path.
|
|
1015
|
+
|
|
1016
|
+
Args:
|
|
1017
|
+
group:
|
|
1018
|
+
The path of the group relative to the system that holds `scope`, or from the root.
|
|
1019
|
+
|
|
1020
|
+
scope:
|
|
1021
|
+
The path of a group or an interaction whose system relative paths are resolved in.
|
|
1022
|
+
|
|
1023
|
+
Returns:
|
|
1024
|
+
path:
|
|
1025
|
+
The path of the group.
|
|
1026
|
+
|
|
1027
|
+
Raises:
|
|
1028
|
+
SimulationError:
|
|
1029
|
+
No group has that path or label.
|
|
1030
|
+
"""
|
|
1031
|
+
prefix = scope.rpartition('/')[0]
|
|
1032
|
+
for candidate in (f'{prefix}/{group}' if prefix else group, group):
|
|
1033
|
+
if candidate in self._specs:
|
|
1034
|
+
return candidate
|
|
1035
|
+
error_msg = f'No agent group {group!r}. Available groups are: {", ".join(self._specs)}.'
|
|
1036
|
+
raise SimulationError(error_msg)
|
|
1037
|
+
|
|
1038
|
+
def _create_agent(self, group: str, location: object, values: Mapping[str, object]) -> mesa.Agent:
|
|
1039
|
+
"""Create an agent of a group with initial state values, placed at a location or a random place.
|
|
1040
|
+
|
|
1041
|
+
Args:
|
|
1042
|
+
group:
|
|
1043
|
+
The path of the group.
|
|
1044
|
+
|
|
1045
|
+
location:
|
|
1046
|
+
The location, or `None` for a random place.
|
|
1047
|
+
|
|
1048
|
+
values:
|
|
1049
|
+
The initial values of states, with the element type's defaults for the others.
|
|
1050
|
+
|
|
1051
|
+
Returns:
|
|
1052
|
+
agent:
|
|
1053
|
+
The Mesa agent.
|
|
1054
|
+
|
|
1055
|
+
Raises:
|
|
1056
|
+
SimulationError:
|
|
1057
|
+
The group does not exist, or it is not variable, so its size cannot change.
|
|
1058
|
+
"""
|
|
1059
|
+
spec = self._specs[self._resolve_group(group)]
|
|
1060
|
+
if not self._populating:
|
|
1061
|
+
self._check_variable(spec, 'create')
|
|
1062
|
+
agent_class = self._agent_class(spec)
|
|
1063
|
+
agent = (
|
|
1064
|
+
agent_class(self.space_, self.model_)
|
|
1065
|
+
if agent_class.__mro__[1] is ContinuousSpaceAgent
|
|
1066
|
+
else agent_class(self.model_)
|
|
1067
|
+
)
|
|
1068
|
+
agent.__dict__['view_'] = self._view_classes[agent_class](agent, self)
|
|
1069
|
+
self.members_[int(agent.unique_id)] = agent
|
|
1070
|
+
defaults = self._agent_type(spec)
|
|
1071
|
+
for name in spec.states:
|
|
1072
|
+
value = values[name] if name in values else self._shared_default(defaults, name)
|
|
1073
|
+
setattr(agent, name, value)
|
|
1074
|
+
self._place(agent, location)
|
|
1075
|
+
self._recount(agent, 1)
|
|
1076
|
+
return agent
|
|
1077
|
+
|
|
1078
|
+
def _populate(self, spec: CompiledAgentsSpec) -> None:
|
|
1079
|
+
"""Create the initial agents of a group with their per-agent or shared initial values."""
|
|
1080
|
+
space = self.problem_.agent_space
|
|
1081
|
+
network_nodes = list(space.graph.nodes) if isinstance(space, NetworkSpace) else []
|
|
1082
|
+
given = spec.element.location if isinstance(spec.element, GroupElement) else None
|
|
1083
|
+
for index in range(spec.size):
|
|
1084
|
+
values = {name: self._member_of(spec, name, value, index) for name, value in spec.values.items()}
|
|
1085
|
+
location = self._member_location(given, index, spec.size)
|
|
1086
|
+
if location is None and spec.size <= len(network_nodes):
|
|
1087
|
+
location = network_nodes[index]
|
|
1088
|
+
self._create_agent(spec.path, location, values)
|
|
1089
|
+
|
|
1090
|
+
def _reference_of(self, spec: CompiledAgentsSpec, state: str) -> str | None:
|
|
1091
|
+
"""Return the path of the group a reference state of a group names members of.
|
|
1092
|
+
|
|
1093
|
+
Args:
|
|
1094
|
+
spec:
|
|
1095
|
+
The compiled agent group.
|
|
1096
|
+
|
|
1097
|
+
state:
|
|
1098
|
+
The name of the state.
|
|
1099
|
+
|
|
1100
|
+
Returns:
|
|
1101
|
+
path:
|
|
1102
|
+
The path of the referenced group, or `None` when the model has no such group, so the state names no
|
|
1103
|
+
member.
|
|
1104
|
+
|
|
1105
|
+
Raises:
|
|
1106
|
+
KeyError:
|
|
1107
|
+
The state names no member of a group.
|
|
1108
|
+
"""
|
|
1109
|
+
declaration = declarations_of(self._agent_type(spec), VariableKind.STATE).get(state)
|
|
1110
|
+
if declaration is None or declaration.reference is None:
|
|
1111
|
+
error_msg = (
|
|
1112
|
+
f'The state {state!r} of {spec.path} names no member of a group. Declare it with '
|
|
1113
|
+
'`StateSpec(reference=group)` to read the member it names.'
|
|
1114
|
+
)
|
|
1115
|
+
raise KeyError(error_msg)
|
|
1116
|
+
try:
|
|
1117
|
+
return self._resolve_group(declaration.reference, spec.path)
|
|
1118
|
+
except SimulationError:
|
|
1119
|
+
return None
|
|
1120
|
+
|
|
1121
|
+
def _resolve_references(self, spec: CompiledAgentsSpec) -> None:
|
|
1122
|
+
"""Turn the initial positions held by the reference states of a group into the ids of the members they name.
|
|
1123
|
+
|
|
1124
|
+
Args:
|
|
1125
|
+
spec:
|
|
1126
|
+
The compiled agent group.
|
|
1127
|
+
|
|
1128
|
+
Raises:
|
|
1129
|
+
SimulationError:
|
|
1130
|
+
An initial position is beyond the initial members of the referenced group.
|
|
1131
|
+
"""
|
|
1132
|
+
declarations = declarations_of(self._agent_type(spec), VariableKind.STATE)
|
|
1133
|
+
for name, declaration in declarations.items():
|
|
1134
|
+
if declaration.reference is None:
|
|
1135
|
+
continue
|
|
1136
|
+
path = self._reference_of(spec, name)
|
|
1137
|
+
members = sorted(self._group_agents(path), key=lambda agent: agent.unique_id) if path else []
|
|
1138
|
+
ids = [agent.unique_id for agent in members]
|
|
1139
|
+
for agent in self._group_agents(spec.path):
|
|
1140
|
+
position = int(float(getattr(agent, name)))
|
|
1141
|
+
if position >= len(ids):
|
|
1142
|
+
error_msg = (
|
|
1143
|
+
f'The state {name!r} of {spec.path} names the member at position {position} of '
|
|
1144
|
+
f'{path or declaration.reference}, which has {len(ids)} members.'
|
|
1145
|
+
)
|
|
1146
|
+
raise SimulationError(error_msg)
|
|
1147
|
+
setattr(agent, name, float(ids[position]) if position >= 0 else -1.0)
|
|
1148
|
+
|
|
1149
|
+
def _spec_of(self, agent: mesa.Agent) -> CompiledAgentsSpec:
|
|
1150
|
+
"""Return the group of a Mesa agent created by the stepper.
|
|
1151
|
+
|
|
1152
|
+
Args:
|
|
1153
|
+
agent:
|
|
1154
|
+
The Mesa agent.
|
|
1155
|
+
|
|
1156
|
+
Returns:
|
|
1157
|
+
spec:
|
|
1158
|
+
The compiled agent group.
|
|
1159
|
+
"""
|
|
1160
|
+
return self._classes[type(agent)]
|
|
1161
|
+
|
|
1162
|
+
def _agents_of(self, group: str) -> list[AgentView] | None:
|
|
1163
|
+
"""Return the views of the alive agents of a group, or `None` when the model has no such group."""
|
|
1164
|
+
if group not in self._specs:
|
|
1165
|
+
return None
|
|
1166
|
+
return [self._view_of(agent) for agent in self._group_agents(group)]
|
|
1167
|
+
|
|
1168
|
+
def _group_agents(self, group: str) -> list[mesa.Agent]:
|
|
1169
|
+
"""Return the alive Mesa agents of a group.
|
|
1170
|
+
|
|
1171
|
+
Args:
|
|
1172
|
+
group:
|
|
1173
|
+
The path of the group.
|
|
1174
|
+
|
|
1175
|
+
Returns:
|
|
1176
|
+
agents:
|
|
1177
|
+
The Mesa agents.
|
|
1178
|
+
"""
|
|
1179
|
+
for agent_class, spec in self._classes.items():
|
|
1180
|
+
if spec.path == group:
|
|
1181
|
+
return list(self.model_.agents_by_type.get(agent_class, []))
|
|
1182
|
+
return []
|
|
1183
|
+
|
|
1184
|
+
def _push_parameters(self, p: Array) -> None:
|
|
1185
|
+
"""Make new parameter values visible to the rules."""
|
|
1186
|
+
self.parameters_ = p.copy()
|
|
1187
|
+
|
|
1188
|
+
def _composition(self, path: str, state: str) -> dict[Hashable, int]:
|
|
1189
|
+
"""Return the counts of the values of a state among the agents of a group, kept from their first reading.
|
|
1190
|
+
|
|
1191
|
+
Args:
|
|
1192
|
+
path:
|
|
1193
|
+
The path of the group.
|
|
1194
|
+
|
|
1195
|
+
state:
|
|
1196
|
+
The name of the state.
|
|
1197
|
+
|
|
1198
|
+
Returns:
|
|
1199
|
+
counts:
|
|
1200
|
+
The number of agents of the group by value of the state.
|
|
1201
|
+
|
|
1202
|
+
Raises:
|
|
1203
|
+
SimulationError:
|
|
1204
|
+
The agents of the group have no such state.
|
|
1205
|
+
"""
|
|
1206
|
+
states = self._specs[path].states
|
|
1207
|
+
if state not in states:
|
|
1208
|
+
error_msg = f'The agents of {path} have no state {state!r}. Count one of: {", ".join(states)}.'
|
|
1209
|
+
raise SimulationError(error_msg)
|
|
1210
|
+
counts = self._compositions.get((path, state))
|
|
1211
|
+
if counts is None:
|
|
1212
|
+
counts = {}
|
|
1213
|
+
for agent in self._group_agents(path):
|
|
1214
|
+
value = MesaSolver._counted(getattr(agent, state))
|
|
1215
|
+
counts[value] = counts.get(value, 0) + 1
|
|
1216
|
+
self._compositions[path, state] = counts
|
|
1217
|
+
return counts
|
|
1218
|
+
|
|
1219
|
+
def _recount(self, agent: mesa.Agent, change: int, names: Iterable[str] | None = None) -> None:
|
|
1220
|
+
"""Add a change to the counts of the values an agent holds, of the states named or of every counted state."""
|
|
1221
|
+
if not self._compositions:
|
|
1222
|
+
return
|
|
1223
|
+
path = self._spec_of(agent).path
|
|
1224
|
+
for (group, state), counts in self._compositions.items():
|
|
1225
|
+
if group == path and (names is None or state in names):
|
|
1226
|
+
value = MesaSolver._counted(getattr(agent, state))
|
|
1227
|
+
counts[value] = counts.get(value, 0) + change
|
|
1228
|
+
|
|
1229
|
+
def _write(self, agent: mesa.Agent, name: str, value: object) -> None:
|
|
1230
|
+
"""Set a state of an agent and keep the counts of its values."""
|
|
1231
|
+
self._recount(agent, -1, (name,))
|
|
1232
|
+
setattr(agent, name, value)
|
|
1233
|
+
self._recount(agent, 1, (name,))
|
|
1234
|
+
|
|
1235
|
+
def _observe(self) -> None:
|
|
1236
|
+
"""Add the scalar values of the observables of the run at the end of a step to their histories."""
|
|
1237
|
+
if not self.problem_.observables:
|
|
1238
|
+
return
|
|
1239
|
+
if self._evaluator is None:
|
|
1240
|
+
self._evaluator = ObservableEvaluator(self.problem_).prepare()
|
|
1241
|
+
values = self._evaluator.evaluate(float(self.model_.time), self._state, self.parameters_, self._agents_of)
|
|
1242
|
+
for name, value in values.items():
|
|
1243
|
+
array = value if isinstance(value, np.ndarray) else None
|
|
1244
|
+
history = self.observed_.setdefault(name, deque(maxlen=_HISTORY_LENGTH))
|
|
1245
|
+
if isinstance(value, numbers.Number) or (
|
|
1246
|
+
array is not None and array.ndim == 0 and np.issubdtype(array.dtype, np.number)
|
|
1247
|
+
):
|
|
1248
|
+
history.append(float(np.real(np.asarray(value))))
|
|
1249
|
+
elif isinstance(value, Hashable):
|
|
1250
|
+
history.append(value)
|
|
1251
|
+
|
|
1252
|
+
def _run_rules(self) -> None:
|
|
1253
|
+
"""Run the phases due in a step, or activate the agents in random order and run the model rules once."""
|
|
1254
|
+
if self._phases is None:
|
|
1255
|
+
self.model_.agents.shuffle_do('step')
|
|
1256
|
+
for model, rule in self._rules:
|
|
1257
|
+
rule.function(model)
|
|
1258
|
+
else:
|
|
1259
|
+
for phase in self._phases:
|
|
1260
|
+
if (round(self.model_.time) - phase.offset) % phase.period:
|
|
1261
|
+
continue
|
|
1262
|
+
for index in range(phase.repeat):
|
|
1263
|
+
self.round_ = index
|
|
1264
|
+
self._run_phase(phase)
|
|
1265
|
+
self.round_ = 0
|
|
1266
|
+
self._remember()
|
|
1267
|
+
self._observe()
|
|
1268
|
+
|
|
1269
|
+
def _phase_paths(self, phase: PhaseSpec) -> list[str]:
|
|
1270
|
+
"""Return the paths of the groups a phase activates, those it names or every group."""
|
|
1271
|
+
return [self._resolve_group(group) for group in phase.groups or [spec.path for spec in self.problem_.agents]]
|
|
1272
|
+
|
|
1273
|
+
def _ordered_agents(self, phase: PhaseSpec) -> list[mesa.Agent]:
|
|
1274
|
+
"""Return the agents of a phase in the order of its activation policy."""
|
|
1275
|
+
if phase.activation == 'sequential':
|
|
1276
|
+
return sorted(self.model_.agents, key=lambda agent: agent.unique_id)
|
|
1277
|
+
if phase.activation == 'by-type':
|
|
1278
|
+
paths = self._phase_paths(phase)
|
|
1279
|
+
ordered: list[mesa.Agent] = []
|
|
1280
|
+
for path in paths:
|
|
1281
|
+
members = sorted(self._group_agents(path), key=lambda agent: agent.unique_id)
|
|
1282
|
+
ordered += [members[index] for index in self.model_.rng.permutation(len(members))]
|
|
1283
|
+
return ordered
|
|
1284
|
+
agents = sorted(self.model_.agents, key=lambda agent: agent.unique_id)
|
|
1285
|
+
return [agents[index] for index in self.model_.rng.permutation(len(agents))]
|
|
1286
|
+
|
|
1287
|
+
def _activate(self, agent: mesa.Agent, phase: PhaseSpec) -> None:
|
|
1288
|
+
"""Run the rules of an agent in a phase, those of its element and then its member rules, while it lives."""
|
|
1289
|
+
view = self._view_of(agent)
|
|
1290
|
+
for model, rule in self._agent_rules(self._spec_of(agent)):
|
|
1291
|
+
if getattr(agent, 'removed_', False):
|
|
1292
|
+
return
|
|
1293
|
+
if self._phase_of(rule) == phase.name:
|
|
1294
|
+
rule.function(view, model)
|
|
1295
|
+
|
|
1296
|
+
def _visit(self, phase: PhaseSpec) -> None:
|
|
1297
|
+
"""Activate agents of a phase drawn with replacement, `visits` times as many as there are at its start."""
|
|
1298
|
+
paths = self._phase_paths(phase)
|
|
1299
|
+
count = int(sum(len(self._group_agents(path)) for path in paths) * phase.visits)
|
|
1300
|
+
try:
|
|
1301
|
+
for visit in range(count):
|
|
1302
|
+
agents = [agent for path in paths for agent in self._group_agents(path)]
|
|
1303
|
+
if not agents:
|
|
1304
|
+
return
|
|
1305
|
+
self.visit_ = (visit, count)
|
|
1306
|
+
self._activate(agents[int(self.model_.rng.integers(len(agents)))], phase)
|
|
1307
|
+
finally:
|
|
1308
|
+
self.visit_ = (0, 0)
|
|
1309
|
+
|
|
1310
|
+
def _run_phase(self, phase: PhaseSpec) -> None:
|
|
1311
|
+
"""Run the agent rules of a phase under its activation policy, then the model rules of the phase."""
|
|
1312
|
+
if phase.activation == 'simultaneous':
|
|
1313
|
+
self.buffer_ = {}
|
|
1314
|
+
try:
|
|
1315
|
+
if phase.activation == 'visits':
|
|
1316
|
+
self._visit(phase)
|
|
1317
|
+
else:
|
|
1318
|
+
for agent in self._ordered_agents(phase):
|
|
1319
|
+
self._activate(agent, phase)
|
|
1320
|
+
finally:
|
|
1321
|
+
buffer, self.buffer_ = self.buffer_, None
|
|
1322
|
+
for (agent, name), value in (buffer or {}).items():
|
|
1323
|
+
self._write(agent, name, value)
|
|
1324
|
+
for model, rule in self._rules:
|
|
1325
|
+
if self._phase_of(rule) == phase.name:
|
|
1326
|
+
rule.function(model)
|
|
1327
|
+
|
|
1328
|
+
def _remember(self) -> None:
|
|
1329
|
+
"""Shift the past values of the states with lags of every agent, at the end of a step."""
|
|
1330
|
+
for agent in self.model_.agents:
|
|
1331
|
+
for name, lags in self._lags[self._spec_of(agent).path].items():
|
|
1332
|
+
for index in range(lags, 1, -1):
|
|
1333
|
+
setattr(agent, f'{name}_lag{index}', getattr(agent, f'{name}_lag{index - 1}'))
|
|
1334
|
+
setattr(agent, f'{name}_lag1', getattr(agent, name))
|
|
1335
|
+
|
|
1336
|
+
def _set_parameter(self, name: str, value: float) -> None:
|
|
1337
|
+
"""Set a parameter during a step, so the rules read it at once and the trajectory records it.
|
|
1338
|
+
|
|
1339
|
+
Args:
|
|
1340
|
+
name:
|
|
1341
|
+
The dotted name of the parameter.
|
|
1342
|
+
|
|
1343
|
+
value:
|
|
1344
|
+
The new value.
|
|
1345
|
+
"""
|
|
1346
|
+
_, indices = self.problem_.parameters.locate(name)
|
|
1347
|
+
self.parameters_[indices] = value
|
|
1348
|
+
if self._live is not None:
|
|
1349
|
+
self._live[indices] = value
|
|
1350
|
+
|
|
1351
|
+
def _observable(self, name: str) -> object:
|
|
1352
|
+
"""Return the current value of an observable of the problem.
|
|
1353
|
+
|
|
1354
|
+
Args:
|
|
1355
|
+
name:
|
|
1356
|
+
The path of the observable.
|
|
1357
|
+
|
|
1358
|
+
Returns:
|
|
1359
|
+
value:
|
|
1360
|
+
Its value for the current agents and parameters.
|
|
1361
|
+
|
|
1362
|
+
Raises:
|
|
1363
|
+
SimulationError:
|
|
1364
|
+
The problem has no such observable.
|
|
1365
|
+
"""
|
|
1366
|
+
if self._evaluator is None:
|
|
1367
|
+
self._evaluator = ObservableEvaluator(self.problem_).prepare()
|
|
1368
|
+
values = self._evaluator.evaluate(float(self.model_.time), self._state, self.parameters_, self._agents_of)
|
|
1369
|
+
if name not in values:
|
|
1370
|
+
error_msg = f'No observable named {name!r}. Available observables are: {", ".join(values) or "none"}.'
|
|
1371
|
+
raise SimulationError(error_msg)
|
|
1372
|
+
return values[name]
|
|
1373
|
+
|
|
1374
|
+
def _advance(self, t: float, x: Array, p: Array, until: float) -> Array:
|
|
1375
|
+
"""Run one Mesa step per integer time from `t` up to `until`.
|
|
1376
|
+
|
|
1377
|
+
Args:
|
|
1378
|
+
t:
|
|
1379
|
+
The current time.
|
|
1380
|
+
|
|
1381
|
+
x:
|
|
1382
|
+
The current state vector, empty for agent-based problems.
|
|
1383
|
+
|
|
1384
|
+
p:
|
|
1385
|
+
The parameter vector.
|
|
1386
|
+
|
|
1387
|
+
until:
|
|
1388
|
+
The time to advance to.
|
|
1389
|
+
|
|
1390
|
+
Returns:
|
|
1391
|
+
state:
|
|
1392
|
+
The unchanged state vector.
|
|
1393
|
+
"""
|
|
1394
|
+
if not np.array_equal(p, self.parameters_):
|
|
1395
|
+
self._push_parameters(p)
|
|
1396
|
+
self._live, self._state = p, x
|
|
1397
|
+
for step in range(math.floor(t + 1e-9), math.floor(until + 1e-9)):
|
|
1398
|
+
del step
|
|
1399
|
+
self.model_.step()
|
|
1400
|
+
return x
|
|
1401
|
+
|
|
1402
|
+
def _collect(self) -> None:
|
|
1403
|
+
"""Set the agents of every group and the reporters at the current step."""
|
|
1404
|
+
groups, agents = {}, {}
|
|
1405
|
+
for spec in self.problem_.agents:
|
|
1406
|
+
agents[spec.path] = self._group_agents(spec.path)
|
|
1407
|
+
groups[spec.path] = self._snapshot_of(
|
|
1408
|
+
agents[spec.path],
|
|
1409
|
+
{name: self._attribute(name) for name in spec.states},
|
|
1410
|
+
spec,
|
|
1411
|
+
)
|
|
1412
|
+
reporters = {f'{path}.count': float(len(snapshot.ids)) for path, snapshot in groups.items()}
|
|
1413
|
+
super()._collect()
|
|
1414
|
+
self.snapshot_ = AgentStateSpec(groups, {**reporters, **self.reports_})
|
|
1415
|
+
self.agents_ = {path: [self._view_of(agent) for agent in members] for path, members in agents.items()}
|
|
1416
|
+
|
|
1417
|
+
@staticmethod
|
|
1418
|
+
def _build_space(space: BaseSpace | None, model: mesa.Model, n_agents: int) -> MesaSpace | None:
|
|
1419
|
+
"""Return the Mesa space of a framework space."""
|
|
1420
|
+
if isinstance(space, LatticeSpace):
|
|
1421
|
+
grid = OrthogonalVonNeumannGrid if space.neighborhood == 'von_neumann' else OrthogonalMooreGrid
|
|
1422
|
+
return grid(space.shape_[:2], torus=space.periodic_, capacity=space.capacity, random=model.random)
|
|
1423
|
+
if isinstance(space, NetworkSpace):
|
|
1424
|
+
return Network(space.graph, capacity=space.capacity, random=model.random, layout=None)
|
|
1425
|
+
if isinstance(space, ContinuousSpace):
|
|
1426
|
+
bounds = [[0.0, space.extent_[0]], [0.0, space.extent_[1]]]
|
|
1427
|
+
return MesaContinuousSpace(bounds, torus=space.periodic_, random=model.random, n_agents=max(n_agents, 1))
|
|
1428
|
+
return None
|
|
1429
|
+
|
|
1430
|
+
@staticmethod
|
|
1431
|
+
def _rules_of(laws: Iterable[BaseLaw]) -> list[RuleLaw]:
|
|
1432
|
+
"""Return the rules among laws, which the compiled agents and the model rules hold alone."""
|
|
1433
|
+
return [law for law in laws if isinstance(law, RuleLaw)]
|
|
1434
|
+
|
|
1435
|
+
@staticmethod
|
|
1436
|
+
def _phase_of(rule: RuleLaw) -> str:
|
|
1437
|
+
"""Return the name of the phase a rule runs in."""
|
|
1438
|
+
return rule.phase or DEFAULT_PHASE
|
|
1439
|
+
|
|
1440
|
+
@staticmethod
|
|
1441
|
+
def _declared_phases(system: System) -> list[PhaseSpec]:
|
|
1442
|
+
"""Return the phases of the schedules of a system and its nested systems, the first of every name kept."""
|
|
1443
|
+
time = system.time
|
|
1444
|
+
schedule = time.check().prepare().schedule_ if isinstance(time, DiscreteTime) else None
|
|
1445
|
+
phases = list(schedule.phases) if isinstance(schedule, PhasesScheduleSpec) else []
|
|
1446
|
+
for nested in system.systems:
|
|
1447
|
+
phases += MesaSolver._declared_phases(nested)
|
|
1448
|
+
kept: dict[str, PhaseSpec] = {}
|
|
1449
|
+
for phase in phases:
|
|
1450
|
+
kept.setdefault(phase.name, phase)
|
|
1451
|
+
return list(kept.values())
|
|
1452
|
+
|
|
1453
|
+
@staticmethod
|
|
1454
|
+
def _phase_plan(phases: Sequence[PhaseSpec], problem: ProblemSpec) -> list[PhaseSpec] | None:
|
|
1455
|
+
"""Return the phases of a step with the default phase, or `None` when no phase is declared or named."""
|
|
1456
|
+
rules = MesaSolver._rules_of(
|
|
1457
|
+
[*(rule for spec in problem.agents for rule in spec.rules), *(rule for _, rule in problem.model_rules)],
|
|
1458
|
+
)
|
|
1459
|
+
if not phases and all(rule.phase is None for rule in rules):
|
|
1460
|
+
return None
|
|
1461
|
+
names = [phase.name for phase in phases]
|
|
1462
|
+
plan = list(phases) if DEFAULT_PHASE in names else [PhaseSpec(DEFAULT_PHASE), *phases]
|
|
1463
|
+
unknown = sorted({MesaSolver._phase_of(rule) for rule in rules} - {phase.name for phase in plan})
|
|
1464
|
+
if unknown:
|
|
1465
|
+
error_msg = (
|
|
1466
|
+
f'Rules run in the phases {", ".join(unknown)}, which the system does not declare. Declared phases '
|
|
1467
|
+
f'are: {", ".join(names) or "none"}.'
|
|
1468
|
+
)
|
|
1469
|
+
raise SimulationError(error_msg)
|
|
1470
|
+
return plan
|
|
1471
|
+
|
|
1472
|
+
@staticmethod
|
|
1473
|
+
def _attribute(name: str) -> Callable[[mesa.Agent], object]:
|
|
1474
|
+
"""Return a function that reads an attribute of an agent."""
|
|
1475
|
+
return lambda agent: getattr(agent, name)
|
|
1476
|
+
|
|
1477
|
+
@staticmethod
|
|
1478
|
+
def _snapshot_of(
|
|
1479
|
+
agents: list[mesa.Agent],
|
|
1480
|
+
reporters: Mapping[str, Callable[[mesa.Agent], object]],
|
|
1481
|
+
spec: CompiledAgentsSpec,
|
|
1482
|
+
) -> AgentSnapshotSpec:
|
|
1483
|
+
"""Return the ids, reported values, and locations of agents, one value per agent for a state of objects."""
|
|
1484
|
+
agents = sorted(agents, key=lambda agent: agent.unique_id)
|
|
1485
|
+
ids = np.array([agent.unique_id for agent in agents], dtype=np.int64)
|
|
1486
|
+
values = {
|
|
1487
|
+
name: (
|
|
1488
|
+
np.fromiter(map(reporter, agents), dtype=object, count=len(agents))
|
|
1489
|
+
if name in spec.objects
|
|
1490
|
+
else np.asarray([reporter(agent) for agent in agents])
|
|
1491
|
+
)
|
|
1492
|
+
for name, reporter in reporters.items()
|
|
1493
|
+
}
|
|
1494
|
+
locations = [MesaSolver._location_of(agent) for agent in agents]
|
|
1495
|
+
has_locations = any(location is not None for location in locations)
|
|
1496
|
+
return AgentSnapshotSpec(ids, values, np.asarray(locations) if has_locations else None, spec.roles)
|
|
1497
|
+
|
|
1498
|
+
@staticmethod
|
|
1499
|
+
def _member_location(location: object, index: int, size: int) -> object:
|
|
1500
|
+
"""Return the initial location of one agent from per-agent locations or one shared location."""
|
|
1501
|
+
if location is None:
|
|
1502
|
+
return None
|
|
1503
|
+
array = np.asarray(location, dtype=object if isinstance(location, list | tuple) else None)
|
|
1504
|
+
if array.ndim >= 1 and array.shape[0] == size:
|
|
1505
|
+
return MesaSolver._cell_key(np.asarray(array[index]))
|
|
1506
|
+
return MesaSolver._cell_key(location)
|
|
1507
|
+
|
|
1508
|
+
@staticmethod
|
|
1509
|
+
def _shared_default(element_type: type, name: str) -> object:
|
|
1510
|
+
"""Return the default of a state of an element type."""
|
|
1511
|
+
return default_of(element_type, name)
|
|
1512
|
+
|
|
1513
|
+
@staticmethod
|
|
1514
|
+
def _state_property(name: str) -> property:
|
|
1515
|
+
"""Return the property of a state of agents, which sets the agent at the end of a simultaneous phase."""
|
|
1516
|
+
|
|
1517
|
+
def read(view: AgentView) -> object:
|
|
1518
|
+
return getattr(view._agent, name)
|
|
1519
|
+
|
|
1520
|
+
def write(view: AgentView, value: object) -> None:
|
|
1521
|
+
buffer = view._stepper.buffer_
|
|
1522
|
+
if buffer is not None:
|
|
1523
|
+
buffer[view._agent, name] = value
|
|
1524
|
+
return
|
|
1525
|
+
view._stepper._write(view._agent, name, value)
|
|
1526
|
+
|
|
1527
|
+
return property(read, write, doc=f'State {name} of the agent.')
|
|
1528
|
+
|
|
1529
|
+
@staticmethod
|
|
1530
|
+
def _parameter_property(name: str, entry: str) -> property:
|
|
1531
|
+
"""Return the read-only property of a parameter of the group of agents."""
|
|
1532
|
+
|
|
1533
|
+
def read(view: AgentView) -> float:
|
|
1534
|
+
stepper = view._stepper
|
|
1535
|
+
return float(np.ravel(stepper.problem_.parameters.read(stepper.parameters_, entry))[0])
|
|
1536
|
+
|
|
1537
|
+
return property(read, doc=f'Parameter {name} of the group of the agent.')
|
|
1538
|
+
|
|
1539
|
+
@staticmethod
|
|
1540
|
+
def _view_class(spec: CompiledAgentsSpec) -> type[AgentView]:
|
|
1541
|
+
"""Return the class of the views of a group's agents, with a property per state and parameter."""
|
|
1542
|
+
names: dict[str, object] = {
|
|
1543
|
+
name: MesaSolver._parameter_property(name, entry)
|
|
1544
|
+
for name, entry in spec.parameters.items()
|
|
1545
|
+
if name not in spec.states
|
|
1546
|
+
}
|
|
1547
|
+
names.update({name: MesaSolver._state_property(name) for name in spec.states})
|
|
1548
|
+
names['__slots__'] = ()
|
|
1549
|
+
base = MesaSolver._agent_type(spec)._get_view() or AgentView
|
|
1550
|
+
if not issubclass(base, AgentView):
|
|
1551
|
+
error_msg = f'The view of {spec.path} is {base.__name__}, which does not derive from AgentView.'
|
|
1552
|
+
raise ValidationError(error_msg)
|
|
1553
|
+
return type(f'{spec.path.replace("/", "_")}_view', (base,), names)
|
|
1554
|
+
|
|
1555
|
+
@staticmethod
|
|
1556
|
+
def _counted(value: object) -> Hashable:
|
|
1557
|
+
"""Return the key that counts a value of a state: a float for a number, and an object as it is."""
|
|
1558
|
+
if isinstance(value, numbers.Real):
|
|
1559
|
+
return float(value)
|
|
1560
|
+
if not isinstance(value, Hashable):
|
|
1561
|
+
error_msg = f'A composition counts hashable values, but an agent holds {value!r}. Give it as a tuple.'
|
|
1562
|
+
raise SimulationError(error_msg)
|
|
1563
|
+
return value
|
|
1564
|
+
|
|
1565
|
+
@staticmethod
|
|
1566
|
+
def _member_of(spec: CompiledAgentsSpec, name: str, value: object, index: int) -> object:
|
|
1567
|
+
"""Return the initial value of one agent: of a list of one object per agent, or of one shared value."""
|
|
1568
|
+
if name not in spec.objects:
|
|
1569
|
+
return MesaSolver._member_value(value, index, spec.size)
|
|
1570
|
+
return value[index] if isinstance(value, list | np.ndarray) and len(value) == spec.size else value
|
|
1571
|
+
|
|
1572
|
+
@staticmethod
|
|
1573
|
+
def _member_value(value: object, index: int, size: int) -> object:
|
|
1574
|
+
"""Return the initial value of one agent from a per-agent array or a shared value."""
|
|
1575
|
+
array = np.asarray(value)
|
|
1576
|
+
if array.ndim and array.shape[0] == size:
|
|
1577
|
+
item = array[index]
|
|
1578
|
+
return item.item() if np.ndim(item) == 0 else item
|
|
1579
|
+
return value
|
|
1580
|
+
|
|
1581
|
+
@staticmethod
|
|
1582
|
+
def _agent_type(spec: CompiledAgentsSpec) -> type[BaseElement]:
|
|
1583
|
+
"""Return the element type of a compiled agent element or group."""
|
|
1584
|
+
return spec.element.element if isinstance(spec.element, GroupElement) else type(spec.element)
|
|
1585
|
+
|
|
1586
|
+
@staticmethod
|
|
1587
|
+
def _cell_key(location: object) -> object:
|
|
1588
|
+
"""Return a location as a hashable cell key, a tuple of grid coordinates or a network node."""
|
|
1589
|
+
if isinstance(location, np.ndarray | list | tuple):
|
|
1590
|
+
values = np.asarray(location).tolist()
|
|
1591
|
+
return tuple(values) if isinstance(values, list) else values
|
|
1592
|
+
return location.item() if isinstance(location, np.generic) else location
|
|
1593
|
+
|
|
1594
|
+
@staticmethod
|
|
1595
|
+
def _check_variable(spec: CompiledAgentsSpec, action: str) -> None:
|
|
1596
|
+
"""Raise an error when a rule changes the size of an agent element or of a group that is not variable."""
|
|
1597
|
+
if isinstance(spec.element, GroupElement) and spec.element.variable:
|
|
1598
|
+
return
|
|
1599
|
+
error_msg = (
|
|
1600
|
+
f'A rule tries to {action} an agent of {spec.path}, whose size is fixed. Declare the group with '
|
|
1601
|
+
'`variable=True`, such as `GroupElement(label, element=..., size=..., variable=True)`, for its members '
|
|
1602
|
+
'to be created and removed during a run.'
|
|
1603
|
+
)
|
|
1604
|
+
raise SimulationError(error_msg)
|
|
1605
|
+
|
|
1606
|
+
@staticmethod
|
|
1607
|
+
def _location_of(agent: mesa.Agent) -> object:
|
|
1608
|
+
"""Return the location of a Mesa agent: grid coordinates, a network node, a position, or `None`."""
|
|
1609
|
+
cell = getattr(agent, 'cell', None)
|
|
1610
|
+
if cell is not None:
|
|
1611
|
+
return cell.coordinate
|
|
1612
|
+
position = getattr(agent, 'position', None)
|
|
1613
|
+
if position is not None:
|
|
1614
|
+
return tuple(np.asarray(position, dtype=float))
|
|
1615
|
+
return getattr(agent, 'pos', None)
|
|
1616
|
+
|
|
1617
|
+
@staticmethod
|
|
1618
|
+
def _view_of(agent: mesa.Agent) -> AgentView:
|
|
1619
|
+
"""Return the view of an agent, which the stepper creates with the agent."""
|
|
1620
|
+
view = agent.__dict__['view_']
|
|
1621
|
+
if not isinstance(view, AgentView):
|
|
1622
|
+
error_msg = f'The agent holds a {type(view).__name__}, not the view the stepper creates with it.'
|
|
1623
|
+
raise TypeError(error_msg)
|
|
1624
|
+
return view
|