Skip to content

Commit

Permalink
switch to PythonCall
Browse files Browse the repository at this point in the history
  • Loading branch information
Krastanov committed Mar 15, 2024
1 parent fc7511f commit e92a858
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 66 deletions.
6 changes: 6 additions & 0 deletions CondaPkg.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

[pip.deps]
pymatching = ""
ldpc = ""
numpy = ""
scipy = ""
8 changes: 3 additions & 5 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
name = "PyQDecoders"
uuid = "17f5de1a-9b79-4409-a58d-4d45812840f7"
authors = ["Stefan Krastanov <[email protected]>"]
version = "0.1.1"
version = "0.2.0"

[deps]
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"

[compat]
Conda = "1.10"
PyCall = "1.96"
PythonCall = "0.9.16"
julia = "1.9"
58 changes: 19 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
A Julia meta-package for accessing the python libraries `pymatching` (for MWPM-like decoders) and `ldpc` (for BP-like decoders).

# How to install

If you plan to use a python environment you are managing yourself, just make sure that julia is started from that environment and run

`] add https://github.com/QuantumSavory/PyQDecoders.jl#master`

You might get error messages telling you that you need to install some python packages in that environment of yours.

If you want julia to automatically take care of creating a hidden python environment that it manages itself, do `ENV["PYTHON"] = ""` before you install `PyQDecoders.jl`

# How to use

## `pymatching`
Expand All @@ -20,7 +10,7 @@ The python pymatching module is immediately available:
julia> using PyQDecoders
julia> PyQDecoders.pm
PyObject <module 'pymatching' from ...>
Python: <module 'pymatching' from ...>
```

Running the example from `pymatching`'s original Readme:
Expand All @@ -33,7 +23,8 @@ julia> H = sps.csc_matrix(
0 1 1 0 0;
0 0 1 1 0;
0 0 0 1 1])
PyObject <4x5 sparse matrix of type '<class 'numpy.int64'>'
Python:
<4x5 sparse matrix of type '<class 'numpy.int64'>'
with 8 stored elements in Compressed Sparse Column format>
julia> weights = [4, 3, 2, 3, 4]
Expand All @@ -45,28 +36,18 @@ julia> weights = [4, 3, 2, 3, 4]
4
julia> matching = pm.Matching(H, weights=weights)
PyObject <pymatching.Matching object with 4 detectors, 1 boundary node, and 5 edges>
Python: <pymatching.Matching object with 4 detectors, 1 boundary node, and 5 edges>
julia> prediction = matching.decode([0, 1, 0, 1])
5-element Vector{UInt8}:
0x00
0x00
0x01
0x01
0x00
Python: array([0, 0, 1, 1, 0], dtype=uint8)
julia> prediction, solution_weight = matching.decode([0, 1, 0, 1], return_weight=true);
julia> prediction
5-element Vector{UInt8}:
0x00
0x00
0x01
0x01
0x00
Python: array([0, 0, 1, 1, 0], dtype=uint8)
julia> solution_weight
5.0
Python: 5.0
```

## ldpc
Expand All @@ -77,7 +58,7 @@ The python ldpc module is immediately available:
julia> using PyQDecoders
julia> PyQDecoders.ldpc
PyObject <module 'ldpc' from ...>
Python: <module 'ldpc' from ...>
```

Running the example from `ldpc`'s original Readme:
Expand All @@ -87,12 +68,12 @@ Running the example from `ldpc`'s original Readme:
julia> using PyQDecoders: sps, np, ldpc
julia> H = ldpc.codes.rep_code(3) # parity check matrix for the length-3 repetition code
2×3 Matrix{Int64}:
1 1 0
0 1 1
Python:
array([[1, 1, 0],
[0, 1, 1]])
julia> n = size(H, 2) # the codeword length
3
julia> n = H.shape[1] # the codeword length, same as `size(H, 2)`
Python: 3
julia> bpd = ldpc.bp_decoder(
H, # the parity check matrix
Expand All @@ -101,22 +82,21 @@ julia> bpd = ldpc.bp_decoder(
bp_method="product_sum", # BP method. The other option is `minimum_sum'
channel_probs=[nothing] # channel probability probabilities. Will override error rate.
)
PyObject <ldpc.bp_decoder.bp_decoder object at 0x7fea8283ab80>
Python: <ldpc.bp_decoder.bp_decoder object at 0x...>
julia> error = [0,1,0]
3-element Vector{Int64}:
0
1
0
julia> syndrome = H*error .% 2
julia> using PythonCall: PyArray
julia> syndrome = PyArray(H)*error .% 2
2-element Vector{Int64}:
1
1
julia> decoding = bpd.decode(syndrome)
3-element Vector{Int64}:
0
1
0
julia> decoding = bpd.decode(np.array(syndrome))
Python: array([0, 1, 0])
```
29 changes: 13 additions & 16 deletions src/PyQDecoders.jl
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
module PyQDecoders
import Conda
using PyCall
import PythonCall

const sps = PyNULL()
const np = PyNULL()
const pm = PyNULL()
const ldpc = PyNULL()
const sp = PythonCall.pynew()
const sps = PythonCall.pynew()
const np = PythonCall.pynew()
const pm = PythonCall.pynew()
const ldpc = PythonCall.pynew()
const ldpccodes = PythonCall.pynew()

function __init__()
copy!(sps, pyimport_conda("scipy.sparse", "scipy"))
copy!(np, pyimport_conda("numpy", "numpy"))
if PyCall.conda
Conda.pip_interop(true)
Conda.pip("install", "pymatching")
Conda.pip("install", "ldpc")
end
copy!(pm, pyimport_conda("pymatching", "pymatching"))
copy!(ldpc, pyimport_conda("ldpc", "ldpc"))
pyimport("ldpc.codes")
PythonCall.pycopy!(sp, PythonCall.pyimport("scipy"))
PythonCall.pycopy!(sps, PythonCall.pyimport("scipy.sparse"))
PythonCall.pycopy!(np, PythonCall.pyimport("numpy"))
PythonCall.pycopy!(pm, PythonCall.pyimport("pymatching"))
PythonCall.pycopy!(ldpc, PythonCall.pyimport("ldpc"))
PythonCall.pycopy!(ldpccodes, PythonCall.pyimport("ldpc.codes"))
end

end # module
4 changes: 2 additions & 2 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[deps]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
Expand Down
1 change: 0 additions & 1 deletion test/test_aqua.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Aqua
using PyQDecoders
Aqua.test_all(PyQDecoders,
ambiguities=(broken=true,),
)
6 changes: 3 additions & 3 deletions test/test_jet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ function (::MayThrowIsOk)(report_type::Type{<:InferenceErrorReport}, @nospeciali
end

# imported to be declared as modules filtered out from analysis result
using Conda, PyCall
using CondaPkg, PythonCall

@testset "JET checks" begin
rep = report_package("PyQDecoders";
report_pass=MayThrowIsOk(),
ignored_modules=(
AnyFrameModule(Conda),
AnyFrameModule(PyCall),
AnyFrameModule(CondaPkg),
AnyFrameModule(PythonCall),
)
)
@show rep
Expand Down

2 comments on commit e92a858

@Krastanov
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/102975

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.2.0 -m "<description of version>" e92a8584e98c1480d97e92be34178b28345dda4f
git push origin v0.2.0

Please sign in to comment.