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

MixedOp implementation #3

Closed
wants to merge 4 commits into from
Closed

MixedOp implementation #3

wants to merge 4 commits into from

Conversation

ElePT
Copy link

@ElePT ElePT commented Aug 31, 2022

Summary

This is a PR to expose my PoC for the MixedOp implementation and corresponding extension of the QubitConverter class.

Apart from the corresponding classes, there are 2 PoC files (not in the best location) to show the functionality that has been implemented. I recommend taking a look at this one.

Details and comments

Implemented:

  • Minimal MixedOp class that supports:
    • Operations:
      - Multiplication with scalar
      - MixedOp addition
    • Basic repr() and len() methods
  • Override of composition operator for FermionicOp to return MixedOp ⚠️⚠️ Currently, mixed ops can only be created by doing FermionicOp @ SpinOp, any other order or classes will not work!
  • Quick fix of QubitConverter to support MixedOp

Missing:

  • Constructor that can take in multiple tuples of (list[ops], coeff) --> do we want this?
  • Extension to arbitrary operators, not only fermionic/spin
  • Operations:
    • MixedOp + MixedOp
    • All others (if required)
  • Proper repr(), etc
  • Clean implementation of QubitConverter, including proper logic to deal with symmetry reductions in the MixedOp case.

@ElePT ElePT requested a review from mrossinek as a code owner August 31, 2022 17:45
@mrossinek
Copy link
Owner

I will review this in ~2 weeks 👍

Copy link
Owner

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

Submitting an in-progress review as some initial feedback

@@ -337,4 +337,4 @@
},
"nbformat": 4,
"nbformat_minor": 4
}
Copy link
Owner

Choose a reason for hiding this comment

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

Please revert this change 🙂

@@ -110,7 +114,7 @@ class QubitConverter:

def __init__(
self,
mapper: QubitMapper,
mappers: Sequence[QubitMapper],
Copy link
Owner

Choose a reason for hiding this comment

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

A scalable approach for the future will need to use a Mapping instead of sequence here which then maps from operator type to mapper.
Alternatively, we could also envision inferring the compatible operator type from a mapper instance and then use a Collection (i.e. set of mappers).

Copy link
Owner

Choose a reason for hiding this comment

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

And arguable we should still support specifying only a single mapper (i.e. with | QubitMapper). I think the code below does this, but the type hint does not reflect this


# convert all fermionics and store in list
qubit_f_ops = []
max_f_reg_length = 0
Copy link
Owner

Choose a reason for hiding this comment

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

We should actually check, that all result in identical length operators. Otherwise something is likely wrong

qubit_ops = []
for c in mix_coefficients:
if len(c[0]) > 1:
qubit_ops.append(qubit_f_ops[c[0][0][1]] ^ qubit_s_ops[c[0][1][1]] * c[1])
Copy link
Owner

Choose a reason for hiding this comment

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

Accessing of the coefficients is a bit cryptic here. Probably more comments on that down below in the MixedOp

Comment on lines +494 to +500
# convert all spins and store in list
qubit_s_ops = []
max_s_reg_length = 0
for s_op in operators[SpinOp]:
q_op = apply_map_sym(s_op, spin_mapper)
max_s_reg_length = q_op.num_qubits if q_op.num_qubits > max_s_reg_length else max_s_reg_length
qubit_s_ops.append(q_op)
Copy link
Owner

Choose a reason for hiding this comment

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

I know that this prototype is currently hardcoding fermionic and spin ops, but we should try to design this block of code as a type-independent standalone piece of code.

This could then also be combined with the identity construction below.

else:
return self._mappers.map(second_q_op)

def _map_multiple(self, second_q_op: MixedOp) -> PauliSumOp:
Copy link
Owner

Choose a reason for hiding this comment

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

Can we generalize this implementation to not be map specific but only deal with handling a MixedOp, such that it can work with an arbitrary internal method such as _map, _two_qubit_reduce, etc. ?

Comment on lines +415 to +416
from .mixed_op import MixedOp
return MixedOp(([self, other], 1))
Copy link
Owner

Choose a reason for hiding this comment

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

I think it should be possible to leave the base operators unchanged, by handling this scenario in the MixedOp.__rmatmul__ case 🤔

Copy link
Author

Choose a reason for hiding this comment

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

I'm not sure how we could do this for the case FermionicOp @ SpinOp, because there isn't any MixedOp involved yet, so MixedOp.__rmatmul__ would not be called, right?

Comment on lines +15 to +18
if type(op) in self.ops:
self.ops[type(op)].append(op)
else:
self.ops[type(op)] = [op]
Copy link
Owner

Choose a reason for hiding this comment

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

You could simplify this by using a defaultdict(list) for self.ops

)

def __len__(self):
return len(self.ops[FermionicOp]) + len(self.ops[SpinOp])
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
return len(self.ops[FermionicOp]) + len(self.ops[SpinOp])
return sum(len(val) for val in self.ops.values())

qiskit_nature/second_q/operators/mixed_op.py Outdated Show resolved Hide resolved
@MarcDrudis
Copy link

Hello! I will be branching this repo since the lattice gauge theory needs MixedOps. That would potentially make it easier for Max to review the code. This way I can also give feedback in case something breaks.

@mrossinek
Copy link
Owner

Closing this in favor of qiskit-community#1188

@mrossinek mrossinek closed this Jul 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants