Fix remaining CI failures: downstream MATLAB ordering & SymPy PyCall setup#1880
Merged
ChrisRackauckas merged 3 commits intoMay 30, 2026
Conversation
The ParameterizedFunctions MATLABDiffEq regression test compared the generated MATLAB string byte-for-byte. The order of operands within a commutative `*` follows SymbolicUtils' argument sort, which is benign but version-dependent: the expected string has `u(1) * u(2)` while current stable Julia (1.12) emits `u(2) * u(1)`, so the test fails on master CI. Compare the two RHS rows modulo commutative `+`/`*` operand ordering (the test already looks up parameter indices to stay stable across parameter reorderings; this extends the same robustness to factor ordering). Mirrors the build_targets tests. Verified test/downstream/ParameterizedFunctions_MATLAB.jl passes 2/2 on Julia 1.12. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The SymPy test group failed on CI with `ModuleNotFoundError: No module named
'sympy'`: PyCall defaulted to the runner's system Python (/usr/bin/python3),
which has no sympy, so SymbolicsSymPyExt failed to precompile.
sympy.jl already set `ENV["PYTHON"] = ""` + `Pkg.build("PyCall")` to switch to
the Conda.jl Python (where SymPy's `pyimport_conda` would install sympy), but it
ran too late — after `Pkg.instantiate()` had already precompiled the extension
against the system Python, and PyCall's Python config is fixed at load time.
Set `ENV["PYTHON"] = ""` before instantiation in `activate_sympy_env` (CI only)
so PyCall builds against the Conda Python from the start and the extension
precompiles successfully.
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1880 +/- ##
==========================================
- Coverage 26.12% 24.87% -1.25%
==========================================
Files 56 57 +1
Lines 5356 5589 +233
==========================================
- Hits 1399 1390 -9
- Misses 3957 4199 +242 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…solve When SymPy cannot find a closed-form antiderivative it returns an unevaluated `Integral(...)`. In `integrating_factor_solve` this comes back through `sympy_integrate` as a symbolic *operation* (function application), but the guard tested `get_variables(solution, variable(:Integral))`, which only matches a *variable* named `Integral` and so never fired. The unevaluated integral was then mangled by `sympy_simplify` into a wrong closed form. Concretely, `symbolic_solve_ode(Dt(x) + sqrt(t)*x ~ sin(4t)*x^3, x, t)` (a Bernoulli equation whose linearization needs the non-elementary ∫ sin(4t) exp(-(4/3) t^(3/2)) dt) returned `1 / sqrt(-2sin(4t) + C₁*exp((4//3)*t^(3//2)))`, which does not satisfy the ODE, instead of `nothing`. Detect the unevaluated integral on the printed form of the solution and bail out, so such ODEs correctly report no closed-form solution. This was previously masked on CI because the SymPy extension failed to precompile (see the PyCall Conda fix); test/sympy.jl line 97 now passes for the right reason. Verified test/sympy.jl passes locally (16 passed, 1 broken, 0 failed) on Julia 1.12 with sympy 1.14.0. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6dc4804
into
JuliaSymbolics:master
21 of 24 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the remaining failing CI jobs on
master(other than theCorereference tests handled in #1878).1.
test (Downstream, 1)— MATLAB target regression testtest/downstream/ParameterizedFunctions_MATLAB.jlcompared the generated MATLAB string byte-for-byte. The order of operands within a commutative*follows SymbolicUtils' argument sort, which is benign but version-dependent: the expected string hasu(1) * u(2)while current stable Julia (1.12) emitsu(2) * u(1). (The test already looked up parameter indices to stay stable across parameter reorderings — this extends the same robustness to factor ordering.)Fix: compare the two RHS rows modulo commutative
+/*operand ordering (mirrors the build_targets tests from #1878).Verified: passes locally 2/2 on Julia 1.12, and the
DownstreamCI job is green on this PR.2.
test (SymPy, 1)— PyCall/sympy precompilationThe SymPy group failed with
ModuleNotFoundError: No module named 'sympy'. PyCall defaulted to the runner's system Python (/usr/bin/python3), which has no sympy, soSymbolicsSymPyExtfailed to precompile.sympy.jlalready triedENV["PYTHON"]=""+Pkg.build("PyCall")to switch to the Conda.jl Python, but it ran afterPkg.instantiate()had already precompiled the extension against the system Python — too late, since PyCall's Python is fixed at load time.Fix: set
ENV["PYTHON"]=""before instantiation inactivate_sympy_env(CI only), so PyCall builds against the Conda Python and SymPy'spyimport_condainstalls sympy. CI logs confirm this now works (Installing sympy via the Conda sympy package... sympy-1.14.0, extension precompiles).3. SymPy solver bug uncovered by fix #2 (
sympy.jl:97)Fixing the precompilation exposed a latent correctness bug that had been masked by the precompile failure.
integrating_factor_solveguarded against SymPy returning an unevaluatedIntegral(...)withget_variables(solution, variable(:Integral))— but the unevaluated integral comes back as an operation, not a variable, so the guard never fired andsympy_simplifymangled it into a wrong closed form.Concretely
symbolic_solve_ode(Dt(x) + sqrt(t)*x ~ sin(4t)*x^3, x, t)returned1/sqrt(-2sin(4t) + C₁*exp((4//3)*t^(3//2)))(which does not satisfy the ODE — I verified the residual is non-zero) instead ofnothing.Fix: detect the unevaluated integral on the printed form of the solution and return
nothing, so such ODEs correctly report no closed-form solution.Verified:
test/sympy.jlpasses locally 16 passed / 1 broken (pre-existing) / 0 failed on Julia 1.12 with sympy 1.14.0, against a dev build of this branch (the solvable Bernoulli cases still solve correctly — no regression).Not addressed here
benchmark: this job's benchmarks run fine; only the final PR-comment step fails with403 Resource not accessible by integration, becauseGITHUB_TOKENis read-only for fork PRs (a GitHub security restriction, independent of thepermissions:block). It does not run onmasterand is not a code/test failure, so I left the workflow unchanged rather than risk masking real benchmark regressions. It will show red on this PR for the same fork-token reason.Please ignore until reviewed by @ChrisRackauckas.
🤖 Generated with Claude Code