Skip to content

Commit f2eabb2

Browse files
authored
First preparations for making And an atomic/leaf bloq (#1347)
* First preparations for making And an atomic/leaf bloq * fix notebook due to change away from defaultdict * format
1 parent ab5372a commit f2eabb2

18 files changed

Lines changed: 185 additions & 101 deletions

qualtran/bloqs/arithmetic/controlled_add_or_subtract_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@
3636
_ctrl_add_or_sub_unsigned,
3737
ControlledAddOrSubtract,
3838
)
39-
from qualtran.bloqs.basic_gates import TGate
40-
from qualtran.resource_counting import get_cost_value
41-
from qualtran.resource_counting._bloq_counts import BloqCount
39+
from qualtran.resource_counting import get_cost_value, QECGatesCost
4240

4341

4442
def test_examples(bloq_autotester):
@@ -107,4 +105,6 @@ def test_t_complexity():
107105
dtype = QUInt(n)
108106
bloq = ControlledAddOrSubtract(dtype, dtype)
109107

110-
assert get_cost_value(bloq, BloqCount.for_gateset('t')) == {TGate(): 4 * n - 4}
108+
counts = get_cost_value(bloq, QECGatesCost()).total_t_and_ccz_count()
109+
assert counts['n_t'] == 0, 'toffoli only'
110+
assert counts['n_ccz'] == n - 1

qualtran/bloqs/arithmetic/permutation_test.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@
3737
Permutation,
3838
PermutationCycle,
3939
)
40-
from qualtran.bloqs.basic_gates import CNOT, TGate, XGate
41-
from qualtran.bloqs.bookkeeping import Allocate, ArbitraryClifford, Free
42-
from qualtran.resource_counting.generalizers import ignore_split_join
40+
from qualtran.bloqs.basic_gates import CNOT, XGate
41+
from qualtran.bloqs.bookkeeping import Allocate, Free
42+
from qualtran.bloqs.mcmt import And
43+
from qualtran.resource_counting.generalizers import generalize_cvs, ignore_split_join
4344
from qualtran.symbolics import ceil, log2, slen
4445

4546

@@ -62,11 +63,14 @@ def test_permutation_cycle_unitary_and_call_graph():
6263
bloq.tensor_contract(), np.array([[0, 0, 1, 0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
6364
)
6465

65-
_, sigma = bloq.call_graph(generalizer=ignore_split_join)
66+
cv = sympy.Symbol('cv')
67+
_, sigma = bloq.call_graph(
68+
generalizer=[ignore_split_join, generalize_cvs], keep=lambda b: isinstance(b, And)
69+
)
6670
assert sigma == {
6771
CNOT(): 8,
68-
TGate(): 16,
69-
ArbitraryClifford(n=2): 76,
72+
And(cv1=cv, cv2=cv): 4,
73+
And(cv1=cv, cv2=cv).adjoint(): 4,
7074
Allocate(QBit()): 1,
7175
Free(QBit()): 1,
7276
}
@@ -76,10 +80,10 @@ def test_permutation_cycle_symbolic_call_graph():
7680
bloq = _permutation_cycle_symb()
7781
logN, L = ceil(log2(bloq.N)), slen(bloq.cycle)
7882

79-
_, sigma = bloq.call_graph()
83+
_, sigma = bloq.call_graph(keep=lambda b: isinstance(b, And))
8084
assert sigma == {
81-
ArbitraryClifford(n=2): (L + 1) * (13 * logN - 13),
82-
TGate(): (L + 1) * (4 * logN - 4),
85+
And(): (L + 1) * (logN - 1),
86+
And().adjoint(): (L + 1) * (logN - 1),
8387
CNOT(): L * logN + L + 1,
8488
}
8589

@@ -103,12 +107,12 @@ def test_permutation_unitary_and_call_graph():
103107
),
104108
)
105109

106-
_, sigma = bloq.call_graph(generalizer=ignore_split_join)
110+
_, sigma = bloq.call_graph(generalizer=ignore_split_join, keep=lambda b: isinstance(b, And))
107111
assert sigma == {
108112
CNOT(): 17,
109-
TGate(): 56,
113+
And(): 56 // 4,
114+
And().adjoint(): 56 // 4,
110115
XGate(): 56,
111-
ArbitraryClifford(n=2): 182,
112116
Allocate(QBit()): 2,
113117
Free(QBit()): 2,
114118
}
@@ -130,9 +134,9 @@ def test_permutation_symbolic_call_graph():
130134
logN = ceil(log2(N))
131135
bloq = _permutation_symb()
132136

133-
_, sigma = bloq.call_graph()
137+
_, sigma = bloq.call_graph(keep=lambda b: isinstance(b, And))
134138
assert sigma == {
135-
ArbitraryClifford(n=2): (N + 1) * (13 * logN - 13),
136-
TGate(): (N + 1) * (4 * logN - 4),
139+
And().adjoint(): (N + 1) * (logN - 1),
140+
And(): (N + 1) * (logN - 1),
137141
CNOT(): N * logN + N + 1,
138142
}

qualtran/bloqs/chemistry/df/double_factorization_test.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from qualtran.bloqs.state_preparation.prepare_uniform_superposition import (
2626
PrepareUniformSuperposition,
2727
)
28+
from qualtran.resource_counting import get_cost_value, QECGatesCost
2829
from qualtran.testing import execute_notebook
2930

3031

@@ -71,7 +72,7 @@ def test_compare_cost_to_openfermion():
7172
num_bits_rot_aa_inner=7,
7273
num_bits_rot=num_bits_rot,
7374
)
74-
_, counts = bloq.call_graph()
75+
t_counts = get_cost_value(bloq, QECGatesCost()).total_t_count()
7576
# https://github.com/quantumlib/OpenFermion/issues/839
7677
of_cost = compute_cost(
7778
num_spin_orb, lambd, 1e-3, num_aux, num_eig, num_bits_state_prep, num_bits_rot, 10_000
@@ -83,16 +84,14 @@ def test_compare_cost_to_openfermion():
8384
prog_rot_qrom_diff = 60
8485
missing_toffoli = 4 # need one more toffoli for second application of CZ
8586
swap_cost = 4 * (7 - 4) * num_spin_orb // 2
86-
qual_cost = (
87-
counts[TGate()] - inner_prep_qrom_diff - prog_rot_qrom_diff + missing_toffoli - swap_cost
88-
)
87+
qual_cost = t_counts - inner_prep_qrom_diff - prog_rot_qrom_diff + missing_toffoli - swap_cost
8988
# correct the expected cost by using a different uniform superposition algorithm
9089
# see: https://github.com/quantumlib/Qualtran/issues/611
9190
eta = power_two(num_aux + 1)
9291
cost1a = 4 * 2 * (3 * nl - 3 * eta + 2 * 7 - 9)
9392
prep = PrepareUniformSuperposition(num_aux + 1)
94-
cost1a_mod = prep.call_graph()[1][TGate()]
95-
cost1a_mod += prep.adjoint().call_graph()[1][TGate()]
93+
cost1a_mod = get_cost_value(prep, QECGatesCost()).total_t_count()
94+
cost1a_mod += get_cost_value(prep.adjoint(), QECGatesCost()).total_t_count()
9695
delta_uni_prep = cost1a_mod - cost1a
9796
qual_cost -= delta_uni_prep
9897
inner_refl = num_bits_state_prep + 1

qualtran/bloqs/chemistry/df/prepare_test.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from qualtran.bloqs.state_preparation.prepare_uniform_superposition import (
2828
PrepareUniformSuperposition,
2929
)
30+
from qualtran.resource_counting import get_cost_value, QECGatesCost
3031

3132

3233
def test_prep_inner(bloq_autotester):
@@ -48,13 +49,11 @@ def test_outerprep_t_counts():
4849
outer_prep = OuterPrepareDoubleFactorization(
4950
num_aux, num_bits_state_prep=num_bits_state_prep, num_bits_rot_aa=num_bits_rot_aa
5051
)
51-
_, counts = outer_prep.call_graph()
52-
toff = counts[TGate()] // 4
52+
toff = get_cost_value(outer_prep, QECGatesCost()).total_t_and_ccz_count()['n_ccz']
5353
outer_prep = OuterPrepareDoubleFactorization(
5454
num_aux, num_bits_state_prep=num_bits_state_prep, num_bits_rot_aa=num_bits_rot_aa
5555
).adjoint()
56-
_, counts = outer_prep.call_graph()
57-
toff += counts[TGate()] // 4
56+
toff += get_cost_value(outer_prep, QECGatesCost()).total_t_and_ccz_count()['n_ccz']
5857
# The output size for the QROM for the first state preparation in Eq. (C27)
5958
eta = power_two(num_aux + 1)
6059
nl = num_aux.bit_length()
@@ -65,8 +64,8 @@ def test_outerprep_t_counts():
6564
# correct the expected cost by using a different uniform superposition algorithm
6665
# https://github.com/quantumlib/Qualtran/issues/611
6766
prep = PrepareUniformSuperposition(num_aux + 1)
68-
cost1a_mod = prep.call_graph()[1][TGate()] // 4
69-
cost1a_mod += prep.adjoint().call_graph()[1][TGate()] // 4
67+
cost1a_mod = get_cost_value(prep, QECGatesCost()).total_t_and_ccz_count()['n_ccz']
68+
cost1a_mod += get_cost_value(prep.adjoint(), QECGatesCost()).total_t_and_ccz_count()['n_ccz']
7069
assert cost1a != cost1a_mod
7170
assert toff == cost1a_mod + cost1b + cost1cd
7271

@@ -107,17 +106,15 @@ def test_inner_prepare_t_counts():
107106
num_bits_rot_aa=num_bits_rot_aa,
108107
num_bits_state_prep=num_bits_state_prep,
109108
)
110-
_, counts = in_prep.call_graph()
111-
toff = counts[TGate()] // 4
109+
toff = get_cost_value(in_prep, QECGatesCost()).total_t_and_ccz_count()['n_ccz']
112110
in_prep = InnerPrepareDoubleFactorization(
113111
num_aux=num_aux,
114112
num_spin_orb=num_spin_orb,
115113
num_eig=num_eig,
116114
num_bits_rot_aa=num_bits_rot_aa,
117115
num_bits_state_prep=num_bits_state_prep,
118116
).adjoint()
119-
_, counts = in_prep.call_graph()
120-
toff += counts[TGate()] // 4
117+
toff += get_cost_value(in_prep, QECGatesCost()).total_t_and_ccz_count()['n_ccz']
121118
toff *= 2 # cost is for the two applications of the in-prep, in-prep^
122119
# application of ciruit.
123120
# captured from cost3 in openfermion df.compute_cost

qualtran/bloqs/chemistry/pbc/first_quantization/prepare_nu_test.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from qualtran.bloqs.basic_gates import TGate
1615
from qualtran.bloqs.chemistry.pbc.first_quantization.prepare_nu import PrepareNuState
16+
from qualtran.resource_counting import get_cost_value, QECGatesCost
1717
from qualtran.testing import assert_valid_bloq_decomposition
1818

1919

@@ -37,11 +37,9 @@ def test_prepare_nu_t_counts():
3737
eq_90 = 3 * num_bits_p**2 + 15 * num_bits_p - 7 + 4 * num_bits_m * (num_bits_p + 1)
3838
assert expected_cost == eq_90 + 5
3939
prep = PrepareNuState(num_bits_p, m_param)
40-
_, counts = prep.call_graph()
41-
qual_cost = counts[TGate()]
40+
qual_cost = get_cost_value(prep, QECGatesCost()).total_t_count()
4241
prep = PrepareNuState(num_bits_p, m_param).adjoint()
43-
_, counts = prep.call_graph()
44-
qual_cost += counts[TGate()]
42+
qual_cost += get_cost_value(prep, QECGatesCost()).total_t_count()
4543
qual_cost //= 4
4644
comp_diff = 1
4745
assert qual_cost == expected_cost - comp_diff

qualtran/bloqs/chemistry/pbc/first_quantization/prepare_uv_test.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
import numpy as np
1616

17-
from qualtran.bloqs.basic_gates import TGate
1817
from qualtran.bloqs.chemistry.pbc.first_quantization.prepare_uv import (
1918
_prepare_uv,
2019
PrepareUVFirstQuantization,
2120
)
21+
from qualtran.resource_counting import get_cost_value, QECGatesCost
2222

2323

2424
def test_prepare_uv(bloq_autotester):
@@ -41,13 +41,11 @@ def test_prepare_uv_t_counts():
4141
prep = PrepareUVFirstQuantization(
4242
num_bits_p, eta, num_atoms, m_param, lambda_zeta, num_bits_nuc_pos
4343
)
44-
_, counts = prep.call_graph()
45-
qual_cost = counts[TGate()]
44+
qual_cost = get_cost_value(prep, QECGatesCost()).total_t_count()
4645
prep = PrepareUVFirstQuantization(
4746
num_bits_p, eta, num_atoms, m_param, lambda_zeta, num_bits_nuc_pos
4847
).adjoint()
49-
_, counts = prep.call_graph()
50-
qual_cost += counts[TGate()]
48+
qual_cost += get_cost_value(prep, QECGatesCost()).total_t_count()
5149
qual_cost //= 4
5250
comp_diff = 1
5351
assert qual_cost == expected_cost - comp_diff

qualtran/bloqs/chemistry/pbc/first_quantization/projectile/prepare_nu_test.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from qualtran.bloqs.basic_gates import TGate
1615
from qualtran.bloqs.chemistry.pbc.first_quantization.projectile.prepare_nu import (
1716
_prep_mu_proj,
1817
_prep_nu_proj,
1918
PrepareNuStateWithProj,
2019
)
20+
from qualtran.resource_counting import get_cost_value, QECGatesCost
2121

2222

2323
def test_prepare_num(bloq_autotester):
@@ -44,11 +44,9 @@ def test_prepare_nu_with_proj_t_counts():
4444
)
4545
assert expected_cost == eq_c6 + 5
4646
prep = PrepareNuStateWithProj(num_bits_p, num_bits_n, m_param)
47-
_, counts = prep.call_graph()
48-
qual_cost = counts[TGate()]
47+
qual_cost = get_cost_value(prep, QECGatesCost()).total_t_count()
4948
prep = PrepareNuStateWithProj(num_bits_p, num_bits_n, m_param).adjoint()
50-
_, counts = prep.call_graph()
51-
qual_cost += counts[TGate()]
49+
qual_cost += get_cost_value(prep, QECGatesCost()).total_t_count()
5250
qual_cost //= 4
5351
comp_diff = 1
5452
assert qual_cost == expected_cost - comp_diff

qualtran/bloqs/chemistry/pbc/first_quantization/projectile/prepare_uv_test.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
import numpy as np
1616

17-
from qualtran.bloqs.basic_gates import TGate
1817
from qualtran.bloqs.chemistry.pbc.first_quantization.projectile.prepare_uv import (
1918
_prep_uv_proj,
2019
PrepareUVFirstQuantizationWithProj,
2120
)
21+
from qualtran.resource_counting import get_cost_value, QECGatesCost
2222

2323

2424
def test_prep_uv_proj(bloq_autotester):
@@ -42,13 +42,11 @@ def test_prepare_uv_t_counts():
4242
prep = PrepareUVFirstQuantizationWithProj(
4343
num_bits_p, num_bits_n, eta, num_atoms, m_param, lambda_zeta, num_bits_nuc_pos
4444
)
45-
_, counts = prep.call_graph()
46-
qual_cost = counts[TGate()]
45+
qual_cost = get_cost_value(prep, QECGatesCost()).total_t_count()
4746
prep = PrepareUVFirstQuantizationWithProj(
4847
num_bits_p, num_bits_n, eta, num_atoms, m_param, lambda_zeta, num_bits_nuc_pos
4948
).adjoint()
50-
_, counts = prep.call_graph()
51-
qual_cost += counts[TGate()]
49+
qual_cost += get_cost_value(prep, QECGatesCost()).total_t_count()
5250
qual_cost //= 4
5351
comp_diff = 1
5452
assert qual_cost == expected_cost - comp_diff

qualtran/bloqs/chemistry/pbc/first_quantization/projectile/select_and_prepare_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
PrepareFirstQuantizationWithProj,
2323
SelectFirstQuantizationWithProj,
2424
)
25+
from qualtran.resource_counting import get_cost_value, QECGatesCost
2526
from qualtran.testing import assert_valid_bloq_decomposition, execute_notebook
2627

2728

@@ -45,13 +46,12 @@ def test_select_t_costs():
4546
num_atoms = 10
4647
lambda_zeta = 10
4748
num_bits_nuc_pos = 41
48-
cost = 0
4949

5050
sel_first_quant = SelectFirstQuantizationWithProj(
5151
num_bits_p, num_bits_n, eta, num_atoms, lambda_zeta, num_bits_nuc_pos=num_bits_nuc_pos
5252
)
5353
assert_valid_bloq_decomposition(sel_first_quant)
54-
cost += sel_first_quant.call_graph()[1][TGate()]
54+
cost = get_cost_value(sel_first_quant, QECGatesCost()).total_t_count()
5555

5656
# Swaps
5757
expected_cost = 7 * (12 * eta * num_bits_p + 6 * num_bits_n) + 4 * (4 * eta - 6) #

qualtran/bloqs/chemistry/sparse/select_bloq_test.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from qualtran.bloqs.basic_gates import TGate
1615
from qualtran.bloqs.chemistry.sparse.select_bloq import _sel_sparse
1716

1817

@@ -22,6 +21,6 @@ def test_prep_inner(bloq_autotester):
2221

2322
def test_decompose_bloq_counts():
2423
sel = _sel_sparse()
25-
cost_decomp = sel.decompose_bloq().call_graph()[1][TGate()]
26-
cost_call = sel.call_graph()[1][TGate()]
24+
cost_decomp = sel.decompose_bloq().call_graph()[1]
25+
cost_call = sel.call_graph()[1]
2726
assert cost_call == cost_decomp

0 commit comments

Comments
 (0)