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

Cleanup PR #69

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![pylint](https://img.shields.io/badge/PyLint-9.03-yellow?logo=python&logoColor=white)
![pylint](https://img.shields.io/badge/PyLint-9.01-yellow?logo=python&logoColor=white)

# Quantum Computing Application Specifications

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pyLIQTR == 1.3.0
pyLIQTR == 1.3.4
matplotlib
networkx
numpy
Expand Down
26 changes: 14 additions & 12 deletions scripts/AP-RE.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,24 +95,28 @@ def grab_arguments() -> Namespace:
)
parser.add_argument(
'-BR',
'--bits_rot',
type=int,
help='The number of precision bits to use for the rotation angles output by the QROM',
default=7
)
parser.add_argument(
'-DF',
'--df_error',
type=float,
help='The threshold used to throw out factors from the double factorization.',
default=1e-3
)
parser.add_argument(
'-SF',
'--sf_error',
type=float,
help='The threshold used to throw out factors from the first eigendecomposition',
default=1e-8
)
parser.add_argument(
'-EE',
'--energy_error',
type=float,
help='The allowable error in phase estimation energy',
default=1e-3
Expand Down Expand Up @@ -148,7 +152,7 @@ def df_subprocess(
outdir: str,
fname: str,
mol_hams: list[InteractionOperator],
br:int,
bits_rot:int,
df_error_threshold:float,
sf_error_threshold:float,
energy_error:float,
Expand All @@ -157,13 +161,14 @@ def df_subprocess(
gate_precision:float | None,
use_analytical: bool = True
):
for ham in mol_hams:
for idx, ham in enumerate(mol_hams):
new_name = f'{fname.split(".xyz")[0]}_{idx}'
gen_df_qpe(
mol_ham=ham,
use_analytical=use_analytical,
outdir=outdir,
fname=fname,
br=br,
fname=new_name,
bits_rot=bits_rot,
df_error_threshold=df_error_threshold,
sf_error_threshold=sf_error_threshold,
energy_error=energy_error,
Expand Down Expand Up @@ -209,7 +214,6 @@ def trotter_subprocess(
outdir = args.dir
if not os.path.exists(outdir):
os.makedirs(outdir)

fname = args.fname
use_df = args.use_df
bits_precision = args.bits_prec
Expand All @@ -219,14 +223,12 @@ def trotter_subprocess(
trotter_order = args.trotter_order
trotter_steps = args.trotter_steps

br = args.BR
sf_error = args.SF
df_error = args.DF
energy_error = args.EE
bits_rot = args.bits_rot
sf_error = args.sf_error
df_error = args.df_error
energy_error = args.energy_error
gate_synth_accuracy = args.gate_synth
print("going to gen mol hams")
mol_hams = gen_mol_hams(fname, basis, pathway, active_space_reduc)
print('now doing it')
fname = f'/{fname.split('/')[-1]}'
if not use_df:
trotter_subprocess(
Expand All @@ -243,7 +245,7 @@ def trotter_subprocess(
outdir=outdir,
fname=fname,
mol_hams=mol_hams,
br=br,
bits_rot=bits_rot,
df_error_threshold=df_error,
sf_error_threshold=sf_error,
energy_error=energy_error,
Expand Down
3 changes: 2 additions & 1 deletion scripts/DickeModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def main(args):
trotter_order_dicke = args.trotter_order
trotter_steps_dicke = args.trotter_steps

name = args.name
name = f'{args.name}_{n_s}_ns_{n_b}_nb'
directory = args.directory
value = args.value
repetitions = args.repetitions
Expand Down Expand Up @@ -76,6 +76,7 @@ def main(args):
nsteps=trotter_steps_dicke,
gsee_args=args_dicke,
init_state=init_state_dicke,
use_analytical=True,
precision_order=1, #actual precision bits accounted as scaling factors in the resource estimate
phase_offset=dicke_phase_offset,
bits_precision=bits_precision_dicke,
Expand Down
1 change: 1 addition & 0 deletions scripts/QCD-RE.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def main():
evolution_time=evolution_time,
energy_precision=energy_precision,
outdir=outdir,
use_analytical=True,
hamiltonian_name=hamiltonian_name,
nsteps=num_steps,
trotter_order=trotter_order,
Expand Down
74 changes: 46 additions & 28 deletions src/qca/utils/algo_utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import os
import time
import random
from typing import Union
import numpy as np
import networkx as nx

import cirq
from cirq import Circuit
from cirq.contrib import qasm_import

Expand Down Expand Up @@ -72,6 +72,7 @@ def estimate_qsp(
energy_precision:float,
outdir:str,
is_extrapolated:bool=False,
use_analytical:bool=False,
metadata: QSPMetaData | None=None,
hamiltonian_name:str='hamiltonian',
write_circuits:bool=False,
Expand Down Expand Up @@ -102,6 +103,7 @@ def estimate_qsp(
algo_name='QSP',
fname=hamiltonian_name,
is_extrapolated=is_extrapolated,
use_analytical=use_analytical,
nsteps=nsteps,
metadata=metadata,
write_circuits=write_circuits,
Expand All @@ -117,14 +119,15 @@ def estimate_trotter(
evolution_time: float,
energy_precision: float,
outdir:str,
use_analytical:bool=False,
is_extrapolated: bool=True,
trotter_order: int = 2,
metadata: TrotterMetaData | None=None,
hamiltonian_name:str='hamiltonian',
write_circuits:bool=False,
nsteps:int|None=None,
include_nested_resources:bool=True
) -> Circuit:
) -> Union[None, Circuit]:

if not os.path.exists(outdir):
os.makedirs(outdir)
Expand Down Expand Up @@ -161,35 +164,48 @@ def estimate_trotter(
qasm_str_trotter = open_fermion_to_qasm(count_qubits(openfermion_hamiltonian), trotter_circuit_of)
trotter_circuit_qasm = qasm_import.circuit_from_qasm(qasm_str_trotter)

t0 = time.perf_counter()
cpt_trotter = clifford_plus_t_direct_transform(circuit=trotter_circuit_qasm, gate_precision=gate_synth_accuracy)
t1 = time.perf_counter()
elapsed = t1-t0
print(f'Time to generate a clifford + T circuit from trotter circuit: {elapsed} seconds')

if write_circuits:
outfile_qasm_trotter = f'{outdir}Trotter_Unitary.qasm'
write_qasm(
circuit=trotter_circuit_qasm,
fname=outfile_qasm_trotter
)
outfile_qasm_cpt = f'{outdir}Trotter_Unitary.cpt.qasm'
write_qasm(
circuit=cpt_trotter,
fname=outfile_qasm_cpt
if use_analytical:
grab_circuit_resources(
trotter_circuit_qasm,
outdir,
'Trotter',
fname=hamiltonian_name,
is_extrapolated=True,
use_analytical=True,
nsteps=nsteps,
metadata=metadata,
gate_synth_accuracy=gate_synth_accuracy
)
return None
else:
t0 = time.perf_counter()
cpt_trotter = clifford_plus_t_direct_transform(circuit=trotter_circuit_qasm, gate_precision=gate_synth_accuracy)
t1 = time.perf_counter()
elapsed = t1-t0
print(f'Time to generate a clifford + T circuit from trotter circuit: {elapsed} seconds')

logical_re = estimate_cpt_resources(
cpt_circuit=cpt_trotter,
is_extrapolated=is_extrapolated,
algo_name= 'TrotterStep',
nsteps=nsteps,
include_nested_resources=include_nested_resources
)
outfile = f'{outdir}{hamiltonian_name}_re.json'
if write_circuits:
outfile_qasm_trotter = f'{outdir}Trotter_Unitary.qasm'
write_qasm(
circuit=trotter_circuit_qasm,
fname=outfile_qasm_trotter
)
outfile_qasm_cpt = f'{outdir}Trotter_Unitary.cpt.qasm'
write_qasm(
circuit=cpt_trotter,
fname=outfile_qasm_cpt
)

gen_json(logical_re, outfile, metadata )
return cpt_trotter
logical_re = estimate_cpt_resources(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here, I did some testing with using Trotter for Dynamics, if use_analytical = False, but given both value and reps, the value_per_t_gate is recorded as null. Is this the correct usage?

cpt_circuit=cpt_trotter,
is_extrapolated=is_extrapolated,
algo_name= 'TrotterStep',
nsteps=nsteps,
include_nested_resources=include_nested_resources
)
outfile = f'{outdir}{hamiltonian_name}_re.json'
gen_json(logical_re, outfile, metadata )
return cpt_trotter

def gsee_resource_estimation(
outdir:str,
Expand All @@ -200,6 +216,7 @@ def gsee_resource_estimation(
bits_precision:int,
phase_offset:float,
is_extrapolated:bool=False,
use_analytical:bool=False,
metadata:GSEEMetaData | None =None,
circuit_name:str='Hamiltonian',
include_nested_resources:bool=False,
Expand Down Expand Up @@ -231,6 +248,7 @@ def gsee_resource_estimation(
algo_name='GSEE',
fname=circuit_name,
is_extrapolated=is_extrapolated,
use_analytical=use_analytical,
nsteps=nsteps,
bits_precision=bits_precision,
metadata=metadata,
Expand Down
34 changes: 23 additions & 11 deletions src/qca/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@
from dataclasses import dataclass, field, asdict

import pandas as pd

import logging as log
import matplotlib.pyplot as plt

import cirq

from pyLIQTR.utils.printing import openqasm
from pyLIQTR.utils.utils import count_T_gates
import pyLIQTR.utils.resource_analysis as pyLRA
import pyLIQTR.utils.global_ancilla_manager as gam
from pyLIQTR.utils.resource_analysis import estimate_resources
from pyLIQTR.utils.circuit_decomposition import circuit_decompose_multi
from pyLIQTR.gate_decomp.cirq_transforms import clifford_plus_t_direct_transform


@dataclass
class EstimateMetaData:
id: str
Expand All @@ -28,6 +29,7 @@ class EstimateMetaData:
is_extrapolated: bool=field(default=False, kw_only=True)
gate_synth_accuracy: int | float = field(default=10,kw_only=True)
value_per_circuit: float | None=field(default=None, kw_only=True)
Copy link
Collaborator

Choose a reason for hiding this comment

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

are we keeping this as value_per_circuit, or just changing to value?

value_per_t_gate: float | None=field(default=None,kw_only=True)
repetitions_per_application: int | None=field(default=None, kw_only=True)

@dataclass
Expand Down Expand Up @@ -390,24 +392,34 @@ def grab_circuit_resources(circuit: cirq.AbstractCircuit,
write_circuits=write_circuits,
)
else:
logical_estimates = estimate_resources(
circuit_element=circuit,
rotation_gate_precision=gate_synth_accuracy
)
if gate_synth_accuracy > 1:
log.warning('gate_synth_accuracy is greater than 1. Converting it to 1e-{gate_synth_accuracy}')
gate_synth_accuracy = pow(10, -gate_synth_accuracy)

logical_estimates = pyLRA.estimate_resources(
circuit,
rotation_gate_precision=gate_synth_accuracy,
profile=False
)
estimates = {'Logical_Abstract':{
'num_qubits': logical_estimates['LogicalQubits'],
't_count': logical_estimates['T'],
'clifford_count': logical_estimates['Clifford'],
'gate_count': logical_estimates['T'] + logical_estimates['Clifford'],
'subcircuit_occurences': 1,
'subcircuit_info': {}
}}
header = estimates['Logical_Abstract']
if is_extrapolated:
for resource in header:
header[resource] = scale_resource(header[resource], nsteps, bits_precision)
header['subcircuit_occurences'] = 1
header['num_qubits'] = logical_estimates['LogicalQubits']

header['subcircuit_info'] = {}

#calculate and insert value_per_t_gate
if metadata != None:
estimates['value_per_t_gate'] = 0
header = estimates['Logical_Abstract']
if (metadata.value_per_circuit != None) and (metadata.repetitions_per_application != None):
estimates['value_per_t_gate'] = metadata.value_per_circuit/(estimates.get('Logical_Abstract').get('t_count') * metadata.repetitions_per_application)
metadata.value_per_t_gate = metadata.value_per_circuit/header['t_count']

outfile = f'{outdir}{fname}_re.json'
gen_json(estimates, outfile, metadata)