paramrf 0.36.4__tar.gz → 0.36.6__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.36.4 → paramrf-0.36.6}/CONTEXT.md +105 -1
- {paramrf-0.36.4/paramrf.egg-info → paramrf-0.36.6}/PKG-INFO +2 -2
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/adr/0002-parameter-api.md +13 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/adr/0005-priors-by-name.md +54 -3
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/adr/0007-edge-values.md +61 -1
- paramrf-0.36.6/docs/examples/discrepancy_prediction.rst +77 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/index.rst +2 -0
- paramrf-0.36.6/docs/examples/port_discrepancy.py +409 -0
- paramrf-0.36.6/docs/examples/port_discrepancy.rst +53 -0
- {paramrf-0.36.4 → paramrf-0.36.6/paramrf.egg-info}/PKG-INFO +2 -2
- {paramrf-0.36.4 → paramrf-0.36.6}/paramrf.egg-info/SOURCES.txt +9 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/paramrf.egg-info/requires.txt +1 -1
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/_solver_view.py +48 -13
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/covariance_kernels.py +52 -19
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/discrepancy_models.py +136 -21
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/evaluators.py +255 -9
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/fitting/minimize.py +7 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/infer/base.py +15 -4
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/likelihoods.py +34 -40
- paramrf-0.36.6/pmrf/linearization.py +198 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/__init__.py +5 -0
- paramrf-0.36.6/pmrf/models/port_discrepancy.py +175 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/modules/wrapped.py +14 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/optimize/base.py +6 -2
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/optimize/minimize.py +6 -0
- paramrf-0.36.6/pmrf/optimize/solvers/scipy.py +236 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/parameters.py +320 -82
- {paramrf-0.36.4 → paramrf-0.36.6}/pyproject.toml +2 -2
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_box_space_solving.py +6 -4
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_covariance_kernels.py +20 -0
- paramrf-0.36.6/tests/test_discrepancy_models.py +248 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_evaluators.py +230 -14
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_fitting_minimize.py +115 -2
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_infer_base.py +42 -1
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_infer_sample.py +38 -3
- paramrf-0.36.6/tests/test_linearization.py +417 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_derived.py +12 -2
- paramrf-0.36.6/tests/test_models/test_port_discrepancy.py +144 -0
- paramrf-0.36.6/tests/test_optimize_minimize.py +374 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_parameters.py +94 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_parameters_joint_prior.py +529 -9
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_parameters_validity.py +11 -0
- paramrf-0.36.6/tests/test_port_discrepancy_example.py +70 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_raw_space_solving.py +93 -1
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_structural_updates.py +10 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_terms.py +3 -1
- paramrf-0.36.4/pmrf/optimize/solvers/scipy.py +0 -172
- paramrf-0.36.4/tests/test_optimize_minimize.py +0 -118
- {paramrf-0.36.4 → paramrf-0.36.6}/.github/workflows/docs.yml +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/.github/workflows/draft-pdf.yml +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/.github/workflows/publish.yml +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/.github/workflows/tests.yml +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/.gitignore +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/AGENTS.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/CHANGELOG.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/CITATION.cff +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/CLAUDE.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/CONTRIBUTING.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/LICENSE +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/NOTICE +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/README.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/assets/logo.png +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/Makefile +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/_static/custom.css +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/_templates/autosummary/class.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/_templates/autosummary/function.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/_templates/autosummary/module.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/adr/0001-line-modelling-architecture.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/adr/0003-derived-models.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/adr/0004-profiled-lines.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/adr/0006-reference-impedance.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/agents/domain.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/agents/issue-tracker.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/agents/triage-labels.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/api/index.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/conf.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/core_concepts/core_primitives.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/core_concepts/index.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/core_concepts/jax_overview.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/core_concepts/optimization_and_inference.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/core_concepts/parameter_names.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/cascading_and_terminating.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/circuit_clc.png +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/circuit_models.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/custom_models.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/derivatives_and_sweeps.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/model_optimization.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/multiple_models_one_parameter_set.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/parameter_naming_and_model_manipulation.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/examples/shared_substrates.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/index.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/license.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/make.bat +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/research/conductor-loss-alternatives.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/research/holloway1994.pdf +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/research/microstrip-loss-conventions.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/research/precision-coax-microstrip-10-500mhz.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/skrf_comparison/index.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/skrf_comparison/overview.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/skrf_comparison/performance.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/tutorials/1_cable_fitting.ipynb +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/tutorials/2_chip_inductor_fitting.ipynb +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/tutorials/data/CBN-1.5FT-SMSM.s2p +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/tutorials/data/on-chip-inductor.s2p +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/docs/tutorials/index.rst +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/paper/paper.bib +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/paper/paper.md +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/paper/rlc.png +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/paramrf.egg-info/dependency_links.txt +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/paramrf.egg-info/top_level.txt +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/bijectors.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/constraints.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/distributions.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/fitting/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/fitting/result.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/fitting/routers.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/fitting/sample.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/fitting/targets.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/frequency.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/infer/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/infer/result.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/infer/sample.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/infer/solvers/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/infer/solvers/blackjax.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/infer/solvers/polychord.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/losses.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/materials/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/materials/conductor.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/materials/dielectric.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/materials/properties.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/materials/roughness.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/materials/substrate.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/materials/surface_impedance.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/math/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/math/aggregations.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/math/bessel.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/math/conversions.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/math/losses.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/math/misc.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/adapters/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/adapters/base.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/adapters/bridge.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/adapters/callable.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/adapters/delegated.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/adapters/derived.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/adapters/static.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/adapters/wrapped.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/base.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/ideal.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/base.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/coaxial.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/empirical.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/ideal.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/microstrip.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/nodal.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/nonuniform.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/planar.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/profiles.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lines/stripline.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/lumped.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/components/sections.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/cascade.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/circuit/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/circuit/base.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/circuit/circuit.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/circuit/solvers/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/circuit/solvers/nodal.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/circuit/solvers/scattering.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/interconnected/terminated.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/nodal.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/topological.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/composite/transformed.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/surrogates/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/surrogates/expansion.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/models/surrogates/rational.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/modules/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/modules/base.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/network_collection.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/noise_models.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/optimize/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/optimize/result.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/optimize/solvers/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/optimize/solvers/jaxopt.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/optimize/solvers/optimistix.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/problems.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/rf/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/rf/cascade.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/rf/conversions.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/rf/mna.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/serialization.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/terms.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/types.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/array.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/debug.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/network.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/random.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/rf.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/transforms.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/tree.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/utils/type.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/viz/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/pmrf/viz/plots.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/scripts/benchmark_gp_marginal_likelihood.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/scripts/install-test-deps.sh +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/setup.cfg +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/__init__.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/_jit.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/conftest.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/data/10m_cable.s2p +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_autodiff.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_conversions.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_dc_limits.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_fitting_routers.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_fitting_sample.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_fitting_targets.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_frequency.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_map_priors.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_materials/test_conductor.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_materials/test_dielectric.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_materials/test_serialization.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_materials/test_substrate.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_materials/test_surface_impedance.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_math/test_bessel.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_model.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_adapters.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_cascade.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_circuit_native_z0.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_circuit_nodal.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_circuit_port_order.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_circuit_scattering.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_circuit_shorted_ports.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_circuit_skrf_port_names.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_circuit_z0.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_current_distribution.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_edge_values.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_interconnected.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_lines.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_lines_skrf_matrix.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_lumped.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_nodal.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_profiles.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_rational.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_repeated_cascade.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_sections.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_transformed.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_models/test_transformers.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_module.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_naming.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_optimize_base.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_parameters_by_name.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_parameters_prior.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_serialization.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_transforms.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_utils/test_compress.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_utils/test_debug.py +0 -0
- {paramrf-0.36.4 → paramrf-0.36.6}/tests/test_utils/test_tree.py +0 -0
|
@@ -98,7 +98,9 @@ is derived, so it has no prior of its own.
|
|
|
98
98
|
|
|
99
99
|
`prf.prior` attaches a prior to the parameters a selector picks (ADR-0005). A
|
|
100
100
|
scalar distribution gives each of them its own prior. A distribution whose
|
|
101
|
-
event size equals the
|
|
101
|
+
event size equals the parameters' total size (their number, when they are
|
|
102
|
+
scalars; an array parameter counts each of its values) is a **joint prior** over
|
|
103
|
+
them: a
|
|
102
104
|
wrapper (`prf.modules.Probabilistic`) around the unchanged tree, so every
|
|
103
105
|
parameter keeps its name. A joint prior replaces its parameters' own priors,
|
|
104
106
|
and its `space` says which space its distribution is over. Raw space for its
|
|
@@ -170,6 +172,108 @@ Modifies conductor behaviour rather than line state — it scales a surface
|
|
|
170
172
|
impedance — so it belongs to the material, not the geometry: it is a field of
|
|
171
173
|
`RoughConductor` in `pmrf.materials.conductor`.
|
|
172
174
|
|
|
175
|
+
## Discrepancy modelling
|
|
176
|
+
|
|
177
|
+
A fit in Kennedy–O'Hagan form treats an observation as $\tilde h = h(\theta) +
|
|
178
|
+
\delta + \varepsilon$: the model prediction, a **discrepancy** and measurement
|
|
179
|
+
noise. `MarginalLogLikelihood` scores it; see `pmrf.discrepancy_models` and
|
|
180
|
+
`pmrf.likelihoods`.
|
|
181
|
+
|
|
182
|
+
### Event space and event block
|
|
183
|
+
|
|
184
|
+
The space in which probability is defined: the prediction after the event
|
|
185
|
+
transform, with frequency as the last (event) axis. Every other axis is a batch
|
|
186
|
+
axis. One entry of that batch, for example the real part of S21, is an **event
|
|
187
|
+
block**. Blocks are independent: a kernel chooses the covariance *within* each
|
|
188
|
+
block (`AutoCrossKernel` routes by block, `SharedIndependentKernel` shares
|
|
189
|
+
hyperparameters across blocks) and never couples two blocks.
|
|
190
|
+
|
|
191
|
+
*Avoid:* "output" or "task" for a block; "cross-covariance" for the kernel an
|
|
192
|
+
`AutoCrossKernel` gives a transmission block.
|
|
193
|
+
|
|
194
|
+
### Discrepancy
|
|
195
|
+
|
|
196
|
+
$\delta$, the systematic misfit between model and reality, as opposed to noise
|
|
197
|
+
$\varepsilon$. Either deterministic or a `GaussianProcess` over each event block.
|
|
198
|
+
It is on the observable unless it is a port or internal discrepancy.
|
|
199
|
+
|
|
200
|
+
### Residual
|
|
201
|
+
|
|
202
|
+
The observation minus the model prediction, in event space: $r = \tilde h -
|
|
203
|
+
h(\theta)$. It contains both discrepancy and noise.
|
|
204
|
+
|
|
205
|
+
### Discrepancy prediction
|
|
206
|
+
|
|
207
|
+
The distribution of $\delta$ at new frequencies $x_B$, conditioned on residuals
|
|
208
|
+
at the fit frequencies $x_A$, per event block:
|
|
209
|
+
$\mu = K_{BA}(K_{AA}+\Sigma_n)^{-1} r$ and
|
|
210
|
+
$\Sigma = K_{BB} - K_{BA}(K_{AA}+\Sigma_n)^{-1}K_{AB}$. It excludes noise: it is
|
|
211
|
+
the discrepancy, not a predicted observation.
|
|
212
|
+
|
|
213
|
+
*Avoid:* "posterior predictive" (that includes noise); "discrepancy posterior"
|
|
214
|
+
(ambiguous with a posterior over hyperparameters).
|
|
215
|
+
|
|
216
|
+
### Linearisation
|
|
217
|
+
|
|
218
|
+
A Gauss–Newton approximation of a fit at its MAP, with the discrepancy's
|
|
219
|
+
hyperparameters held fixed: the Jacobian $J = -\partial r / \partial \theta$ of the
|
|
220
|
+
residual with respect to the model's free parameters, and the Fisher matrix
|
|
221
|
+
$F = J^\top \Sigma_D^{-1} J$ with $\Sigma_D = K + \Sigma_n$ per event block. With
|
|
222
|
+
the prior precision $\Sigma_0^{-1}$ it gives the linearised posterior covariance
|
|
223
|
+
$\Sigma_\text{post} = (F + \Sigma_0^{-1})^{-1}$, over parameter values in one space
|
|
224
|
+
(declared by default). Fisher matrices of independent fits add.
|
|
225
|
+
|
|
226
|
+
### Joint prediction
|
|
227
|
+
|
|
228
|
+
The Gaussian over the free parameters and the discrepancy at new frequencies
|
|
229
|
+
together, from a linearisation: unlike a discrepancy prediction, it carries the
|
|
230
|
+
parameters' uncertainty into $\delta$ and the cross-covariance between them. It is
|
|
231
|
+
the form in which one fit's posterior becomes the next fit's joint prior.
|
|
232
|
+
|
|
233
|
+
### Port discrepancy
|
|
234
|
+
|
|
235
|
+
A discrepancy embedded at a component's ports, on its S-parameters rather than on
|
|
236
|
+
an observable: $\check S_{ii} = S_{ii} + \delta_{ii}$ for reflection and
|
|
237
|
+
$\check S_{ij} = S_{ij} e^{\delta_{ij}}$ for transmission. A circuit containing
|
|
238
|
+
the corrected component carries $\delta$ to any observable or quantity of
|
|
239
|
+
interest, so it transfers between fits that observe the component differently.
|
|
240
|
+
Transmission is split into a symmetric and an antisymmetric block,
|
|
241
|
+
$\delta_{ij} = \delta^s_{ij} \pm \delta^a_{ij}$; a reciprocal component has no
|
|
242
|
+
antisymmetric block. $\delta$ is defined at a reference impedance and is learnt
|
|
243
|
+
at that impedance.
|
|
244
|
+
|
|
245
|
+
When the component is observed directly, in an event space of the same form
|
|
246
|
+
(additive for reflection, logarithmic for transmission), the port discrepancy *is*
|
|
247
|
+
the event-space discrepancy, and is marginalised there: this is the **reference
|
|
248
|
+
fit**. A later fit with the component inside a larger circuit holds $\delta$ as
|
|
249
|
+
explicit parameters, under the reference fit's joint prediction as their prior:
|
|
250
|
+
this is a **transfer fit**.
|
|
251
|
+
|
|
252
|
+
*Avoid:* "embedded discrepancy" or "embedded model error" (in the literature
|
|
253
|
+
these embed the error in the parameters); "stage 1" and "stage 2" (say reference
|
|
254
|
+
fit and transfer fit).
|
|
255
|
+
|
|
256
|
+
### Internal discrepancy
|
|
257
|
+
|
|
258
|
+
A discrepancy on a quantity inside a model rather than on its ports: for a
|
|
259
|
+
uniform line, its characteristic impedance, attenuation and phase constant,
|
|
260
|
+
$\check Z_c = Z_c e^{z}$, $\check\alpha = \alpha e^{a}$, $\check\beta = \beta e^{b}$.
|
|
261
|
+
The correction is log-relative and per unit length, so it is independent of the
|
|
262
|
+
line's length. A port discrepancy carries the whole instance's error and does
|
|
263
|
+
not transfer to another length; an internal discrepancy does, provided the
|
|
264
|
+
line's $\gamma L$ scales with its length. Choose the internal quantity by what
|
|
265
|
+
stays the same between the instances it must transfer across.
|
|
266
|
+
|
|
267
|
+
$\alpha$ and $\beta$ are corrected separately rather than by one complex factor
|
|
268
|
+
on $\gamma$, which would mix phase into loss because $\beta \gg \alpha$.
|
|
269
|
+
|
|
270
|
+
It is learnt in a reference fit either from reference internal quantities, in
|
|
271
|
+
an event space of the same log form, or from port observables alone, and is
|
|
272
|
+
carried into transfer fits as a port discrepancy is.
|
|
273
|
+
|
|
274
|
+
*Avoid:* "internal hook" (no general method interception exists; each
|
|
275
|
+
internal discrepancy corrects one typed quantity).
|
|
276
|
+
|
|
173
277
|
## Records at the boundaries
|
|
174
278
|
|
|
175
279
|
These frozen records are the seams that keep `Param`s and `Module`s out of the
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: paramrf
|
|
3
|
-
Version: 0.36.
|
|
3
|
+
Version: 0.36.6
|
|
4
4
|
Summary: Parametric radio frequency modeling
|
|
5
5
|
Author-email: Gary Allen <gvcallen@gmail.com>
|
|
6
6
|
Project-URL: homepage, https://github.com/gvcallen/paramrf
|
|
7
7
|
Description-Content-Type: text/x-rst
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
License-File: NOTICE
|
|
10
|
-
Requires-Dist: parax>=0.11.
|
|
10
|
+
Requires-Dist: parax>=0.11.6
|
|
11
11
|
Requires-Dist: threadpoolctl
|
|
12
12
|
Requires-Dist: eqxpress
|
|
13
13
|
Requires-Dist: jax
|
|
@@ -124,6 +124,19 @@ It replaces `with_values`, `with_free`, `with_fixed`, `Module.map`,
|
|
|
124
124
|
- **Not an optimiser step.** In fitting, "updates" also means Optax gradient
|
|
125
125
|
steps; the docstring says `update` is neither.
|
|
126
126
|
|
|
127
|
+
- **Numerical trials can opt out of raising on invalid parameter values.**
|
|
128
|
+
`update(..., on_invalid='raise')` remains strict by default. Numerical value
|
|
129
|
+
updates may opt into `on_invalid='nan'`, which marks the entire updated
|
|
130
|
+
parameter leaf NaN when its candidate is outside the effective constraint,
|
|
131
|
+
lies on an excluded open edge, or contains a nonfinite value. This gives
|
|
132
|
+
line searches and other numerical objectives a non-raising way to reject a
|
|
133
|
+
trial while keeping the parameter pytree structure and the other requested
|
|
134
|
+
values intact. The policy applies only to numerical value updates; structural
|
|
135
|
+
replacements and fixed-state changes remain outside it. Only parameter
|
|
136
|
+
validity failures become NaN: independent model errors keep their existing
|
|
137
|
+
behavior. NaN trials require a floating or complex leaf and do not promote
|
|
138
|
+
integer leaves.
|
|
139
|
+
|
|
127
140
|
`prf.replace` stays as the plain `dataclasses.replace`: fields of one object,
|
|
128
141
|
unvalidated, able to break a type. Its docstring points to `update` for
|
|
129
142
|
anything name-based.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# ADR-0005: Priors are attached by name, and a joint prior keeps its parameters
|
|
2
2
|
|
|
3
|
-
Status: accepted (2026-09)
|
|
3
|
+
Status: accepted (2026-09); amended (2026-10) to allow array-valued parameters
|
|
4
|
+
under a joint prior, and to compute a constant whitening log-determinant once.
|
|
4
5
|
|
|
5
6
|
## Context
|
|
6
7
|
|
|
@@ -43,8 +44,8 @@ The distribution's event size decides which:
|
|
|
43
44
|
`prf.Random`. Its raw space becomes the new prior's whitening, as for
|
|
44
45
|
`prf.Random`, and the prior is truncated to the parameter's existing bounds so
|
|
45
46
|
the bounds still hold.
|
|
46
|
-
- **Event size equal to the
|
|
47
|
-
over them.
|
|
47
|
+
- **Event size equal to the total size of the selected parameters**: a **joint
|
|
48
|
+
prior** over them. For scalar parameters the total size is their number.
|
|
48
49
|
- Anything else raises.
|
|
49
50
|
|
|
50
51
|
### A joint prior keeps its parameters
|
|
@@ -63,6 +64,22 @@ transparent to the name resolver, as `Tied` is. So:
|
|
|
63
64
|
would count the earlier fit's priors twice, since its posterior already
|
|
64
65
|
includes them.
|
|
65
66
|
|
|
67
|
+
### Array-valued parameters
|
|
68
|
+
|
|
69
|
+
A parameter under a joint prior may be an array, such as a port discrepancy's
|
|
70
|
+
values on a frequency grid. The distribution's vector is the selected parameters'
|
|
71
|
+
values, each flattened in C order, concatenated in name order. A parameter's own
|
|
72
|
+
shape is its declared shape: leading batch axes of a batched model stay batch
|
|
73
|
+
axes. Its raw value under the joint prior is its slice of the whitened vector,
|
|
74
|
+
reshaped to its shape, so it keeps one name however many values it holds.
|
|
75
|
+
Bounds are checked element by element, and fixing or tying the parameter raises,
|
|
76
|
+
as for a scalar.
|
|
77
|
+
|
|
78
|
+
The driving case is a port discrepancy (`CONTEXT.md`), whose values number
|
|
79
|
+
about $6 N_f$ for a reciprocal two-port, a few thousand. One parameter per value
|
|
80
|
+
would give it thousands of names and makes attaching and compiling the prior
|
|
81
|
+
slow (7 s and 52 s at 6000 scalars).
|
|
82
|
+
|
|
66
83
|
### Space
|
|
67
84
|
|
|
68
85
|
`space` states the space the distribution is over: `'raw'`, `'declared'` or
|
|
@@ -109,6 +126,28 @@ whether a bound is the model's (validity, such as a positive width) or the
|
|
|
109
126
|
user's (a range, such as `prf.Bounded`), so the check treats every bound as
|
|
110
127
|
validity.
|
|
111
128
|
|
|
129
|
+
### Explicit unnormalised truncation for inference
|
|
130
|
+
|
|
131
|
+
Declared- and physical-space joint priors may opt into `prior(...,
|
|
132
|
+
truncate='unnormalised')` when their support leaves a selected parameter's
|
|
133
|
+
validity. The distribution keeps its supplied density at every interior
|
|
134
|
+
validity point, and the attached prior contributes `-inf` outside validity;
|
|
135
|
+
ParamRF does not estimate or apply a truncation normaliser. The wrapper stores
|
|
136
|
+
this choice as static `normalised=False` metadata, which survives resolution,
|
|
137
|
+
updates, enclosing trees and supported serialization. The default remains
|
|
138
|
+
`truncate='normalised'` and retains the support-inside-validity check. Scalar
|
|
139
|
+
events and raw-space joint priors do not support unnormalised truncation.
|
|
140
|
+
|
|
141
|
+
This opt-in is for MAP, scoring, differentiation and posterior covariance.
|
|
142
|
+
Keeping the declared Gaussian density unchanged in the interior preserves its
|
|
143
|
+
gradient and precision, which are needed when transferring a local Gaussian
|
|
144
|
+
fit into a later linearised inference problem. It is not a probability
|
|
145
|
+
normalised over the valid region and cannot be used for sampling or evidence:
|
|
146
|
+
every public sampling path rejects an active unnormalised joint prior before
|
|
147
|
+
calling the sampler, with the affected parameter names in the error. This
|
|
148
|
+
includes direct sampling, `fit_sample`, joint samplers, split samplers and
|
|
149
|
+
hypercube samplers.
|
|
150
|
+
|
|
112
151
|
### Hypercube samplers
|
|
113
152
|
|
|
114
153
|
A hypercube sampler maps the unit cube through a joint prior's block as
|
|
@@ -130,6 +169,14 @@ CDF.
|
|
|
130
169
|
- `prf.resolve` keeps a joint prior, since it is not a tie and does not change
|
|
131
170
|
what the parameters are. `prf.unwrap` drops it, as it drops every prior.
|
|
132
171
|
|
|
172
|
+
### A constant whitening log-determinant
|
|
173
|
+
|
|
174
|
+
Scoring in raw space adds the log-determinant of the whitening. When the
|
|
175
|
+
whitening's Jacobian is constant, as for a multivariate normal, that term is a
|
|
176
|
+
constant: it is computed once, when the prior is attached, and held by the joint
|
|
177
|
+
prior. Recomputing it as a dense Jacobian and its determinant on every call cost
|
|
178
|
+
15.7 s per evaluation at 6000 values.
|
|
179
|
+
|
|
133
180
|
## Rejected options
|
|
134
181
|
|
|
135
182
|
- **Polishing the collapsing `Probabilistic`** (keeping the names of the
|
|
@@ -148,6 +195,10 @@ CDF.
|
|
|
148
195
|
- **`Transformed.icdf` in distreqx.** It would not be an inverse CDF, and it would
|
|
149
196
|
put ParamRF's sampler logic in another repository.
|
|
150
197
|
|
|
198
|
+
- **A separate Gaussian-prior node for large arrays** (for a port discrepancy).
|
|
199
|
+
It would be a second way to attach a joint prior, which this ADR removed, and a
|
|
200
|
+
flow or Gaussian posterior over any array parameter needs the same thing.
|
|
201
|
+
|
|
151
202
|
## Consequences
|
|
152
203
|
|
|
153
204
|
- The old `Probabilistic` constructor (`target=`, `static=`, tuple targets) and
|
|
@@ -85,7 +85,9 @@ wrong for complex $Z_r$.
|
|
|
85
85
|
- **Box space** is a fourth space: the box a bounded minimiser searches. It is
|
|
86
86
|
built from a parameter's bounds, not its prior: the unit box when both bounds
|
|
87
87
|
are finite, declared space otherwise. A closed edge of the box is the bound
|
|
88
|
-
itself
|
|
88
|
+
itself. A finite open edge is inset by a dtype-aware relative distance based
|
|
89
|
+
on machine epsilon, the bound and the original start; infinite edges stay
|
|
90
|
+
infinite. The exact algorithm is recorded below.
|
|
89
91
|
- **Minimisers say whether they honour bounds**, through the minimiser
|
|
90
92
|
interface. `SolverView` hands box space to one that does and raw space to one
|
|
91
93
|
that does not. Nothing in `SolverView` knows about a specific backend.
|
|
@@ -95,6 +97,64 @@ wrong for complex $Z_r$.
|
|
|
95
97
|
is silent: it is the kind of difference engineers expect between optimisers.
|
|
96
98
|
- **Raw space is unchanged.** It stays whitened by the prior (ADR-0005).
|
|
97
99
|
|
|
100
|
+
### Open box edges preserve valid starts
|
|
101
|
+
|
|
102
|
+
For each finite open edge `b`, let `x0` be the original box-space start, `eps`
|
|
103
|
+
the dtype's machine epsilon and `tiny` its smallest positive normal value. The
|
|
104
|
+
inward distance is
|
|
105
|
+
|
|
106
|
+
`max(tiny, eps * max(abs(b), abs(x0 - b), tiny))`.
|
|
107
|
+
|
|
108
|
+
Add this distance at a lower edge and subtract it at an upper edge. If rounding
|
|
109
|
+
leaves the result on the excluded edge, move one representable value inward.
|
|
110
|
+
If the proposed inset would exclude an already valid interior start, use that
|
|
111
|
+
start as the search edge. A start exactly on an open edge is moved to the
|
|
112
|
+
resulting interior edge; construction still rejects a deliberately declared
|
|
113
|
+
invalid start. Keep infinite edges infinite. This preserves tiny positive
|
|
114
|
+
starts, avoids a fixed absolute inset and ensures `Positive` has a positive
|
|
115
|
+
normal-number search edge. Closed edges and raw-space closed-start nudging keep
|
|
116
|
+
their existing behavior.
|
|
117
|
+
|
|
118
|
+
### Trust-constr uses fixed affine search coordinates
|
|
119
|
+
|
|
120
|
+
When bounds are supplied to SciPy `trust-constr` (case-insensitively), pass
|
|
121
|
+
feasible `Bounds` and use fixed affine coordinates. For flattened original box
|
|
122
|
+
start `x0`, choose each scale `s` as `upper - lower` for two finite bounds,
|
|
123
|
+
`abs(x0 - lower)` for lower-only, `abs(upper - x0)` for upper-only, and
|
|
124
|
+
`abs(x0)` for unbounded coordinates. Replace a zero or nonfinite scale by 1.
|
|
125
|
+
SciPy starts at `z0 = 0`, sees bounds `(lower - x0) / s` and
|
|
126
|
+
`(upper - x0) / s`, and evaluates the original objective at `x = x0 + s * z`.
|
|
127
|
+
Apply the affine chain rule to supplied gradients and convert the returned
|
|
128
|
+
coordinates to box space before rebuilding parameters. Scales stay fixed for
|
|
129
|
+
the solve.
|
|
130
|
+
|
|
131
|
+
Metrics retain SciPy's actual internal coordinates. Add `box_origin=x0` and
|
|
132
|
+
`box_scale=s` so callers can recover box coordinates from `metrics.x`; do not
|
|
133
|
+
partially rewrite derivative or multiplier fields. Other methods and calls
|
|
134
|
+
without supplied bounds keep their existing representations and coordinates.
|
|
135
|
+
This is private solver scaling, not a new public value space, and `SolverView`
|
|
136
|
+
continues to expose box space.
|
|
137
|
+
|
|
138
|
+
### Nonfinite SciPy evaluations fail immediately
|
|
139
|
+
|
|
140
|
+
Before returning an objective value to SciPy, check the loss and each requested
|
|
141
|
+
gradient entry for finiteness; check a Hessian only when a callback is actually
|
|
142
|
+
passed. A nonfinite value raises `FloatingPointError` on that evaluation.
|
|
143
|
+
Include the method, one-based evaluation number, failing quantity and affected
|
|
144
|
+
free parameter names for a nonfinite gradient. A nonfinite loss may list the
|
|
145
|
+
available free names as context without attributing cause. Identify a
|
|
146
|
+
nonfinite attempted parameter vector separately. Diagnostics use the original
|
|
147
|
+
box or raw coordinates before private affine scaling, never the internal vector
|
|
148
|
+
as if it were box space. Direct low-level calls may identify positional
|
|
149
|
+
coordinates when names are unavailable.
|
|
150
|
+
|
|
151
|
+
Do not include parameter values, full model representations or distributions
|
|
152
|
+
in errors or logs. Synchronize deferred JAX results before checking. Public
|
|
153
|
+
minimize and Bayesian fit APIs propagate the exception rather than returning a
|
|
154
|
+
failed start point; close any progress bar on failure. Finite nonconvergence
|
|
155
|
+
still returns `success=False` with its existing warning, and unrelated user
|
|
156
|
+
exceptions retain their type and message.
|
|
157
|
+
|
|
98
158
|
## Rejected options
|
|
99
159
|
|
|
100
160
|
- **Keep Y from the MNA solver and detect ill-conditioning.** Wrong answers get
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Discrepancy Prediction
|
|
2
|
+
======================
|
|
3
|
+
|
|
4
|
+
A fit with a Gaussian-process discrepancy learns how the model differs from the data, not just the model parameters. That discrepancy can be predicted at frequencies the fit never saw, with its uncertainty. In this example we fit the S11 of a 10 m coaxial line with a GP discrepancy, then predict the discrepancy off the fit grid.
|
|
5
|
+
|
|
6
|
+
Fitting with a Discrepancy
|
|
7
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
8
|
+
|
|
9
|
+
The measured S11 is a coaxial line plus a slow ripple that the model cannot produce, and a little measurement noise. We fit the dielectric constant, with a :class:`~pmrf.discrepancy_models.GaussianProcess` to absorb the ripple. Its kernel's length scale is in the fit frequency's unit, here MHz:
|
|
10
|
+
|
|
11
|
+
.. plot::
|
|
12
|
+
:context: reset
|
|
13
|
+
:include-source:
|
|
14
|
+
:nofigs:
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
import pmrf as prf
|
|
18
|
+
from pmrf.models import CoaxialLine
|
|
19
|
+
from pmrf.materials import BulkConductor, ConstantDielectric
|
|
20
|
+
from pmrf.fitting import fit
|
|
21
|
+
from pmrf.likelihoods import GaussianLikelihood
|
|
22
|
+
from pmrf.discrepancy_models import GaussianProcess
|
|
23
|
+
from pmrf.covariance_kernels import Matern52Kernel
|
|
24
|
+
|
|
25
|
+
def coax(ep_r):
|
|
26
|
+
return CoaxialLine(
|
|
27
|
+
d_in=1.05e-3, d_out=3.2e-3,
|
|
28
|
+
dielectric=ConstantDielectric(ep_r=ep_r, tand=1e-3),
|
|
29
|
+
conductor=BulkConductor(sigma=1 / 1.7e-8),
|
|
30
|
+
length=10.0,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
freq = prf.Frequency(10, 500, 100, 'MHz')
|
|
34
|
+
ripple = 0.01 * np.exp(2j * np.pi * freq.f_scaled / 150.0)
|
|
35
|
+
rng = np.random.default_rng(0)
|
|
36
|
+
noise = 1e-3 * (rng.normal(size=freq.npoints) + 1j * rng.normal(size=freq.npoints))
|
|
37
|
+
s11 = np.asarray(coax(1.40).s(freq)[:, 0, 0]) + ripple + noise
|
|
38
|
+
|
|
39
|
+
gp = GaussianProcess(
|
|
40
|
+
Matern52Kernel(prf.Bounded(10.0, 200.0, value=50.0)) * prf.Bounded(1e-5, 1e-3, value=1e-4)
|
|
41
|
+
)
|
|
42
|
+
result = fit(
|
|
43
|
+
coax(prf.Bounded(1.38, 1.42, value=1.39)), s11, frequency=freq, features='s11',
|
|
44
|
+
likelihood=GaussianLikelihood(prf.Bounded(1e-7, 1e-4, value=1e-6)),
|
|
45
|
+
discrepancy=gp,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
Predicting the Discrepancy
|
|
49
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
50
|
+
|
|
51
|
+
The fitted :class:`~pmrf.evaluators.MarginalLogLikelihood`, with its optimized GP hyperparameters and noise, is the one term of the fit's objective. :meth:`~pmrf.evaluators.MarginalLogLikelihood.predict_discrepancy` conditions the GP on the fit's residuals and returns the distribution of the discrepancy at new frequencies. Here they extend past the fit band and are given in GHz; they are converted to the fit's unit first.
|
|
52
|
+
|
|
53
|
+
.. plot::
|
|
54
|
+
:context:
|
|
55
|
+
:include-source:
|
|
56
|
+
|
|
57
|
+
import matplotlib.pyplot as plt
|
|
58
|
+
|
|
59
|
+
(term,) = result.solution.objective
|
|
60
|
+
mll = term.evaluator.evaluator
|
|
61
|
+
|
|
62
|
+
new_freq = prf.Frequency(0.005, 0.6, 300, 'GHz')
|
|
63
|
+
delta = mll.predict_discrepancy(result.model, freq, new_freq)
|
|
64
|
+
|
|
65
|
+
mean = delta.mean()
|
|
66
|
+
std = np.sqrt(np.diagonal(delta.covariance(), axis1=-2, axis2=-1))
|
|
67
|
+
|
|
68
|
+
fig, axes = plt.subplots(2, 1, sharex=True)
|
|
69
|
+
for ax, m, s, r, part in zip(axes, mean, std, (ripple.real, ripple.imag), ('Re', 'Im')):
|
|
70
|
+
ax.fill_between(new_freq.f_scaled * 1e3, m - s, m + s, alpha=0.3, label=r'$\pm 1\sigma$')
|
|
71
|
+
ax.plot(new_freq.f_scaled * 1e3, m, label='predicted mean')
|
|
72
|
+
ax.plot(freq.f_scaled, r, 'k.', markersize=3, label='true ripple')
|
|
73
|
+
ax.set_ylabel(rf'{part} $\delta$')
|
|
74
|
+
axes[0].legend()
|
|
75
|
+
axes[1].set_xlabel('Frequency (MHz)')
|
|
76
|
+
|
|
77
|
+
The prediction is in event space: one block for the real part of S11 and one for the imaginary part, with frequency last. It is of the discrepancy alone, and excludes measurement noise. Inside the fit band it follows the ripple closely; beyond it, the mean relaxes towards zero and the uncertainty grows back to the GP's prior.
|
|
@@ -9,6 +9,8 @@ This chapter includes some basic examples to demonstrate ParamRF's core features
|
|
|
9
9
|
cascading_and_terminating
|
|
10
10
|
circuit_models
|
|
11
11
|
model_optimization
|
|
12
|
+
discrepancy_prediction
|
|
13
|
+
port_discrepancy
|
|
12
14
|
derivatives_and_sweeps
|
|
13
15
|
parameter_naming_and_model_manipulation
|
|
14
16
|
custom_models
|