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

Support ClExpr #176

Merged
merged 5 commits into from
Nov 12, 2024
Merged

Support ClExpr #176

merged 5 commits into from
Nov 12, 2024

Conversation

PabloAndresCQ
Copy link
Collaborator

@PabloAndresCQ PabloAndresCQ commented Nov 11, 2024

Description

Support for ClExpr

Related issues

#175

Checklist

  • I have performed a self-review of my code.
  • I have commented hard-to-understand parts of my code.
  • I have made corresponding changes to the public API documentation.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have updated the changelog with any user-facing changes.

c = circ.add_c_register("c", 5)
d = circ.add_c_register("d", 5)
circ.H(0)
wexpr, args = wired_clexpr_from_logic_exp(a | b, c) # type: ignore
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 had to add # type: ignore here because it complains that the second argument c is a BitRegister, rather than list[Bit]. Is there a way around it? Is this a valid implicit cast, or should it be avoided?

Copy link
Collaborator

Choose a reason for hiding this comment

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

You could write c.to_list().

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

All of the new tests in this file are just copy-pastes of existing tests using ClassicalExpBox, but now using ClExpr. It would be nice to add more tests, because these are minimal and only one of them is checking for correctness (and only on bit operations, rather than register ones).

Do you know of any tests from other repositories that could be used here? Any suggestions of where to get circuits to test on, for which the intended behaviour is known (and, hence, can be checked against)?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not really. There's a test here for the quantinuum local emulator, but it uses ClassicalExpBox with operations that are not supported here, so isn't much use.

@PabloAndresCQ PabloAndresCQ marked this pull request as ready for review November 12, 2024 11:17
Copy link
Collaborator

@cqc-alec cqc-alec left a comment

Choose a reason for hiding this comment

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

Looks good, just a few comments. It would be good to nail down the exact semantics of all the operations; I intentionally didn't do this in the pytket documentation because we don't seem to have an agreed semantics for extended QASM written down anywhere.

I'd recommend testing this also with the pre-release pytket 1.35.0rc0 if that's easy to do.

@@ -239,6 +330,32 @@ def test_pytket_qir_conditional_10() -> None:
assert state.get_fidelity() == 1.0


def test_pytket_qir_conditional_11() -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this name?

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 grabbed these tests from the pytket_qir repository (here) and did not notice that the qir in the name was no longer applicable here. Happy to rename it them test_basic_conditional_x.

Comment on lines +596 to +597
# From chat with Silas and exploring the RUS as a block matrix, we have noticed
# that the circuit is missing an X correction when this condition is satisfied
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this issue tracked somewhere?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This RUS circuit comes from a paper where they acknowledge that a "recovery operation" (i.e. correction) is required in some cases for RUS. As far as I can tell, they don't explicitly indicate what is the recovery operation required for this particular circuit (appearing in Fig 1c), but we figured it was an X correction.

AFAIK this is not tracked anywhere, but is known by people with experience on RUS.

Comment on lines +598 to +599
wexpr, args = wired_clexpr_from_logic_exp(flag[0] ^ flag[1], [flag[2]])
circ.add_clexpr(wexpr, args)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Reading these tests makes me think we should add a method Circuit.add_clexpr_from_logic_exp() to combine these two steps.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, could be a handy addition, but not strictly necessary.

else:
# TODO: Currently not supporting ClOp's RegDiv since it does not return int,
# so I am unsure what the semantic is meant to be.
# TODO: I don't now what to do with RegNot, since input
Copy link
Collaborator

Choose a reason for hiding this comment

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

The intended semantics of RegNot is bitwise-NOT, i.e. every bit of the register is flipped.

# result = int(args_val[0] == 0)
elif expr.op in [ClOp.BitZero, ClOp.RegZero]:
result = 0
elif expr.op in [ClOp.BitOne, ClOp.RegOne]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

The intended semantics of RegOne is that every bit is set to 1.

# elif expr.op == ClOp.RegNeg:
# result = -args_val[0]
else:
# TODO: Currently not supporting ClOp's RegDiv since it does not return int,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it should return the integer quotient, i.e. floor(a/b) where a and b are unsigned integers. (If this doesn't fit in the result register, perhaps error is the kindest response.)

Copy link
Collaborator

Choose a reason for hiding this comment

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

But if we are leaving ADD etc unsupported for now I don't see a need to support DIV.

@PabloAndresCQ
Copy link
Collaborator Author

Thanks for the pointers on the semantics for the undefined operations. I will add these, and throw an error on overflow for now. I will bring up the need to agree on semantics of these extended QASM operations in the cross-team standup today.

Copy link
Collaborator

@cqc-alec cqc-alec left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@PabloAndresCQ PabloAndresCQ merged commit 1e12786 into main Nov 12, 2024
9 checks passed
@PabloAndresCQ PabloAndresCQ deleted the feat/clexpr branch November 12, 2024 17:05
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.

2 participants