Skip to main content

DualPerspective Python Package

Python interface for DualPerspective.jl, a Julia package for solving Kullback-Leibler regularized least squares problems.

Seeing juliacall.JuliaError: UndefVarError: reset! not defined? This affects every Julia release up to v0.1.4 and is fixed in v0.1.5. See UPGRADING.md for a workaround that needs no upgrade, and for upgrade instructions.

Installation

pip install DualPerspective

Julia itself is installed automatically on first use, via juliacall.

Versioning

The PyPI package and the Julia package version independently. Each wheel pins one exact Julia release in juliapkg.json and is tested against it, so PyPI 0.2.0 shipping DualPerspective.jl 0.1.5 is expected, not a mismatch.

import DualPerspective
DualPerspective.__version__   # the Python package
DualPerspective.version()     # the Julia package it pins

Basic usage

import numpy as np
from DualPerspective import DPModel, solve

np.random.seed(42)
n, m = 200, 100                     # solution dimension, number of measurements
x0 = np.pi * (tmp := np.random.rand(n)) / np.sum(tmp)
A = np.random.rand(m, n)
b = A @ x0                          # measurements

model = DPModel(A, b, lam=1e-4)
x = solve(model)

print(f"sum of solution: {x.sum():.6f} (should be about {np.pi:.6f})")

solve returns a NumPy array. Pass full_output=True for the full result:

result = solve(model, full_output=True)
result.x            # primal solution
result.status       # 'optimal', 'max_iter', ...
result.iterations
result.optimality   # final ‖∇d(y)‖, the quantity the stopping rule tests
result.residual
result.trace        # per-iteration history (a list of dicts), when the solver records one
result.to_pandas()  # the trace as a DataFrame, if pandas is installed

The model

DPModel(A, b, q=None, C=None, c=None, lam=None)

Minimizes (1/2λ)‖Ax - b‖²_{C⁻¹} + ⟨c, x⟩ + KL(x ‖ q).

Argument Shape Meaning
A (m, n) Forward operator
b (m,) Measurements
q (n,) Prior; defaults to uniform
C (m, m) Covariance weighting the residual; defaults to the identity
c (n,) Linear cost
lam scalar Regularization parameter (also accepted as λ)

C weights the residual b - Ax, so it is (m, m). Releases before 0.2.0 documented it incorrectly as (n, n).

Integer and single-precision arrays are accepted and converted to double precision. All arrays are copied into Julia, so mutating them afterwards does not change the model.

lam and scale are settable properties:

model.lam = 1e-4      # same as regularize(model, 1e-4)
model.scale = 2.0     # same as scale(model, 2.0)

Choosing a solver

solve(model, method="sequential", atol=1e-6, rtol=1e-6, logging=0, full_output=False)
method Algorithm
"sequential" Sequential scaling (default)
"trust-region" Trust-region Newton-CG
"level-set" Level-set method
"adaptive-level-set" Adaptive level-set method
"self-scaled" Self-scaled Gauss-Newton, for unknown total mass

The solver stops when ‖∇d(y)‖ < atol + rtol*‖b‖. Unrecognized keywords are passed straight through to the Julia solver.

Diagnosing problems

python -m DualPerspective.doctor

Prints the Python, Julia and resolved Julia package versions, the relevant environment variables, and runs a small solve. Include its output in any bug report.

Julia errors surface as DualPerspectiveError, whose message is the first line of the Julia exception; the full Julia backtrace is on .julia_traceback, and the original exception is chained as __cause__.

Running on a cluster

  • Put the Julia depot on fast local storage. Precompilation is very sensitive to filesystem latency, and ~/.julia on NFS is usually slow and quota-limited:
    export JULIA_DEPOT_PATH=/local/scratch/$USER/julia_depot
    
  • Resolve before going offline. Import the package once on a login node with the same JULIA_DEPOT_PATH before submitting jobs to nodes without network access.
  • Shared environments. PYTHON_JULIACALL_PROJECT points juliacall at an existing Julia project, which must already have a matching PythonCall.jl. Do not mutate an admin-managed project.
  • Threads and signals. PYTHON_JULIACALL_HANDLE_SIGNALS=yes avoids segfaults from Julia's garbage collector in multi-threaded programs, but interferes with Python's own signal handling (including Ctrl-C). It is not set by default; enable it only if you need it.

Local development

To run against a checkout of DualPerspective.jl rather than the pinned release:

export DUALPERSPECTIVE_JL_PATH=/path/to/DualPerspective.jl

Building and publishing

Remove stale artefacts first — twine upload dist/* will otherwise try to re-upload every old build sitting in dist/:

cd pypi
rm -rf build dist *.egg-info
python -m build
unzip -l dist/*.whl | grep juliapkg.json    # the pin must be in the wheel
twine check dist/*

Publish only after the pinned Julia version has been registered in the General registry; otherwise the wheel pins a version that cannot be resolved.

License

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dualperspective-0.2.0.tar.gz (18.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dualperspective-0.2.0-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

Details for the file dualperspective-0.2.0.tar.gz.

File metadata

  • Download URL: dualperspective-0.2.0.tar.gz
  • Upload date:
  • Size: 18.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dualperspective-0.2.0.tar.gz
Algorithm Hash digest
SHA256 32908092489abdaa53e57516846e4aca0f2833fc4e2fb1bc89e5e074ef47b03c
MD5 3fe2f697be3b1f8cf7d7d5d17376e02e
BLAKE2b-256 120e6f392774e7c9ead8dac24df3ebd3513c62e51f2076c56a941e1f0f256739

See more details on using hashes here.

Provenance

The following attestation bundles were made for dualperspective-0.2.0.tar.gz:

Publisher: python-publish.yml on MPF-Optimization-Laboratory/DualPerspective.jl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dualperspective-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for dualperspective-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a889b2f8056029b9b01173c7cd41cfd6b21d4f3a0fc764b3a7a1827ad74a711c
MD5 e0005edd436c189a4aa0a1409282ed3c
BLAKE2b-256 d3adb86c2010db7315b6ed1cbb0df3fdb3ba64a774cc189d819675b9ee011f61

See more details on using hashes here.

Provenance

The following attestation bundles were made for dualperspective-0.2.0-py3-none-any.whl:

Publisher: python-publish.yml on MPF-Optimization-Laboratory/DualPerspective.jl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.2

2 files

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page