msolveio
Strict Python I/O for msolve: canonical input, mode-required output.
Gröbner mode (-g) and characteristic-0 rational-parametrization mode (-P).
Bytes from any other msolve mode are rejected, not interpreted.
msolveio writes .ms files that msolve 0.10.x will parse the way you meant, and reads back
only the one output language it can identify with certainty. It is not a CAS and not a
Gröbner engine.
Install
pip install msolveio
You also need a system msolve 0.10.x binary on PATH (or pass binary=). msolveio has no
runtime dependencies.
Usage
from msolveio import emit_system, parse_groebner, run_groebner, MsolveAmbiguous
source = emit_system(
["x^2+y", "x*y-1"],
variables=["x", "y"],
characteristic=0,
)
result = run_groebner(source, gb=2, timeout=60)
print(result.output.unit_ideal) # False
print(result.output.basis) # ('y^2+x', 'x*y-1', 'x^2+y')
print(result.msolve_version) # '0.10.1'
emit_system raises MsolveInputError rather than rewriting input: parentheses,
post-monomial division (x/2), repeated monomials, unknown identifiers, and coefficients
that would overflow msolve's 64-bit read are all refused. Leading rationals (1/2*x) are
allowed over Q only.
parse_groebner requires msolve's # comment header. That header is the only thing in the
bytes that says which mode produced them, so it is load-bearing. Feeding it solver output
raises MsolveAmbiguous instead of returning a basis:
parse_groebner("[-1]:") # MsolveAmbiguous
This matters because the two languages invert each other. In solver mode [-1]: means no
solutions; in Gröbner mode the unit ideal — the same fact — prints as [1]:. A parser that
guesses gets the answer exactly backwards.
Rational parametrization (-P)
run_param runs msolve -P 2 and parses the rational univariate representation exactly.
Every returned coefficient is a Python integer; nothing is a float, and nothing is eval'd.
The result is one of three types — match on it, none is ever a silent empty list:
from fractions import Fraction
from msolveio import emit_system, run_param
from msolveio import RationalParametrization, EmptySolutionSet, PositiveDimensional
source = emit_system(["2*x-1", "3*y-1"], variables=["x", "y"], characteristic=0)
result = run_param(source, timeout=60)
assert isinstance(result.output, RationalParametrization)
result.output.w_ascending # (-1, 3) w(t) = 3t - 1, ascending, content kept
result.output.wprime_ascending # (3,) the denominator; checked to equal w'(t)
result.output.numerators_printed # (ParamNumerator(v_ascending=(-3,), denominator_scale=2),)
result.chart.point_at(Fraction(1, 3)) # (Fraction(1, 2), Fraction(1, 3))
Read that worked example closely, because the conventions are load-bearing. The parameter
t is the last printed variable (here y, so t = 1/3 at the point). Every earlier
printed variable is recovered as
variable = -v(t) / (denominator_scale * w'(t))
so x = -(-3) / (2 * 3) = 1/2. The leading minus sign, the integer scale, the ascending
coefficient order, and the kept integer content of w are all msolve's printed conventions,
pinned as named dataclass fields and verified by the parser; a misread scale or sign would
yield wrong witness points that still pass casual arithmetic, which is exactly the class of
silent inversion this library exists to refuse.
msolve fixes non-generic systems silently: it may permute your variables, and may append
an auxiliary variable tied to a linear form (always printed as A, even when that collides
with one of yours). result.chart resolves all of that back onto your input chart —
printed_index, added_variable, linear_form_input (t = -(c_1*x_1 + ...)), and one
numerator per input variable under the uniform convention above. Consume the chart, not
the printed order.
[-1]: parses to EmptySolutionSet and [1, nvars, -1, []]: to PositiveDimensional —
typed results, not errors and not lists. Gröbner-shaped or solver-shaped bytes raise
MsolveAmbiguous. A parametrization over a prime field raises
MsolveCharPParamUnsupported: msolve's characteristic-p -P grammar differs, and
half-parsing it with characteristic-0 conventions is the footgun, not the feature.
Passing precision=<bits> switches to msolve -P 1 -p <bits> and additionally returns
real-root isolation boxes as exact Fraction pairs (msolve prints dyadic rationals, not
floats), un-permuted to input order on the chart. Note that msolve parametrizes the
radical: quotient_degree may exceed deg w, and multiplicity is not recoverable here.
ParamResult carries the same custody fields as RunResult: msolve_version, argv,
wall_seconds, returncode, stderr, input_sha256, output_sha256.
Not supported in v0.2
- Solver mode (real-root isolation without
-P) — raises, and is never interpreted as a basis or a parametrization. - Parametrizations over prime fields — a typed raise, see above.
- JSON output, Macaulay2 format, or any other msolve serialization.
- sympy / flint / numpy interop. Gröbner basis elements are strings exactly as msolve printed them; parametrization coefficients are plain Python integers. One canonical representation, zero dependencies; convert downstream where your algebra lives.
A note on characteristic
msolve 0.10.1 labels some unlifted rational Gröbner bases as characteristic 0 regardless of
whether a lift to Q actually happened. GroebnerOutput.characteristic reports what msolve
printed and nothing more; msolveio does not pretend to know better.
License
MIT © 2026 DC Posch — https://github.com/dcposch/msolveio
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file msolveio-0.2.1.tar.gz.
File metadata
- Download URL: msolveio-0.2.1.tar.gz
- Upload date:
- Size: 35.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6fe3957bae69a0d819faf8f0aec93fa84f44fa8dfc4b43033e3430d42ee52ee9
|
|
| MD5 |
0bf0b9a129cb258316ff8948475cfbe1
|
|
| BLAKE2b-256 |
2cfc9db9841842b6b12b32613ed4c3a71e84f1241688d5d1837f4eec3ddbbd84
|
Provenance
The following attestation bundles were made for msolveio-0.2.1.tar.gz:
Publisher:
publish.yml on dcposch/msolveio
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
msolveio-0.2.1.tar.gz -
Subject digest:
6fe3957bae69a0d819faf8f0aec93fa84f44fa8dfc4b43033e3430d42ee52ee9 - Sigstore transparency entry: 2684281270
- Sigstore integration time:
-
Permalink:
dcposch/msolveio@8a56f52fc0f33b2d4b501cb1590546271299d452 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/dcposch
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8a56f52fc0f33b2d4b501cb1590546271299d452 -
Trigger Event:
release
-
Statement type:
File details
Details for the file msolveio-0.2.1-py3-none-any.whl.
File metadata
- Download URL: msolveio-0.2.1-py3-none-any.whl
- Upload date:
- Size: 27.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0e96ccdaca4fc16c1039b303d28ca2357705137b367a73b5abda62c6a865441
|
|
| MD5 |
90591e8f6f39a67a275a87688f9940ad
|
|
| BLAKE2b-256 |
7798239342ae73b01440e6f4ed34a8d5e7c5557c2b0fb6869c8faeeab74e17c2
|
Provenance
The following attestation bundles were made for msolveio-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on dcposch/msolveio
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
msolveio-0.2.1-py3-none-any.whl -
Subject digest:
b0e96ccdaca4fc16c1039b303d28ca2357705137b367a73b5abda62c6a865441 - Sigstore transparency entry: 2684281293
- Sigstore integration time:
-
Permalink:
dcposch/msolveio@8a56f52fc0f33b2d4b501cb1590546271299d452 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/dcposch
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8a56f52fc0f33b2d4b501cb1590546271299d452 -
Trigger Event:
release
-
Statement type: