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

New multirep PR initiated #496

Open
wants to merge 84 commits into
base: develop
Choose a base branch
from
Open

New multirep PR initiated #496

wants to merge 84 commits into from

Conversation

arsalan-motamedi
Copy link
Collaborator

Context:
We need a way to handle representations, without needing to worry about them when taking contractions.

Description of the Change:
The main change is adding _index_representation as an attribute to CircuitComponent, which keeps track of representation on each index.

Benefits:
We don't need to worry about BtoQ and BtoPS changing the result of contractions.

Possible Drawbacks:
All contractions are computed in Bargmann still. We may want to enforce contacting in a specific representation.

Related GitHub Issues:
None.

@arsalan-motamedi arsalan-motamedi added the no changelog Pull request does not require a CHANGELOG entry label Oct 2, 2024
@@ -325,6 +325,11 @@ def indices(self) -> tuple[int, ...]:
self.index_dicts[t][m] for t, modes in enumerate(self.sorted_args) for m in modes
)


@cached_property
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are we caching this? This seems unnecessary as it's just a reordering of an already cached property i.e. duplicate information being cached

Copy link

codecov bot commented Oct 9, 2024

Codecov Report

Attention: Patch coverage is 93.90244% with 15 lines in your changes missing coverage. Please review.

Project coverage is 89.88%. Comparing base (8c705c0) to head (fdfbe02).

Files with missing lines Patch % Lines
mrmustard/lab_dev/circuit_components.py 88.23% 14 Missing ⚠️
...mustard/lab_dev/circuit_components_utils/b_to_q.py 98.24% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #496      +/-   ##
===========================================
+ Coverage    89.77%   89.88%   +0.11%     
===========================================
  Files          104      104              
  Lines         7639     7871     +232     
===========================================
+ Hits          6858     7075     +217     
- Misses         781      796      +15     
Files with missing lines Coverage Δ
...ustard/lab_dev/circuit_components_utils/b_to_ps.py 100.00% <100.00%> (ø)
mrmustard/lab_dev/states/base.py 96.56% <100.00%> (+0.05%) ⬆️
mrmustard/lab_dev/transformations/dgate.py 100.00% <ø> (ø)
mrmustard/lab_dev/wires.py 99.28% <100.00%> (+0.01%) ⬆️
...mustard/lab_dev/circuit_components_utils/b_to_q.py 98.57% <98.24%> (-1.43%) ⬇️
mrmustard/lab_dev/circuit_components.py 96.14% <88.23%> (-2.96%) ⬇️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8c705c0...fdfbe02. Read the comment docs.

Circuit_20241007_161758_6f66130b.json Outdated Show resolved Hide resolved
mrmustard/lab_dev/circuit_components.py Outdated Show resolved Hide resolved

# add some validation
self._index_representation_ = value

def _serialize(self) -> tuple[dict[str, Any], dict[str, ArrayLike]]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you need to incorporate _index_representation into the serialization of the object?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm.. not sure about that. But I guess it makes some sense to keep _index_representationas a hidden attribute since there are many calls to circuit component initializer and I might be missing correcting some when doing the change.

mrmustard/lab_dev/circuit_components.py Outdated Show resolved Hide resolved
mrmustard/lab_dev/circuit_components.py Outdated Show resolved Hide resolved
mrmustard/lab_dev/circuit_components.py Outdated Show resolved Hide resolved
mrmustard/lab_dev/circuit_components.py Outdated Show resolved Hide resolved
rep = self.representation + other.representation
rep = (
self.to_bargmann().representation + other.to_bargmann().representation
) # addition occurs in bargmann always
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need it in bargmann?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is to avoid adding things with different representations. Lmk if you have a better approach in mind.

):
return self.representation == other.representation and self.wires == other.wires
else:
self_rep = self.to_bargmann().representation
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure how I feel about this why do we need this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well.. two things are equal if they are equal in the same representation. I mean, in physics, we call them the same thing.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But why do we need to call to_bargmann in the __eq__? I would expect it to just be

def __eq__(self, other):
     if isinstance(other, CircuitComponent):
          return self.representation == other.representation and self.wires == other.wires
     return False 


def __mul__(self, other: Scalar) -> CircuitComponent:
r"""
Implements the multiplication by a scalar from the right.
"""
return self._from_attributes(self.representation * other, self.wires, self.name)
ret = self._from_attributes(self.representation * other, self.wires, self.name)
ret._index_representation = self._index_representation
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you need to copy?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am not sure I understand the question. Can you please elaborate?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Same issue you encountered before where the solution was to deepcopy the dictionary. As in, ret._index_representation is now pointing to the dictionary of self._index_representation so any mutations to the latter propagate to the former

d2 = {mode + len(modes): ("B", None) for mode in range(len(modes))}
d3 = {mode + 2 * len(modes): ("PS", float(self.s.value)) for mode in range(len(modes))}
d4 = {mode + 3 * len(modes): ("B", None) for mode in range(len(modes))}
self._index_representation = {**d1, **d2, **d3, **d4}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Alternatively now that self._index_representation is initialized in the super().__init__ you can just update the output indices

@@ -16,6 +16,7 @@
The class representing an operation that changes Bargmann into quadrature.
"""
# pylint: disable=protected-access
# pylint: disable=protected-access
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
# pylint: disable=protected-access

self._add_parameter(Constant(phi, "phi"))
self.phi = phi
d1 = {mode: ("Q", float(self.phi.value)) for mode in range(len(modes))}
d2 = {mode + len(modes): ("B", None) for mode in range(len(modes))}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto to what I mentioned in BtoPS

if isinstance(self.representation, Bargmann): # TODO: better name for Bargmann class
# check cc rep
if not indices:
indices = self.wires.indices
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
indices = self.wires.indices
indices = indices if indices else self.wires.indices

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no changelog Pull request does not require a CHANGELOG entry
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants