paramrf 0.37.4__tar.gz → 0.37.5__tar.gz
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.
- {paramrf-0.37.4 → paramrf-0.37.5}/AGENTS.md +0 -1
- {paramrf-0.37.4 → paramrf-0.37.5}/CLAUDE.md +0 -1
- {paramrf-0.37.4 → paramrf-0.37.5}/CONTEXT.md +70 -6
- {paramrf-0.37.4/paramrf.egg-info → paramrf-0.37.5}/PKG-INFO +1 -1
- paramrf-0.37.5/docs/adr/0008-shared-discrepancy.md +40 -0
- paramrf-0.37.5/docs/adr/0009-least-squares-map-fits.md +106 -0
- {paramrf-0.37.4 → paramrf-0.37.5/paramrf.egg-info}/PKG-INFO +1 -1
- {paramrf-0.37.4 → paramrf-0.37.5}/paramrf.egg-info/SOURCES.txt +6 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/fitting/minimize.py +32 -2
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/objectives/__init__.py +3 -1
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/objectives/evaluators.py +287 -29
- paramrf-0.37.5/pmrf/objectives/problems.py +268 -0
- paramrf-0.37.5/pmrf/objectives/shared.py +278 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/objectives/terms.py +16 -1
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/optimize/__init__.py +4 -1
- paramrf-0.37.5/pmrf/optimize/base.py +383 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/optimize/minimize.py +8 -1
- paramrf-0.37.5/pmrf/optimize/solvers/scipy.py +460 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/parameters/__init__.py +3 -1
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/stats/__init__.py +9 -1
- paramrf-0.37.5/pmrf/stats/shared_discrepancy.py +108 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pyproject.toml +1 -1
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_evaluators.py +88 -3
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_fitting_minimize.py +52 -1
- paramrf-0.37.5/tests/test_least_squares.py +561 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_linearization.py +106 -10
- paramrf-0.37.5/tests/test_shared_discrepancy.py +464 -0
- paramrf-0.37.4/pmrf/objectives/problems.py +0 -155
- paramrf-0.37.4/pmrf/optimize/base.py +0 -216
- paramrf-0.37.4/pmrf/optimize/solvers/scipy.py +0 -236
- {paramrf-0.37.4 → paramrf-0.37.5}/.github/workflows/docs.yml +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/.github/workflows/draft-pdf.yml +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/.github/workflows/publish.yml +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/.github/workflows/tests.yml +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/.gitignore +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/CHANGELOG.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/CITATION.cff +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/CONTRIBUTING.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/LICENSE +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/NOTICE +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/README.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/assets/logo.png +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/Makefile +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/_static/custom.css +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/_templates/autosummary/class.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/_templates/autosummary/function.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/_templates/autosummary/module.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/adr/0001-line-modelling-architecture.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/adr/0002-parameter-api.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/adr/0003-derived-models.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/adr/0004-profiled-lines.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/adr/0005-priors-by-name.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/adr/0006-reference-impedance.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/adr/0007-edge-values.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/agents/domain.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/agents/issue-tracker.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/agents/triage-labels.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/api/index.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/conf.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/core_concepts/core_primitives.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/core_concepts/index.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/core_concepts/jax_overview.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/core_concepts/optimization_and_inference.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/core_concepts/parameter_names.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/cascading_and_terminating.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/circuit_clc.png +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/circuit_models.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/custom_models.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/derivatives_and_sweeps.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/discrepancy_prediction.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/index.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/model_optimization.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/multiple_models_one_parameter_set.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/parameter_naming_and_model_manipulation.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/examples/shared_modules.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/index.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/license.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/make.bat +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/research/conductor-loss-alternatives.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/research/holloway1994.pdf +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/research/microstrip-loss-conventions.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/research/precision-coax-microstrip-10-500mhz.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/skrf_comparison/index.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/skrf_comparison/overview.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/skrf_comparison/performance.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/tutorials/1_cable_fitting.ipynb +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/tutorials/2_chip_inductor_fitting.ipynb +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/tutorials/3_discrepancy_transfer.ipynb +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/tutorials/data/CBN-1.5FT-SMSM.s2p +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/tutorials/data/on-chip-inductor.s2p +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/tutorials/index.rst +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/tutorials/line_internal_discrepancy.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/docs/tutorials/port_discrepancy.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/paper/paper.bib +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/paper/paper.md +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/paper/rlc.png +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/paramrf.egg-info/dependency_links.txt +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/paramrf.egg-info/requires.txt +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/paramrf.egg-info/top_level.txt +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/_solver_view.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/fitting/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/fitting/result.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/fitting/routers.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/fitting/sample.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/fitting/targets.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/frequency.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/infer/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/infer/base.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/infer/result.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/infer/sample.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/infer/solvers/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/infer/solvers/blackjax.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/infer/solvers/polychord.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/materials/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/materials/conductor.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/materials/dielectric.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/materials/properties.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/materials/roughness.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/materials/substrate.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/materials/surface_impedance.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/math/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/math/aggregations.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/math/bessel.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/math/conversions.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/math/losses.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/math/misc.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/adapters/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/adapters/base.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/adapters/bridge.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/adapters/callable.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/adapters/delegated.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/adapters/derived.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/adapters/static.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/adapters/wrapped.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/base.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/ideal.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/base.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/coaxial.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/empirical.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/ideal.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/microstrip.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/nodal.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/nonuniform.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/planar.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/profiles.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lines/stripline.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/lumped.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/components/sections.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/cascade.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/circuit/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/circuit/base.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/circuit/circuit.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/circuit/solvers/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/circuit/solvers/nodal.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/circuit/solvers/scattering.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/interconnected/terminated.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/nodal.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/topological.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/composite/transformed.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/line_discrepancy.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/port_discrepancy.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/surrogates/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/surrogates/expansion.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/models/surrogates/rational.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/modules/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/modules/base.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/modules/wrapped.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/network_collection.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/objectives/losses.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/optimize/result.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/optimize/solvers/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/optimize/solvers/jaxopt.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/optimize/solvers/optimistix.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/parameters/constraints.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/rf/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/rf/cascade.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/rf/conversions.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/rf/mna.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/serialization.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/stats/bijectors.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/stats/covariance_kernels.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/stats/discrepancy_models.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/stats/distributions.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/stats/likelihoods.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/stats/linearization.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/stats/noise_models.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/types.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/array.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/debug.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/network.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/random.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/rf.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/transforms.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/tree.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/utils/type.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/viz/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/pmrf/viz/plots.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/scripts/benchmark_gp_marginal_likelihood.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/scripts/install-test-deps.sh +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/setup.cfg +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/__init__.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/_jit.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/conftest.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/data/10m_cable.s2p +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_autodiff.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_box_space_solving.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_conversions.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_covariance_kernels.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_dc_limits.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_discrepancy_models.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_fitting_routers.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_fitting_sample.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_fitting_targets.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_frequency.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_grouped_exports.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_infer_base.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_infer_sample.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_line_internal_discrepancy_example.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_map_priors.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_materials/test_conductor.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_materials/test_dielectric.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_materials/test_serialization.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_materials/test_substrate.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_materials/test_surface_impedance.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_math/test_bessel.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_model.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_adapters.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_cascade.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_circuit_native_z0.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_circuit_nodal.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_circuit_port_order.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_circuit_scattering.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_circuit_shorted_ports.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_circuit_skrf_port_names.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_circuit_z0.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_current_distribution.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_derived.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_edge_values.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_interconnected.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_line_discrepancy.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_lines.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_lines_skrf_matrix.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_lumped.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_nodal.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_port_discrepancy.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_profiles.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_rational.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_repeated_cascade.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_sections.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_transformed.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_models/test_transformers.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_module.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_naming.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_optimize_base.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_optimize_minimize.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_parameters.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_parameters_by_name.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_parameters_joint_prior.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_parameters_prior.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_parameters_validity.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_port_discrepancy_example.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_raw_space_solving.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_serialization.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_structural_updates.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_terms.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_transforms.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_utils/test_compress.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_utils/test_debug.py +0 -0
- {paramrf-0.37.4 → paramrf-0.37.5}/tests/test_utils/test_tree.py +0 -0
|
@@ -27,7 +27,6 @@ there are none.
|
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
.venv/bin/python -m pytest tests/test_x.py # the tests covering a change, while working
|
|
30
|
-
.venv/bin/python -m pytest -n 4 # local test command: full suite, once before committing
|
|
31
30
|
.venv/bin/python -c "import pmrf" # import smoke check
|
|
32
31
|
```
|
|
33
32
|
|
|
@@ -27,7 +27,6 @@ there are none.
|
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
.venv/bin/python -m pytest tests/test_x.py # the tests covering a change, while working
|
|
30
|
-
.venv/bin/python -m pytest -n 4 # local test command: full suite, once before committing
|
|
31
30
|
.venv/bin/python -c "import pmrf" # import smoke check
|
|
32
31
|
```
|
|
33
32
|
|
|
@@ -184,9 +184,10 @@ noise. `pmrf.objectives.MarginalLogLikelihood` scores it; see
|
|
|
184
184
|
The space in which probability is defined: the prediction after the event
|
|
185
185
|
transform, with frequency as the last (event) axis. Every other axis is a batch
|
|
186
186
|
axis. One entry of that batch, for example the real part of S21, is an **event
|
|
187
|
-
block**.
|
|
188
|
-
block (`AutoCrossKernel` routes by block,
|
|
189
|
-
hyperparameters across blocks) and never couples
|
|
187
|
+
block**. Under a `GaussianProcess` discrepancy, blocks are independent: a kernel
|
|
188
|
+
chooses the covariance *within* each block (`AutoCrossKernel` routes by block,
|
|
189
|
+
`SharedIndependentKernel` shares hyperparameters across blocks) and never couples
|
|
190
|
+
two blocks. A **shared discrepancy** couples blocks, and datasets.
|
|
190
191
|
|
|
191
192
|
*Avoid:* "output" or "task" for a block; "cross-covariance" for the kernel an
|
|
192
193
|
`AutoCrossKernel` gives a transmission block.
|
|
@@ -194,8 +195,40 @@ hyperparameters across blocks) and never couples two blocks.
|
|
|
194
195
|
### Discrepancy
|
|
195
196
|
|
|
196
197
|
$\delta$, the systematic misfit between model and reality, as opposed to noise
|
|
197
|
-
$\varepsilon$. Either deterministic
|
|
198
|
-
It is on the observable unless it is a port or internal
|
|
198
|
+
$\varepsilon$. Either deterministic, a `GaussianProcess` over each event block, or
|
|
199
|
+
a shared discrepancy. It is on the observable unless it is a port or internal
|
|
200
|
+
discrepancy.
|
|
201
|
+
|
|
202
|
+
### Shared latent
|
|
203
|
+
|
|
204
|
+
A function of frequency with a Gaussian-process prior, common to several event blocks
|
|
205
|
+
or several datasets: for example a VNA's residual directivity, which is the same for
|
|
206
|
+
every device measured with one calibration. It has one or more rows (two for a
|
|
207
|
+
complex function: Re and Im), each an independent draw from its kernel.
|
|
208
|
+
|
|
209
|
+
*Avoid:* "task", "output" (those are event blocks); "error term" (one application's name
|
|
210
|
+
for it); "coregionalisation" in user-facing text.
|
|
211
|
+
|
|
212
|
+
### Mixing
|
|
213
|
+
|
|
214
|
+
The linear map, at each frequency, from a shared latent's rows to one dataset's event
|
|
215
|
+
blocks. It may depend on that dataset's prediction: multiplying a complex latent by the
|
|
216
|
+
predicted reflection coefficient is a mixing. A mixing may carry parameters.
|
|
217
|
+
|
|
218
|
+
### Shared discrepancy
|
|
219
|
+
|
|
220
|
+
The discrepancy formed by mixing shared latents:
|
|
221
|
+
$\delta_l(f) = \sum_j M_{lj}(f)\, g_j(f)$ for dataset $l$, with per-dataset noise on
|
|
222
|
+
top. Because the latents are common, it couples the datasets and the event blocks it
|
|
223
|
+
mixes into. `pmrf.objectives.SharedMarginalLogLikelihood` scores it.
|
|
224
|
+
|
|
225
|
+
### Latent prediction
|
|
226
|
+
|
|
227
|
+
The joint distribution of the shared latents at new frequencies, conditioned on the
|
|
228
|
+
residuals of every dataset, excluding noise. It is what transfers to a new dataset that
|
|
229
|
+
shares the latents, through that dataset's mixing.
|
|
230
|
+
|
|
231
|
+
*Avoid:* "discrepancy prediction" for this (that is per dataset, in event space).
|
|
199
232
|
|
|
200
233
|
### Residual
|
|
201
234
|
|
|
@@ -236,6 +269,34 @@ together, from a linearisation: unlike a discrepancy prediction, it carries the
|
|
|
236
269
|
parameters' uncertainty into $\delta$ and the cross-covariance between them. It is
|
|
237
270
|
the form in which one fit's posterior becomes the next fit's joint prior.
|
|
238
271
|
|
|
272
|
+
### Hyperparameter
|
|
273
|
+
|
|
274
|
+
A free parameter owned by a term rather than by the model, such as white noise or a
|
|
275
|
+
kernel's length scale. The model parameters are the free parameters of
|
|
276
|
+
`problem.model`; the hyperparameters are the rest (ADR-0009).
|
|
277
|
+
|
|
278
|
+
### Whitened residual
|
|
279
|
+
|
|
280
|
+
A term's residual scaled so that half its squared norm is the term's negative log
|
|
281
|
+
likelihood, up to terms constant in the model parameters, with the hyperparameters
|
|
282
|
+
held: $L^{-1} r$ per event block for a `MarginalLogLikelihood`, with
|
|
283
|
+
$\Sigma_D = K + \Sigma_n = L L^\top$. Its Jacobian is the whitened Jacobian of a
|
|
284
|
+
linearisation (ADR-0009).
|
|
285
|
+
|
|
286
|
+
### Prior residual
|
|
287
|
+
|
|
288
|
+
A free parameter's contribution to a least-squares fit from its prior: half its
|
|
289
|
+
squared norm is the negative log prior, up to a constant. $(\theta - \mu)/\sigma$ for a
|
|
290
|
+
normal or truncated normal prior, the Cholesky-whitened $\theta - \mu$ for a joint
|
|
291
|
+
normal prior, and nothing for a uniform prior, whose bounds are the box edges instead.
|
|
292
|
+
It is computed from the distribution, not read from raw space (ADR-0009).
|
|
293
|
+
|
|
294
|
+
### Hyperparameter step
|
|
295
|
+
|
|
296
|
+
In an alternating MAP fit, the scalar minimisation of the full negative log posterior
|
|
297
|
+
over the hyperparameters with the model parameters held. It takes the
|
|
298
|
+
$\tfrac{1}{2}\ln|\Sigma_D|$ term, which a least-squares solve cannot (ADR-0009).
|
|
299
|
+
|
|
239
300
|
### Port discrepancy
|
|
240
301
|
|
|
241
302
|
A discrepancy embedded at a component's ports, on its S-parameters rather than on
|
|
@@ -309,4 +370,7 @@ method, a public function or a value space. Read
|
|
|
309
370
|
`docs/adr/0005-priors-by-name.md` before changing how priors are attached or
|
|
310
371
|
scored, and `docs/adr/0007-edge-values.md` before changing how a
|
|
311
372
|
circuit solver produces S, how bounds are validated, or which space a solver
|
|
312
|
-
moves through.
|
|
373
|
+
moves through. Read `docs/adr/0008-shared-discrepancy.md` before coupling event
|
|
374
|
+
blocks or datasets in a discrepancy, and `docs/adr/0009-least-squares-map-fits.md`
|
|
375
|
+
before changing how a least-squares minimiser builds its residual or treats
|
|
376
|
+
hyperparameters.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Shared discrepancy is a joint evaluator over per-dataset likelihoods
|
|
2
|
+
|
|
3
|
+
A discrepancy whose latent functions are shared across datasets (or across event blocks
|
|
4
|
+
of one dataset) makes those datasets statistically dependent, so their joint likelihood
|
|
5
|
+
is not a sum of per-dataset terms. We add a new evaluator,
|
|
6
|
+
`SharedMarginalLogLikelihood`, that takes several ordinary `MarginalLogLikelihood`s
|
|
7
|
+
(each with no discrepancy of its own) plus a tuple of `SharedLatent`s, and returns one
|
|
8
|
+
joint log-likelihood. It goes into `SummedTerms` as a single term. Each `SharedLatent`
|
|
9
|
+
is a covariance kernel paired with a **mixing**: a function of the dataset's
|
|
10
|
+
event-space prediction and frequency that returns, per frequency, a real matrix from
|
|
11
|
+
the latent's rows to the dataset's event blocks. The joint covariance is low rank plus
|
|
12
|
+
diagonal and is solved by Woodbury in the latent dimension, never densely.
|
|
13
|
+
|
|
14
|
+
## Considered options
|
|
15
|
+
|
|
16
|
+
- **A shared object inside several `MarginalLogLikelihood` terms, marginalised jointly by
|
|
17
|
+
`SummedTerms`.** Rejected: `SummedTerms` would have to detect sharing and stop being a
|
|
18
|
+
sum, and the joint maths would be spread across classes that should not know about
|
|
19
|
+
each other.
|
|
20
|
+
- **Extend `GaussianProcess` and its kernels to couple event blocks** (as in the
|
|
21
|
+
correlated-GP note and the routing idea in #250). Rejected: a `GaussianProcess` is a
|
|
22
|
+
discrepancy for one dataset, and its kernels cannot see the prediction, which
|
|
23
|
+
multiplicative error (for example a VNA's tracking error, $e_t \Gamma$) needs.
|
|
24
|
+
- **An error-box model component with GP-distributed error terms.** This is the exact
|
|
25
|
+
bilinear form, but its marginal is not Gaussian. It is a separate, later feature.
|
|
26
|
+
|
|
27
|
+
## Consequences
|
|
28
|
+
|
|
29
|
+
- `MarginalLogLikelihood` exposes its event-space residual, noise variance and
|
|
30
|
+
conditional-transform log-determinant, so the joint evaluator reuses all per-dataset
|
|
31
|
+
plumbing (predictor, observation, likelihood, event transform) without copying it.
|
|
32
|
+
- A latent holds a kernel, not a `GaussianProcess`. Every existing kernel is reusable.
|
|
33
|
+
- Mixings act in event space. Helpers that multiply by the prediction assume the
|
|
34
|
+
default Re/Im event layout and say so.
|
|
35
|
+
- With a prediction-dependent mixing, the covariance depends on the model parameters;
|
|
36
|
+
gradients flow through it.
|
|
37
|
+
- A `MarginalLogLikelihood` with a `GaussianProcess` is mathematically the one-dataset,
|
|
38
|
+
identity-mixing case. Both stay: the existing class is the fast independent-block
|
|
39
|
+
path. If the two ever duplicate maths rather than share plumbing, merge them into one
|
|
40
|
+
evaluator with the independent path as an internal optimisation.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# ADR-0009: MAP fits are bounded least squares, alternating with a hyperparameter step
|
|
2
|
+
|
|
3
|
+
Status: accepted (2026-10)
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
Physical line models often have parameters that are each identifiable but jointly
|
|
8
|
+
near-degenerate: the loss is a long, narrow valley. On a synthetic `MicrostripLine` fit
|
|
9
|
+
(10-500 MHz, `w`, `h`, `ep_r`, `tand`, `sigma` and `length` free, noise 1e-5, Jacobian
|
|
10
|
+
condition number about 4e5 in box space), starting from a perturbed point:
|
|
11
|
+
|
|
12
|
+
| Method | Outcome |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `ScipyMinimize` L-BFGS-B (default) | Reports success at a wrong point |
|
|
15
|
+
| `ScipyMinimize` trust-constr (BFGS) | Not converged in 3000 iterations |
|
|
16
|
+
| trust-constr, exact JAX Hessian | Not converged in 3000 iterations, about 20x slower |
|
|
17
|
+
| trust-constr, Gauss-Newton Hessian | Not converged in 3000 iterations |
|
|
18
|
+
| trust-exact, Levenberg-Marquardt (unbounded) | Leave the box and fail |
|
|
19
|
+
| Optimistix Levenberg-Marquardt, Dogleg, Gauss-Newton (raw space) | Stall on the bounds, where the raw Jacobian vanishes |
|
|
20
|
+
| SciPy `least_squares`, `'trf'`, box space | Recovers all six true values |
|
|
21
|
+
|
|
22
|
+
The exact Hessian adds the residual-weighted second derivative of the model, the term a
|
|
23
|
+
linearisation drops. Far from the solution it hurts rather than helps.
|
|
24
|
+
|
|
25
|
+
Under a Gaussian likelihood with fixed noise and discrepancy hyperparameters, the negative
|
|
26
|
+
log posterior is half the squared norm of a residual vector, up to a constant, whenever
|
|
27
|
+
each prior is Gaussian, truncated Gaussian or uniform. Noise and kernel hyperparameters
|
|
28
|
+
are usually fitted too, and they enter through $\tfrac{1}{2}\ln|\Sigma_D|$, which is not a
|
|
29
|
+
square.
|
|
30
|
+
|
|
31
|
+
## Decision
|
|
32
|
+
|
|
33
|
+
### A least-squares minimiser over box space
|
|
34
|
+
|
|
35
|
+
`pmrf.optimize.ScipyLeastSquares` wraps `scipy.optimize.least_squares` with `'trf'`. Like
|
|
36
|
+
any minimiser that honours bounds, it searches box space and is given the box's edges
|
|
37
|
+
(ADR-0007). It minimises half the squared norm of a residual vector, not a scalar.
|
|
38
|
+
|
|
39
|
+
### The residual vector
|
|
40
|
+
|
|
41
|
+
The vector stacks the **whitened residual** of each term and the **prior residual** of each
|
|
42
|
+
free parameter.
|
|
43
|
+
|
|
44
|
+
- **Whitened residual.** For a `MarginalLogLikelihood`, $L^{-1} r$ per event block, with
|
|
45
|
+
$L$ the lower Cholesky factor of $\Sigma_D = K + \Sigma_n$: the same factor
|
|
46
|
+
`linearize` uses. For a `TargetLoss` with `MSELoss`, the prediction error scaled so
|
|
47
|
+
that half its squared norm is the loss.
|
|
48
|
+
- **Prior residual.** Computed from the distribution, in the space it is over. It is not
|
|
49
|
+
the raw value, since truncation makes the raw map nonlinear.
|
|
50
|
+
|
|
51
|
+
| Prior | Prior residual | Bounds |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| `Normal` | $(\theta - \mu)/\sigma$ | none |
|
|
54
|
+
| `TruncatedNormal`, including a `Normal` truncated to a validity | $(\theta - \mu)/\sigma$ | the truncation |
|
|
55
|
+
| Joint multivariate normal, including `truncate='unnormalised'` | $L_0^{-1}(\theta - \mu)$, with $\Sigma_0 = L_0 L_0^\top$ | each parameter's validity |
|
|
56
|
+
| `Uniform`, or no prior | none | the parameter's bounds |
|
|
57
|
+
|
|
58
|
+
A truncation normaliser is constant in $\theta$, so it does not move the MAP.
|
|
59
|
+
|
|
60
|
+
### Alternating with a hyperparameter step
|
|
61
|
+
|
|
62
|
+
The level above the minimiser splits the free parameters. The model parameters are the
|
|
63
|
+
free parameters of `problem.model`. The **hyperparameters** are the free parameters the
|
|
64
|
+
terms own, such as white noise and kernel hyperparameters. `run_minimizer` hands the
|
|
65
|
+
minimiser both groups: a residual function of the model parameters given the
|
|
66
|
+
hyperparameters, and the full scalar objective of the hyperparameters given the model
|
|
67
|
+
parameters. The minimiser knows nothing about noise or kernels.
|
|
68
|
+
|
|
69
|
+
Each round is a least-squares solve over the model parameters, then a **hyperparameter
|
|
70
|
+
step**: a scalar minimisation of the full negative log posterior over the hyperparameters
|
|
71
|
+
with the model parameters held, by `hyper_minimizer` (default `ScipyMinimize()`). The fit
|
|
72
|
+
stops when a round no longer decreases the full objective. With no free hyperparameters
|
|
73
|
+
it is a single least-squares solve.
|
|
74
|
+
|
|
75
|
+
### Not yet supported
|
|
76
|
+
|
|
77
|
+
Each of these raises an error saying it is not yet supported:
|
|
78
|
+
|
|
79
|
+
- noise given as a callable of the prediction, since $\Sigma_D$ then depends on the
|
|
80
|
+
model parameters;
|
|
81
|
+
- a mixing that depends on the prediction, for the same reason;
|
|
82
|
+
- orthogonal discrepancy without a fixed reference basis;
|
|
83
|
+
- priors other than those in the table, such as a prior over raw space carried to
|
|
84
|
+
declared space with a change-of-variables term;
|
|
85
|
+
- `GibbsMarginalLogLikelihood`, losses other than `MSELoss`, and any term without a
|
|
86
|
+
whitened residual.
|
|
87
|
+
|
|
88
|
+
## Considered options
|
|
89
|
+
|
|
90
|
+
- **Restore the exact Hessian in `ScipyMinimize`.** Rejected as the fix: it did not
|
|
91
|
+
converge on the degenerate fit and is slow to compile. It may still be added for other
|
|
92
|
+
reasons.
|
|
93
|
+
- **Optimistix least-squares solvers.** They keep the fit in JAX, but take no bounds, and
|
|
94
|
+
in raw space they stall on the bounds. Rejected.
|
|
95
|
+
- **One least-squares solve over model parameters and hyperparameters together.** The
|
|
96
|
+
log-determinant is not a square; writing it as one gives a residual with a singular
|
|
97
|
+
derivative. Rejected.
|
|
98
|
+
|
|
99
|
+
## Consequences
|
|
100
|
+
|
|
101
|
+
- At the MAP, the stacked whitened Jacobian and prior square root of the last
|
|
102
|
+
least-squares solve are the $A$ of `posterior_covariance_factor`. The fit and its
|
|
103
|
+
linearisation share one approximation.
|
|
104
|
+
- `ScipyMinimize`'s commented-out Hessian path is removed.
|
|
105
|
+
- Shared discrepancy is supported once its whitened residual covers the joint covariance
|
|
106
|
+
across datasets, for mixings that do not depend on the prediction.
|
|
@@ -30,6 +30,8 @@ docs/adr/0004-profiled-lines.md
|
|
|
30
30
|
docs/adr/0005-priors-by-name.md
|
|
31
31
|
docs/adr/0006-reference-impedance.md
|
|
32
32
|
docs/adr/0007-edge-values.md
|
|
33
|
+
docs/adr/0008-shared-discrepancy.md
|
|
34
|
+
docs/adr/0009-least-squares-map-fits.md
|
|
33
35
|
docs/agents/domain.md
|
|
34
36
|
docs/agents/issue-tracker.md
|
|
35
37
|
docs/agents/triage-labels.md
|
|
@@ -155,6 +157,7 @@ pmrf/objectives/__init__.py
|
|
|
155
157
|
pmrf/objectives/evaluators.py
|
|
156
158
|
pmrf/objectives/losses.py
|
|
157
159
|
pmrf/objectives/problems.py
|
|
160
|
+
pmrf/objectives/shared.py
|
|
158
161
|
pmrf/objectives/terms.py
|
|
159
162
|
pmrf/optimize/__init__.py
|
|
160
163
|
pmrf/optimize/base.py
|
|
@@ -178,6 +181,7 @@ pmrf/stats/distributions.py
|
|
|
178
181
|
pmrf/stats/likelihoods.py
|
|
179
182
|
pmrf/stats/linearization.py
|
|
180
183
|
pmrf/stats/noise_models.py
|
|
184
|
+
pmrf/stats/shared_discrepancy.py
|
|
181
185
|
pmrf/utils/__init__.py
|
|
182
186
|
pmrf/utils/array.py
|
|
183
187
|
pmrf/utils/debug.py
|
|
@@ -209,6 +213,7 @@ tests/test_frequency.py
|
|
|
209
213
|
tests/test_grouped_exports.py
|
|
210
214
|
tests/test_infer_base.py
|
|
211
215
|
tests/test_infer_sample.py
|
|
216
|
+
tests/test_least_squares.py
|
|
212
217
|
tests/test_line_internal_discrepancy_example.py
|
|
213
218
|
tests/test_linearization.py
|
|
214
219
|
tests/test_map_priors.py
|
|
@@ -225,6 +230,7 @@ tests/test_parameters_validity.py
|
|
|
225
230
|
tests/test_port_discrepancy_example.py
|
|
226
231
|
tests/test_raw_space_solving.py
|
|
227
232
|
tests/test_serialization.py
|
|
233
|
+
tests/test_shared_discrepancy.py
|
|
228
234
|
tests/test_structural_updates.py
|
|
229
235
|
tests/test_terms.py
|
|
230
236
|
tests/test_transforms.py
|
|
@@ -40,6 +40,8 @@ def fit_minimize(
|
|
|
40
40
|
noise: Param | Callable[[jnp.ndarray], jnp.ndarray] = None,
|
|
41
41
|
discrepancy: Callable[[jnp.ndarray, jnp.ndarray], dist.AbstractDistribution] | None = None,
|
|
42
42
|
temperature: float = None,
|
|
43
|
+
use_orthogonal_discrepancy: bool = False,
|
|
44
|
+
orthogonal_rcond: float | None = None,
|
|
43
45
|
**kwargs,
|
|
44
46
|
) -> FitResult[PyTreeT]:
|
|
45
47
|
"""
|
|
@@ -61,6 +63,14 @@ def fit_minimize(
|
|
|
61
63
|
solver : AbstractMinimizer, optional
|
|
62
64
|
The optimizer to use.
|
|
63
65
|
See :mod:`pmrf.optimize` for available solvers.
|
|
66
|
+
:class:`pmrf.optimize.ScipyLeastSquares` suits fits whose parameters are
|
|
67
|
+
jointly near-degenerate. It supports a frequentist fit with
|
|
68
|
+
:class:`pmrf.objectives.losses.MSELoss`, and a bayesian fit with a
|
|
69
|
+
:class:`pmrf.stats.likelihoods.GaussianLikelihood`, fitting a free noise and a
|
|
70
|
+
Gaussian-process discrepancy's hyperparameters by alternating with a
|
|
71
|
+
hyperparameter step. Noise given as a callable of the prediction, orthogonal
|
|
72
|
+
discrepancy without a fixed reference basis, and priors on the model other than
|
|
73
|
+
normal, truncated normal and uniform are not yet supported.
|
|
64
74
|
features : str | list[str] | Callable[[PyTree, Frequency], jnp.ndarray], default='s'
|
|
65
75
|
The RF features to fit.
|
|
66
76
|
Can either be function, a callable PyTree with optional parameters, or a string,
|
|
@@ -114,6 +124,12 @@ def fit_minimize(
|
|
|
114
124
|
The temperature value for generalized Bayesian optimization.
|
|
115
125
|
Only allowed if `inference` is 'bayesian' and `loss` is not None.
|
|
116
126
|
Defaults to 1.0 internally.
|
|
127
|
+
use_orthogonal_discrepancy : bool, default=False
|
|
128
|
+
Fix the discrepancy's tangent basis at the initial model for each dataset.
|
|
129
|
+
Requires a discrepancy model.
|
|
130
|
+
orthogonal_rcond : float, optional
|
|
131
|
+
Relative cutoff for the tangent basis singular values. Required when
|
|
132
|
+
enabling orthogonal discrepancy.
|
|
117
133
|
**kwargs : dict
|
|
118
134
|
Additional keyword arguments passed to :func:`pmrf.optimize.minimize`
|
|
119
135
|
and then underlying solver.
|
|
@@ -139,6 +155,8 @@ def fit_minimize(
|
|
|
139
155
|
raise ValueError("Only one of either `loss` or `likelihood` can be past to `fit_minimize`")
|
|
140
156
|
if discrepancy is not None and not (likelihood is not None or inference == 'bayesian'):
|
|
141
157
|
raise ValueError("Discrepancy models can only be passed if `likelihood` is passed or `inference` is 'bayesian'`")
|
|
158
|
+
if use_orthogonal_discrepancy and discrepancy is None:
|
|
159
|
+
raise ValueError("`use_orthogonal_discrepancy=True` requires a discrepancy model")
|
|
142
160
|
|
|
143
161
|
# Resolve data and features
|
|
144
162
|
datasets = resolve_datasets(features, data, frequency)
|
|
@@ -161,10 +179,22 @@ def fit_minimize(
|
|
|
161
179
|
evaluator = TargetLoss(predictor=dataset.predictor, target=dataset.target, loss=loss)
|
|
162
180
|
else:
|
|
163
181
|
if likelihood is not None:
|
|
164
|
-
mll = MarginalLogLikelihood(
|
|
182
|
+
mll = MarginalLogLikelihood(
|
|
183
|
+
predictor=dataset.predictor, observed=dataset.target, likelihood=likelihood,
|
|
184
|
+
discrepancy=discrepancy,
|
|
185
|
+
use_orthogonal_discrepancy=use_orthogonal_discrepancy,
|
|
186
|
+
orthogonal_rcond=orthogonal_rcond,
|
|
187
|
+
)
|
|
165
188
|
else:
|
|
166
189
|
temperature = temperature if temperature is not None else 1.0
|
|
167
|
-
mll = GibbsMarginalLogLikelihood(
|
|
190
|
+
mll = GibbsMarginalLogLikelihood(
|
|
191
|
+
predictor=dataset.predictor, observed=dataset.target, loss=loss,
|
|
192
|
+
discrepancy=discrepancy, temperature=temperature,
|
|
193
|
+
use_orthogonal_discrepancy=use_orthogonal_discrepancy,
|
|
194
|
+
orthogonal_rcond=orthogonal_rcond,
|
|
195
|
+
)
|
|
196
|
+
if use_orthogonal_discrepancy:
|
|
197
|
+
mll = mll.with_orthogonal_reference(model, dataset.frequency)
|
|
168
198
|
evaluator = Negated(mll)
|
|
169
199
|
objective.append((evaluator, dataset.frequency))
|
|
170
200
|
|
|
@@ -31,6 +31,7 @@ if TYPE_CHECKING:
|
|
|
31
31
|
SummedTerms as SummedTerms,
|
|
32
32
|
problem_terms as problem_terms,
|
|
33
33
|
)
|
|
34
|
+
from .shared import SharedMarginalLogLikelihood as SharedMarginalLogLikelihood
|
|
34
35
|
from .terms import (
|
|
35
36
|
AbstractTerm as AbstractTerm,
|
|
36
37
|
BoundEvaluator as BoundEvaluator,
|
|
@@ -59,6 +60,7 @@ _EXPORTS = {
|
|
|
59
60
|
'Negated': 'evaluators',
|
|
60
61
|
'PriorPenalized': 'problems',
|
|
61
62
|
'RMSELoss': 'losses',
|
|
63
|
+
'SharedMarginalLogLikelihood': 'shared',
|
|
62
64
|
'SummedTerms': 'problems',
|
|
63
65
|
'TargetLoss': 'evaluators',
|
|
64
66
|
'TermFn': 'terms',
|
|
@@ -66,7 +68,7 @@ _EXPORTS = {
|
|
|
66
68
|
'as_terms': 'terms',
|
|
67
69
|
'problem_terms': 'problems',
|
|
68
70
|
}
|
|
69
|
-
_MODULES = {'evaluators', 'losses', 'problems', 'terms'}
|
|
71
|
+
_MODULES = {'evaluators', 'losses', 'problems', 'shared', 'terms'}
|
|
70
72
|
|
|
71
73
|
def __getattr__(name):
|
|
72
74
|
if name in _MODULES:
|