fix(ga): change default dual mode to Iinv+ for correct B*dual(B)=I#544
fix(ga): change default dual mode to Iinv+ for correct B*dual(B)=I#544utiberious wants to merge 4 commits intopygae:masterfrom
Conversation
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
|
Thanks for digging into this. The convention ( A few things to address before this could be considered for merge:
That said, this is a global default change and a breaking change for any user calling |
|
Good catches, addressed in 2025e17:
|
|
Thanks, CI is green. I'll leave this PR open for demonstrating the change of default dual mode. Also I'm considering to default to this new dual mode for Kingdon compatible interface in #524 . |
utensil
left a comment
There was a problem hiding this comment.
Thanks for fixing this — the math is correct. 'Iinv+' (dual(A) = A·I⁻¹) is the standard Hodge dual per Doran & Lasenby, and issue #514 confirms the bug: with the old 'I+' default, B * B.dual() gives -I instead of I for a unit bivector.
That said, this is a breaking change in default behavior for any code that calls dual() without explicitly setting Ga.dual_mode(), so a few things are needed before this can merge:
1. Docs need updating
doc/module-components.rst still describes the old default in two places:
- Line 342: method signature shows
GA.dual_mode(mode='I+') - Line 359: prose says "default for the dual mode is
mode='I+'"
Both should be updated to 'Iinv+'.
2. Changelog entry missing
Please add an entry to doc/changelog.rst (following the existing :bug: format) noting the breaking change and migration path, e.g.:
:bug:`514` The default dual mode has changed from `'I+'` to `'Iinv+'` so that
`B * B.dual() == I` holds for unit blades, matching the standard definition
(Doran & Lasenby). To preserve the old behavior, call `Ga.dual_mode('I+')`
at the start of your program.
3. Minor cleanup (optional)
galgebra/primer.py:34 has an explicit Ga.dual_mode('Iinv+') call that was a workaround for this exact bug. With the default fixed it becomes a no-op — worth removing or updating the comment to reflect that it's now just confirming the default.
Note: primer.py already used 'Iinv+' explicitly, which shows this is the right direction. Happy to revisit once the docs and changelog are in place.
utensil
left a comment
There was a problem hiding this comment.
All three requested items are now addressed:
- ✅
doc/module-components.rst— both the method signature (line 342) and the prose (line 359) updated to'Iinv+'; prose now correctly saysA*I^{-1}is returned - ✅
doc/changelog.rst— entry added with the:bug:514`` format and migration note - ✅
galgebra/primer.py— explicitGa.dual_mode('Iinv+')call kept, comment updated to "Confirms the default" rather than "workaround" framing
The PR is technically complete. Holding off on merge for now — this is a breaking change in default behavior and needs deliberate inclusion into a release rather than a quiet merge. Tracking here for when the time is right.
The default dual_mode was 'I+' which computes self*I. The conventional
Hodge dual in geometric algebra is self*I^{-1}. Changed the default to
'Iinv+' so that for any blade B, B * B.dual() == I holds, matching
standard textbook definitions (Doran & Lasenby, Macdonald).
Fixes #2
The dual fix (issue pygae#514) changes sign conventions in the dual operation, which propagates through the Smith Sphere calculations. Update saved outputs to reflect the corrected results.
- Correct test_dual_correctness docstring: B*dual(B)=I holds for unit bivectors, not all blades - Remove negation in down()/up() functions: with Iinv+ mode, N.dual() already gives the correct outward normal
- doc/module-components.rst: update method signature and prose to show Iinv+ as default - doc/changelog.rst: add bug#514 entry noting the breaking change and migration path - galgebra/primer.py: update comment to reflect Iinv+ is now the default, not a workaround
0fb90e8 to
c147809
Compare
Summary
Changes the default
dual_modefrom'I+'to'Iinv+'so thatB * B.dual() == Iholds, which is the conventional definition of the dual in geometric algebra.With
'I+',dual(B) = B * I, which does not satisfy this identity in general. The correct definition isdual(B) = B * I_inv.Fixes #514
Changes
galgebra/ga.py: Changedual_mode_valuedefault from'I+'to'Iinv+'test/test_test.py: Update existing dual mode test, addtest_dual_correctnessverifyingB * B.dual() == Iexamples/ipython/Smith Sphere.ipynb: Update notebook outputs to match corrected dualTest plan