def qsvt_solver(
mat_raw_scr,
b_raw,
poly_degree,
be_method="banded",
cheb_approx_type="numpy_interpolated",
preferences=Preferences(),
constraints=Constraints(),
):
SCALE = 0.5
b_norm = np.linalg.norm(b_raw) # b normalization
b_normalized = b_raw / b_norm
# Define block encoding
if be_method == "pauli":
data_size, block_size, be_scaling_factor, be_qfunc = get_pauli_be(
mat_raw_scr, PAULI_TRIM_REL_TOL
)
print(
f"Pauli block encoding with block size {block_size} and scaling factor {be_scaling_factor}"
)
elif be_method == "banded":
data_size, block_size, be_scaling_factor, be_qfunc = get_banded_diags_be(
mat_raw_scr
)
print(
f"Banded diagonal block encoding with block size {block_size} and scaling factor {be_scaling_factor}"
)
class BlockEncodedState(QStruct):
data: QNum[data_size]
block: QNum[block_size]
# Get SVD range
w_min, w_max = get_svd_range(mat_raw_scr / be_scaling_factor)
# Get Chebyshev polynomial and the corresponding QSVT angles
pcoefs, poly_scale = get_cheb_coeff(
w_min, poly_degree, w_max, scale=SCALE, method=cheb_approx_type, epsilon=0.01
)
inv_phases = qsvt_phases(pcoefs, tol=0.001)
# Define QSVT projector
@qfunc
def projector(be: BlockEncodedState, res: QBit):
res ^= be.block == 0
@qfunc
def main(
qsvt_aux: Output[QBit],
data: Output[QNum[data_size]],
block: Output[QNum[block_size]],
):
allocate(qsvt_aux)
allocate(block)
prepare_amplitudes(b_normalized.tolist(), 0, data)
be_state = BlockEncodedState()
within_apply(
lambda: bind([data, block], be_state),
lambda: qsvt_inversion(
inv_phases,
lambda aux: projector(be_state, aux),
lambda: be_qfunc(be_state.block, be_state.data),
qsvt_aux,
),
)
start_time_syn = time.time()
qprog = synthesize(main, preferences=preferences, constraints=constraints)
print("time to syn:", time.time() - start_time_syn)
execution_preferences = ExecutionPreferences(
num_shots=1,
backend_preferences=ClassiqBackendPreferences(
backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR
),
)
start_time_exe = time.time()
with ExecutionSession(qprog, execution_preferences) as es:
es.set_measured_state_filter("block", lambda state: state == 0.0)
es.set_measured_state_filter("qsvt_aux", lambda state: state == 0.0)
results = es.sample()
print("time to exe:", time.time() - start_time_exe)
resulting_state = get_projected_state_vector(results, "data")
normalization_factor = (be_scaling_factor * poly_scale) / b_norm
return resulting_state / normalization_factor, qprog