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

Remove dependance of BooleanExpression on tweedledum #13769

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

gadial
Copy link
Contributor

@gadial gadial commented Jan 30, 2025

Summary

Rewrites the BooleanExpression class such that expression parsing and circuit synthesis does not rely on the tweedledum library, and moves it to the synthesis library. Adds a BitFlipOracle class to preserve the user-facing usage of BooleanExpression.

Partially addresses #13755.

Details and comments

BooleanExpression is used to describe classical boolean functions and synthesize phase/bit-flip oracles for them. Currently it is used directly within qiskit only for the PhaseOracle class.

The current implementation of BooleanExpression relies on the tweedledum library for parsing and synthesizing. Since qiskit 2.0 will stop using tweedledum, this PR makes the code of BooleanExpression independent, in the cost of lower capabilities.

These are the main changes:

  1. Parsing is now done using the ast library, using a custom boolean_expression_visitor. Parsing DIMACS files is done directly using regexp.
  2. Oracle synthesis is now performed directly (within the new boolean_expression_synth module) using a straightforward approach seemingly also employed by tweedledum, given a representation of the function as ESOP (Exclusive sum of squares).
  3. A rudimentary procedure for converting a BooleanExpression into ESOP representation was also added. While it features basic optimizations to reduce the size of the ESOP, it needs to generate the full truth table of the represented function, making it a viable approach only for functions on a relatively low number of variables. This can be improved upon in the future if required, using more sophisticated ESOP generation and minimization techniques (such as using BDDs or SAT-solvers).
  4. All the synthesis-related code was moved to a new directory, synthesis/boolean. A new class, BitFlipOracle was added to the circuit library. The old BooleanExpression code remains unchanged and will be deprecated in a separate PR along with the rest of the classicalfunction library.

@gadial gadial requested a review from a team as a code owner January 30, 2025 19:14
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Cryoris
  • @Qiskit/terra-core
  • @ajavadia

@gadial gadial added this to the 2.0.0 milestone Jan 30, 2025
@ShellyGarion ShellyGarion self-assigned this Jan 31, 2025
@coveralls
Copy link

coveralls commented Feb 2, 2025

Pull Request Test Coverage Report for Build 13175136785

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 191 of 203 (94.09%) changed or added relevant lines in 6 files are covered.
  • 1177 unchanged lines in 35 files lost coverage.
  • Overall coverage decreased (-0.2%) to 88.638%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/synthesis/boolean/boolean_expression.py 68 69 98.55%
qiskit/synthesis/boolean/boolean_expression_visitor.py 38 39 97.44%
qiskit/synthesis/boolean/boolean_expression_synth.py 74 77 96.1%
qiskit/circuit/library/bit_flip_oracle.py 7 14 50.0%
Files with Coverage Reduction New Missed Lines %
qiskit/circuit/library/phase_oracle.py 1 85.71%
crates/accelerate/src/gate_direction.rs 1 97.34%
crates/accelerate/src/twirling.rs 1 97.62%
crates/accelerate/src/unitary_synthesis.rs 1 92.97%
crates/accelerate/src/barrier_before_final_measurement.rs 1 98.36%
qiskit/providers/fake_provider/fake_backend.py 1 85.51%
qiskit/transpiler/preset_passmanagers/plugin.py 1 98.33%
qiskit/providers/basic_provider/basic_provider_tools.py 1 83.33%
qiskit/pulse/transforms/canonicalization.py 1 93.44%
qiskit/pulse/transforms/base_transforms.py 2 86.96%
Totals Coverage Status
Change from base Build 13072040346: -0.2%
Covered Lines: 79535
Relevant Lines: 89730

💛 - Coveralls

@ShellyGarion ShellyGarion linked an issue Feb 2, 2025 that may be closed by this pull request
Copy link
Member

@ShellyGarion ShellyGarion left a comment

Choose a reason for hiding this comment

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

Thanks @gadial for taking care of this - it looks great!

Note that there are some necessary API changes here, which makes sense and it's also allowed for Qiskit 2.0, but probably need better release notes, as well as raise deprecation warnings in Qiskit 1.4.

Did you make some experiments to check the performance compared to Tweedledum?



@HAS_TWEEDLEDUM.require_in_instance
class BooleanExpression(ClassicalElement):
class BooleanExpression(Gate):
Copy link
Member

Choose a reason for hiding this comment

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

Note the API change here (changed types)

quantum register.
synthesizer: A callable that takes self and returns a Tweedledum
circuit.
circuit_type: which type of oracle to create, 'bit' or 'phase' flip oracle.
Copy link
Member

Choose a reason for hiding this comment

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

Note the API change in this function

@@ -50,40 +44,18 @@ class PhaseOracle(QuantumCircuit):

def __init__(
self,
expression: Union[str, ClassicalElement],
synthesizer: Optional[Callable[[BooleanExpression], QuantumCircuit]] = None,
expression: str,
var_order: list = None,
Copy link
Member

Choose a reason for hiding this comment

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

Note the API change in the init



@HAS_TWEEDLEDUM.require_in_instance
class BooleanExpression(ClassicalElement):
class BooleanExpression(Gate):
Copy link
Contributor

Choose a reason for hiding this comment

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

The easiest deprecation path would be to just deprecate BooleanExpression in place and have the new version in the circuit library.

It might also be worth considering a renaming to avoid too much confusion with the new object. What does this circuit implement exactly? Does it flip a target bit if the boolean expression is satisfied or does it something in-place? If it's the first, maybe BitflipOracle could be a good name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems like a sound strategy - we already have a PhaseOracle so we can add BitFlipOracle which will be similar but with a different synthesis, and both gates would rely on a non-gate version of BooleanExpression (maybe with a different name) which handles parsing, simulating (to create the truth table) and synthesizing (since we might want to invest in optimized algorithms later.

The main question is where to put those files. We can put BitFlipOracle next to PhaseOracle in qiskit.circuit.library but we still need to put the NewBooleanExpression module (which would consist at least of boolean_expression, boolean_expression_visitor and boolean_expression_synth files) somewhere that makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in e403028

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.

Remove tweedledum from qiskit-sdk
5 participants