-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
virtual padding for invalid section_size in synth_cnot_count_full_pmh #12712
Changes from 3 commits
51ae0b3
3f19cb2
a71f09f
9e3bf5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,14 +37,19 @@ def synth_cnot_count_full_pmh( | |
Args: | ||
state: :math:`n \\times n` boolean invertible matrix, describing | ||
the state of the input circuit | ||
section_size: The size of each section in the Patel–Markov–Hayes algorithm [1]. | ||
section_size: The size of each section, used in the | ||
Patel–Markov–Hayes algorithm [1]. ``section_size`` must be a factor of the number | ||
of qubits. | ||
|
||
Returns: | ||
QuantumCircuit: a CX-only circuit implementing the linear transformation. | ||
|
||
Raises: | ||
QiskitError: when variable ``state`` isn't of type ``numpy.ndarray`` | ||
|
||
We used concept called virtual padding to generate marices filled by Zeros | ||
when the algorithm fail to handle a section_size more than the number of qubits. | ||
|
||
References: | ||
1. Patel, Ketan N., Igor L. Markov, and John P. Hayes, | ||
*Optimal synthesis of linear reversible circuits*, | ||
|
@@ -53,25 +58,38 @@ def synth_cnot_count_full_pmh( | |
""" | ||
if not isinstance(state, (list, np.ndarray)): | ||
raise QiskitError( | ||
f"state should be of type list or numpy.ndarray, but was of the type {type(state)}" | ||
"state should be of type list or numpy.ndarray, " | ||
"but was of the type {}".format(type(state)) | ||
) | ||
state = np.array(state) | ||
num_qubits = state.shape[0] | ||
|
||
# Virtual Padding | ||
if section_size > num_qubits: | ||
padding_size = section_size - (num_qubits % section_size) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could this be simplified to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @alexanderivrii the goal of padding is to extend the matrix to a size divisible by the |
||
state = np.hstack((state, np.zeros((num_qubits, padding_size), dtype=bool))) | ||
|
||
# Synthesize lower triangular part | ||
[state, circuit_l] = _lwr_cnot_synth(state, section_size) | ||
[state, circuit_l] = _lwr_cnot_synth(state, section_size, num_qubits) | ||
state = np.transpose(state) | ||
|
||
# Synthesize upper triangular part | ||
[state, circuit_u] = _lwr_cnot_synth(state, section_size) | ||
[state, circuit_u] = _lwr_cnot_synth(state, section_size, num_qubits) | ||
circuit_l.reverse() | ||
for i in circuit_u: | ||
i.reverse() | ||
# Convert the list into a circuit of C-NOT gates | ||
circ = QuantumCircuit(state.shape[0]) | ||
|
||
# Convert the list into a circuit of C-NOT gates (removing virtual padding) | ||
circ = QuantumCircuit(num_qubits) # Circuit size is the original num_qubits | ||
for i in circuit_u + circuit_l: | ||
circ.cx(i[0], i[1]) | ||
# Only add gates if both control and target are within the original matrix | ||
if i[0] < num_qubits and i[1] < num_qubits: | ||
circ.cx(i[0], i[1]) | ||
|
||
return circ | ||
|
||
def _lwr_cnot_synth(state, section_size, num_qubits): | ||
|
||
def _lwr_cnot_synth(state, section_size): | ||
""" | ||
Abdalla01001 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This function is a helper function of the algorithm for optimal synthesis | ||
of linear reversible circuits (the Patel–Markov–Hayes algorithm). It works | ||
|
@@ -103,25 +121,31 @@ def _lwr_cnot_synth(state, section_size): | |
numpy.matrix: n by n matrix, describing the state of the output circuit | ||
list: a k by 2 list of C-NOT operations that need to be applied | ||
""" | ||
|
||
"""Also used virtual padding.""" | ||
|
||
circuit = [] | ||
num_qubits = state.shape[0] | ||
cutoff = 1 | ||
|
||
# Iterate over column sections | ||
for sec in range(1, int(np.floor(num_qubits / section_size) + 1)): | ||
# Iterate over column sections (including padded sections) | ||
for sec in range(1, int(np.ceil(state.shape[1] / section_size)) + 1): | ||
# Remove duplicate sub-rows in section sec | ||
patt = {} | ||
for row in range((sec - 1) * section_size, num_qubits): | ||
sub_row_patt = copy.deepcopy(state[row, (sec - 1) * section_size : sec * section_size]) | ||
sub_row_patt = copy.deepcopy( | ||
state[row, (sec - 1) * section_size : sec * section_size] | ||
) | ||
if np.sum(sub_row_patt) == 0: | ||
continue | ||
if str(sub_row_patt) not in patt: | ||
patt[str(sub_row_patt)] = row | ||
else: | ||
state[row, :] ^= state[patt[str(sub_row_patt)], :] | ||
circuit.append([patt[str(sub_row_patt)], row]) | ||
|
||
# Use gaussian elimination for remaining entries in column section | ||
for col in range((sec - 1) * section_size, sec * section_size): | ||
# Modified loop range | ||
for col in range((sec - 1) * section_size, min(sec * section_size, num_qubits)): | ||
# Check if 1 on diagonal | ||
diag_one = 1 | ||
if state[col, col] == 0: | ||
|
@@ -139,4 +163,5 @@ def _lwr_cnot_synth(state, section_size): | |
if sum(state[col, :] & state[row, :]) > cutoff: | ||
state[col, :] ^= state[row, :] | ||
circuit.append([row, col]) | ||
|
||
return [state, circuit] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After discussing with @alexanderivrii and @ShellyGarion we came to the conclusion that the section size being larger than the number of qubits is an invalid input. It would be better to raise an error if
section_size > num_qubits
, as originally done in #12166. Could you do that and remove the virtual padding?We'll go forward with your PR then, as it still fixes the bad
section_size
values due to your fixes on L131 and L148.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, I did it