Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allowing arbitrary initialization of the input nodes #135

Open
wants to merge 33 commits into
base: master
Choose a base branch
from

Conversation

mgarnier59
Copy link
Contributor

Allowing arbitrary intialization of the input nodes for statevector and density matrix backends + tests.

Several format of initialization are supported (Statevec or DensityMatrix objects, list of newly-defined State objects, numerical data).
Main change is that basic states (|0>, |+>, ...) are now in states.BasicStates and no longer in ops.py.

@mgarnier59 mgarnier59 requested a review from shinich1 May 3, 2024 14:28
graphix/states.py Outdated Show resolved Hide resolved
@shinich1 shinich1 linked an issue May 6, 2024 that may be closed by this pull request
graphix/states.py Outdated Show resolved Hide resolved
.pre-commit-config.yaml Outdated Show resolved Hide resolved
.vscode/settings.json Outdated Show resolved Hide resolved
graphix/ops.py Outdated Show resolved Hide resolved
graphix/pattern.py Outdated Show resolved Hide resolved
graphix/pattern.py Outdated Show resolved Hide resolved
graphix/simulator.py Outdated Show resolved Hide resolved
graphix/simulator.py Outdated Show resolved Hide resolved
tests/test_statevec.py Outdated Show resolved Hide resolved
graphix/sim/statevec.py Outdated Show resolved Hide resolved
@@ -29,8 +32,10 @@ def test_measurement_into_each_XYZ_basis(self):
n = 3
k = 0
# for measurement into |-> returns [[0, 0], ..., [0, 0]] (whose norm is zero)
for state in [States.plus, States.zero, States.one, States.iplus, States.iminus]:
m_op = np.outer(state, state.T.conjugate())
# NOTE weird choice (MINUS is orthogonal to PLUS so zero)
Copy link
Contributor

Choose a reason for hiding this comment

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

? remove?

tests/test_pattern.py Outdated Show resolved Hide resolved
tests/test_pattern.py Outdated Show resolved Hide resolved
@shinich1 shinich1 mentioned this pull request May 9, 2024
@thierry-martinez
Copy link
Contributor

@mgarnier59 @thierry-martinez how do the performance of simulation compare with original implementation? I presume no significant difference since it's only modifying the initialization part?

We didn't investigate it. What's more it provides more feature compared to the previous versions. I tend to think that global performance issues will be adressed later.

I believe we should at least test it's not surprisingly slow by 2x or more, or have completely different scaling as a function of problem size, which indicates something is wrong with the code. if it's up to a few tens of % (which I believe is most likely the case) indeed it can be safely addressed later.

I obtained these benchmarks (input-init is the version I just pushed, which includes the last changes in master; input-init^1 is the version before the merge). Performances are quite close indeed.

+-------------------------------------------------------------------------------------+
|                       statement                      |master|input-init|input-init^1|
+------------------------------------------------------+------+----------+------------+
|                    pytest.main([])                   | 16.28|   16.41  |    14.67   |
+------------------------------------------------------+------+----------+------------+
|random_circuits(seed=42, times=20, nqubit=15, depth=1)| 3.12 |   3.30   |    3.27    |
+------------------------------------------------------+------+----------+------------+
|random_circuits(seed=42, times=20, nqubit=16, depth=1)| 9.69 |   8.24   |    8.45    |
+------------------------------------------------------+------+----------+------------+
|random_circuits(seed=42, times=20, nqubit=17, depth=1)| 17.61|   18.91  |    17.72   |
+------------------------------------------------------+------+----------+------------+
|random_circuits(seed=42, times=20, nqubit=18, depth=1)| 39.14|   41.15  |    42.17   |
+------------------------------------------------------+------+----------+------------+
|random_circuits(seed=42, times=20, nqubit=19, depth=1)| 72.78|   76.26  |    77.80   |
+------------------------------------------------------+------+----------+------------+
|random_circuits(seed=42, times=20, nqubit=20, depth=1)|155.43|  162.73  |   163.46   |
+-------------------------------------------------------------------------------------+

@shinich1
Copy link
Contributor

@thierry-martinez Thanks a lot, that looks great!

Copy link

codecov bot commented May 13, 2024

Codecov Report

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

Project coverage is 72.17%. Comparing base (dd15e5d) to head (8836a61).

Current head 8836a61 differs from pull request most recent head 6ebfcbe

Please upload reports for the commit 6ebfcbe to get more accurate results.

Files Patch % Lines
graphix/sim/tensornet.py 38.09% 13 Missing ⚠️
graphix/sim/statevec.py 92.98% 4 Missing ⚠️
graphix/states.py 87.09% 4 Missing ⚠️
graphix/sim/density_matrix.py 92.68% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #135      +/-   ##
==========================================
+ Coverage   71.75%   72.17%   +0.42%     
==========================================
  Files          30       32       +2     
  Lines        5353     5441      +88     
==========================================
+ Hits         3841     3927      +86     
- Misses       1512     1514       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

mgarnier59 and others added 7 commits May 14, 2024 14:46
Reported by Maxime Garnier.
TeamGraphix@f377001#r142237724

The test for Pauli preprocessing in density_matrix.py should be
```
pattern._pauli_preprocessed and input_state != graphix.states.BasicStates.PLUS
```
without `not`.

This bug wasn't caught by `pytest` because the density matrix backend
was never tested with Pauli-preprocessed patterns. I think a natural
place to add such a test is in `test_pattern.py`, by "parametrizing"
`test_pauli_measurment` with `backend`. This was not enough because
`test_pauli_measurment` was defined twice in the same file and the
second definition was hiding the first one. Therefore, this commit:

- rename the first `test_pauli_measurment` into
  `test_pauli_measurement_random_circuit` (fixing the typo by the way);

- "parametrize" `test_pauli_measurement_random_circuit` with
  `backend`, testing `"statevector"` and `"densitymatrix"`;

- a TODO is added for tensor network backend, since the default
  `graph_prep` mode (`auto`) selects the mode `parallel` despite this
  mode is incompatible with non-standardize patterns. I propose to leave
  that for another PR.
@shinich1 shinich1 requested a review from EarlMilktea May 23, 2024 17:03
@shinich1
Copy link
Contributor

@EarlMilktea could you take a quick look at the changes?

Copy link
Contributor

@EarlMilktea EarlMilktea left a comment

Choose a reason for hiding this comment

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

memo: duplicated comments are added only once (ex. use from __future__ import annotations)

@@ -1,5 +1,6 @@
from typing import Optional, Union
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use from __future__ import annotations instead.

@@ -68,7 +69,7 @@ def rand_dm(dim: int, rank: int = None, dm_dtype=True) -> DensityMatrix:
return dm


def rand_gauss_cpx_mat(dim: int, sig: float = 1 / np.sqrt(2)) -> npt.NDArray:
def rand_gauss_cpx_mat(dim: int, sig: float = 1 / np.sqrt(2)) -> np.ndarray:
Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer to use npt.NDArray unless absolutely necessary (ex. runtime checking of return type) because we cannot specify element type.

from graphix.sim.statevec import CNOT_TENSOR, CZ_TENSOR, SWAP_TENSOR, meas_op
from graphix.sim.statevec import CNOT_TENSOR, CZ_TENSOR, SWAP_TENSOR, Statevec

Data = typing.Union[
Copy link
Contributor

Choose a reason for hiding this comment

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

typing.Union is deprecated.

graphix.states.State,
"DensityMatrix",
Statevec,
typing.Iterable[graphix.states.State],
Copy link
Contributor

Choose a reason for hiding this comment

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

Please import from collections.abc instead.

return
if isinstance(data, typing.Iterable):
input_list = list(data)
if len(input_list) != 0:
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to compute len.

"""

@abc.abstractmethod
def get_statevector(self) -> np.ndarray:
Copy link
Contributor

Choose a reason for hiding this comment

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

npt.NDArray if possible.

plane: graphix.pauli.Plane
angle: float

def __repr__(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Please specify return type explicitly.

nqb = fx_rng.integers(2, 5)
print(f"nqb is {nqb}")
rand_angles = fx_rng.random(nqb) * 2 * np.pi
rand_planes = fx_rng.choice(np.array([i for i in graphix.pauli.Plane]), nqb)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it necessary to cast to np.ndarray before choice?

from graphix.states import BasicStates, PlanarState


class TestStatevec(unittest.TestCase):
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do not use unittest.

# for testing with arbitrary inputs
# SV and DM backend
class TestPatternSim:
def test_sv_sim(self, fx_rng: Generator, nqb, rand_circ):
Copy link
Contributor

Choose a reason for hiding this comment

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

Please specify -> None explicitly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

arbitrary initial state
4 participants