mhostetter / galois

A performant NumPy extension for Galois fields and their applications
https://mhostetter.github.io/galois/
MIT License
335 stars 31 forks source link

Linear system solver for GF2 #541

Closed Scurrra closed 5 months ago

Scurrra commented 8 months ago

I needed a solver for linear systems over GF2 for simple codes decoding, but the library only has a solver that just inverts the coefficient matrix A requiring matrix A be square. I found this solution in Julia and translated it. The solve function can be invoked using np.linalg.solve (i.e. galois.GF2._solve) and using galois.GF2._solve. As I modified the old function calling style I would say that it works (build succeeded), and it works well in may project.

codecov[bot] commented 8 months ago

Codecov Report

Attention: Patch coverage is 52.94118% with 24 lines in your changes are missing coverage. Please review.

Project coverage is 96.07%. Comparing base (25baec4) to head (cd1fc57).

:exclamation: Current head cd1fc57 differs from pull request most recent head 288aff8. Consider uploading reports for the commit 288aff8 to get more accurate results

Files Patch % Lines
src/galois/_fields/_gf2.py 52.94% 24 Missing :warning:
Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #541 +/- ## ========================================== - Coverage 96.44% 96.07% -0.38% ========================================== Files 46 46 Lines 5911 5962 +51 ========================================== + Hits 5701 5728 +27 - Misses 210 234 +24 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

mhostetter commented 8 months ago

Thanks for the pull request.

I needed a solver for linear systems over GF2 for simple codes decoding, but the library only has a solver that just inverts the coefficient matrix A requiring matrix A be square.

Are you trying to solve a over-determined system? Are there "bit errors" involved? Or are all equations consistent?

The solve function can be invoked using np.linalg.solve (i.e. galois.GF2._solve) and using galois.GF2._solve.

I don't like overloading np.linalg.solve(), since that should only operate on square matrices. np.linalg.lstsq(), however, is intended for over-determined systems. Perhaps this should hook into there.

Scurrra commented 8 months ago

Are you trying to solve a over-determined system?

Yes. I am decoding code words back into informational messages (I don't know proper terms in English, sorry).

I changed solve to lstsq for overloading, but saved galois.GF2.solve. Anyway, there is no such solver for other fields in the library.

I also want to add Galois rings (issue #280) to the library in another pr. I have already implemented it in Julia (SimplePolynomialRing.jl).

mhostetter commented 8 months ago

I changed solve to lstsq for overloading, but saved galois.GF2.solve. Anyway, there is no such solver for other fields in the library.

Which algorithm is implemented here? It's likely the algorithm should work in other fields. If so, I'd like to implement it so it can work in any field.

I also want to add Galois rings (issue https://github.com/mhostetter/galois/issues/280) to the library in another pr. I have already implemented it in Julia (SimplePolynomialRing.jl).

Cool. But please work with me before starting work. There is significant architecture implications.

Scurrra commented 8 months ago

Which algorithm is implemented here? It's likely the algorithm should work in other fields. If so, I'd like to implement it so it can work in any field.

To be honest, I don't know the name of the algorithm (I contacted the author of that library and it's name were not mentioned). It seems that the algorithm is optimized for GF2.

Cool. But please work with me before starting work. There is significant architecture implications.

I figured it out, and definitely liked it. How can I contact you to get instructions?

dimbleby commented 7 months ago

this feels like quite a lot of ceremony, for what is essentially just:

    puzzle = np.c_[A, b]
    reduced = puzzle.row_reduce()
    solution = reduced[:, -1]
mhostetter commented 5 months ago

@Scurrra I tend to agree with @dimbleby. I believe this is simply achieved using row reduction via Gaussian elimination, as he pointed out. I don't think there is a clean place to put this in the API. I'm closing for now. If you have other ideas of how to incorporate, feel free to reach out.