diff --git a/data/RuCl_test_input.csv b/data/RuCl_test_input.csv index 0e52209..0d8cda9 100644 --- a/data/RuCl_test_input.csv +++ b/data/RuCl_test_input.csv @@ -1,7 +1,7 @@ -reference, method, J1, K1, Gam1, Gam_prime1, J2, K2, J3, K3 -"Winter et al. PRB","Ab initio (DFT + exact diag.)", -1.7,-6.7,6.6,-0.9,0,0,2.7,0 -"Winter et al. NC","Ab initio-inspired (INS fit)", -0.5, -5.0, 2.5,0,0,0,0.5,0 -"Wu et al.","THz spectroscopy fit", -0.35,-2.8, 2.4,0,0,0,0.34,0 +reference,method,J1,K1,Gam1,Gam_prime1,J2,K2,J3,K3 +"Winter et al. PRB","Ab initio (DFT + exact diag.)",-1.7,-6.7,6.6,-0.9,0,0,2.7,0 +"Winter et al. NC","Ab initio-inspired (INS fit)",-0.5,-5.0,2.5,0,0,0,0.5,0 +"Wu et al.","THz spectroscopy fit",-0.35,-2.8, 2.4,0,0,0,0.34,0 "Cookmeyer and Moore","Magnon thermal Hall (sign)",-0.5,-5.0,2.5,0,0,0,0.1125,0 "Kim and Kee","DFT + t=U expansion",-1.53,-6.55,5.25,-0.95,0,0,0,0 "Suzuki and Suga","Magnetic specific heat",-1.53,-24.4,5.25,-0.95,0,0,0,0 diff --git a/notebooks/RuClExample.ipynb b/notebooks/RuClExample.ipynb index a7890be..d4870d6 100644 --- a/notebooks/RuClExample.ipynb +++ b/notebooks/RuClExample.ipynb @@ -63,7 +63,7 @@ "from pyLIQTR.gate_decomp.cirq_transforms import clifford_plus_t_direct_transform\n", "\n", "\n", - "from qca.utils.utils import plot_histogram, gen_resource_estimate, re_as_json, QSPMetaData, TrotterMetaData, circuit_estimate\n", + "from qca.utils.utils import plot_histogram, gen_resource_estimate, re_as_json, QSPMetaData, TrotterMetaData,GSEEMetaData, circuit_estimate\n", "from qca.utils.algo_utils import estimate_qsp, estimate_trotter, gsee_resource_estimation\n", "from qca.utils.hamiltonian_utils import flatten_nx_graph, assign_hexagon_labels, pyliqtr_hamiltonian_to_openfermion_qubit_operator" ] @@ -780,11 +780,14 @@ " H.append((string_z, weight_z))\n", " return H\n", "\n", - "#using normalized time s = t_current / t_total to allow for more variation of total time\n", - "def generate_rucl_hamiltonian(lattice_size, data_series, s=0, field_x=lambda s: 0, field_y=lambda s: 0, field_z=lambda s: 0):\n", + "def build_rucl_graph(lattice_size) -> nx.graph:\n", " graph = hexagonal_lattice_graph(lattice_size,lattice_size)\n", " assign_hexagon_labels_rucl(graph)\n", " graph = flatten_nx_graph(graph)\n", + " return graph\n", + "\n", + "#using normalized time s = t_current / t_total to allow for more variation of total time\n", + "def generate_rucl_hamiltonian(graph, data_series, s=0, field_x=lambda s: 0, field_y=lambda s: 0, field_z=lambda s: 0):\n", " H_constant = nx_rucl_terms(graph, data_series)\n", " H_time_varied = generate_time_varying_terms(graph, s, x=field_x, y = field_y, z = field_z)\n", " H = H_constant + H_time_varied\n", @@ -822,7 +825,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 6, "id": "2a1e7584-5f7c-458b-92db-d73bafb10a6b", "metadata": {}, "outputs": [ @@ -960,16 +963,16 @@ }, "outputs": [], "source": [ + "#defining precision required for the trotterized circuit\n", + "lattice_size = 32\n", + "evolution_time=1000\n", + "trotter_order = 2\n", + "energy_precision = 1e-3\n", + "extrapolated=True\n", + "\n", "#Commenting out range, to avoid long runtimes. This still takes ~20-30 minutes as written\n", "for i in [13]:\n", "#for i in range(19):\n", - " #defining precision required for the trotterized circuit\n", - " lattice_size = 32\n", - " evolution_time=1000\n", - " trotter_order = 2\n", - " energy_precision = 1e-3\n", - " extrapolated=True\n", - "\n", "\n", " figdir=\"Trotter/Figures/\"\n", " if not os.path.exists(figdir):\n", @@ -978,9 +981,8 @@ " if not os.path.exists(widthdir):\n", " os.makedirs(widthdir)\n", "\n", - "\n", - "\n", - " H_rucl = generate_rucl_hamiltonian(lattice_size, df_rucl.iloc[i], field_x=lambda s: 1/sqrt(6), field_y=lambda s: 1/sqrt(6), field_z=lambda s: -2/sqrt(6))\n", + " graph = build_rucl_graph(lattice_size)\n", + " H_rucl = generate_rucl_hamiltonian(graph, df_rucl.iloc[i], field_x=lambda s: 1/sqrt(6), field_y=lambda s: 1/sqrt(6), field_z=lambda s: -2/sqrt(6))\n", " H_rucl_pyliqtr = pyH(H_rucl)\n", " openfermion_hamiltonian_rucl = pyliqtr_hamiltonian_to_openfermion_qubit_operator(H_rucl_pyliqtr)\n", " \n", @@ -1011,7 +1013,7 @@ " outdir='Trotter/RuCl_circuits/',\n", " metadata=trotter_metadata,\n", " is_extrapolated=extrapolated,\n", - " hamiltonian_name=f'rucl_trotter_{i}_test',\n", + " hamiltonian_name=f'rucl_trotter_{i}_test_lattice_size_{lattice_size}',\n", " write_circuits=True\n", " )\n", " t1 = time.perf_counter()\n", @@ -1020,7 +1022,7 @@ " \n", " plot_histogram(\n", " cpt_trotter_rucl,\n", - " f'trotter RuCl, row{i}',\n", + " f'trotter RuCl, row{i}, lattice_size_{lattice_size}',\n", " figdir,\n", " widthdir,\n", " 0\n", @@ -1086,7 +1088,8 @@ " if not os.path.exists(widthdir):\n", " os.makedirs(widthdir)\n", "\n", - " H_rucl = generate_rucl_hamiltonian(lattice_size, df_rucl.iloc[i], field_x=lambda s: 1/sqrt(6), field_y=lambda s: 1/sqrt(6), field_z=lambda s: -2/sqrt(6))\n", + " graph = build_rucl_graph(lattice_size)\n", + " H_rucl = generate_rucl_hamiltonian(graph, df_rucl.iloc[i], field_x=lambda s: 1/sqrt(6), field_y=lambda s: 1/sqrt(6), field_z=lambda s: -2/sqrt(6))\n", " H_rucl_pyliqtr = pyH(H_rucl)\n", " \n", " rucl_name = f'Rucl_row_{i}_qsp'\n", @@ -1113,7 +1116,7 @@ " nsteps=nsteps,\n", " energy_precision=energy_precision,\n", " outdir='QSP/RuCl_circuits/',\n", - " hamiltonian_name=f'rucl_qsp_{i}_test',\n", + " hamiltonian_name=f'rucl_qsp_{i}_test_lattice_size_{lattice_size}',\n", " metadata=qsp_metadata,\n", " write_circuits=True\n", " )\n", @@ -1318,17 +1321,17 @@ "id": "e1dd65bb", "metadata": {}, "source": [ - "First, we use classical methods such as DMRG for initialization. Since this cannot be incorporated into the notebook, we assume it has been prepared." + "First, we use classical methods such as DMRG for initialization. Since this cannot be incorporated into the notebook, we assume it has been prepared. Instead, we set the size of the initial state equal to the number of nodes in the Hexgonal Lattice Graph." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "b2f30269", "metadata": {}, "outputs": [], "source": [ - "#Assume the initial state for GSEE has been prepared through DMRG." + "#Assume the initial state for GSEE has been prepared through DMRG.\n" ] }, { @@ -1347,7 +1350,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 6, "id": "0629c6f2", "metadata": {}, "outputs": [], @@ -1355,7 +1358,8 @@ "#Generating Hamiltonian with zero external magnetic field. (H_field = 0)\n", "#This is the way that it is prepared using QCA which we will see later in the Trotterized subprocess\n", "\n", - "H_rucl_no_field = generate_rucl_hamiltonian(32, df_rucl.iloc[0], field_x=lambda s: 0, field_y=lambda s: 0, field_z=lambda s: 0) ###Note df_rucl.iloc[i] used information from the table\n", + "graph = build_rucl_graph(32)\n", + "H_rucl_no_field = generate_rucl_hamiltonian(graph, df_rucl.iloc[0], field_x=lambda s: 0, field_y=lambda s: 0, field_z=lambda s: 0) ###Note df_rucl.iloc[i] used information from the table\n", "H_rucl_no_field_pyliqtr = pyH(H_rucl_no_field)\n", "H_rucl_no_field_qubit_op = pyliqtr_hamiltonian_to_openfermion_qubit_operator(H_rucl_no_field_pyliqtr)" ] @@ -1376,13 +1380,14 @@ "outputs": [], "source": [ "###Trotterized Subprocess\n", - "for i in [13]:\n", - " bits_precision = 10 \n", - " trotter_order = 2\n", - " trotter_steps = 1\n", - " lattice_size = 32\n", + "bits_precision = 10 \n", + "trotter_order = 2\n", + "trotter_steps = 1\n", + "lattice_size = 32\n", "\n", - " H_rucl_no_field = generate_rucl_hamiltonian(lattice_size, df_rucl.iloc[i], field_x=lambda s: 0, field_y=lambda s: 0, field_z=lambda s: 0)\n", + "for i in [13]:\n", + " graph = build_rucl_graph(lattice_size)\n", + " H_rucl_no_field = generate_rucl_hamiltonian(graph, df_rucl.iloc[i], field_x=lambda s: 0, field_y=lambda s: 0, field_z=lambda s: 0)\n", " H_rucl_no_field_pyliqtr = pyH(H_rucl_no_field)\n", " H_rucl_no_field_qubit_op = pyliqtr_hamiltonian_to_openfermion_qubit_operator(H_rucl_no_field_pyliqtr)\n", "\n", @@ -1393,6 +1398,19 @@ " t = 2*np.pi/omega\n", " phase_offset = E_max*t\n", "\n", + " rucl_metadata = GSEEMetaData(\n", + " id = 2000,\n", + " name = rucl_name,\n", + " category='scientific',\n", + " size=f'{lattice_size}',\n", + " task='Ground State Energy Estimation',\n", + " evolution_time=t,\n", + " is_extrapolated=True,\n", + " trotter_order=trotter_order,\n", + " bits_precision=bits_precision,\n", + " nsteps=trotter_steps,\n", + " )\n", + "\n", " gsee_args = {\n", " 'trotterize' : True,\n", " 'mol_ham' : H_rucl_no_field_qubit_op,\n", @@ -1400,7 +1418,9 @@ " 'trot_ord' : trotter_order,\n", " 'trot_num' : trotter_steps\n", " }\n", - " init_state = [0] * lattice_size * lattice_size * 2 #Assume DMRG is used in initial state prep\n", + "\n", + " #Initial State\n", + " init_state = [0] * len(graph.nodes) #Assume DMRG is used in initial state prep\n", "\n", " print(f'Estimating RuCl Ham row {i} of size {lattice_size}')\n", " t0 = time.perf_counter()\n", @@ -1412,8 +1432,9 @@ " precision_order=1,\n", " bits_precision=bits_precision,\n", " phase_offset=phase_offset,\n", - " circuit_name=f'H_rucl_no_field',\n", - " write_circuits=True\n", + " circuit_name=f'gsee_rucl_size_{lattice_size}_row_{i}',\n", + " metadata=rucl_metadata,\n", + " write_circuits=False\n", " )\n", " t1 = time.perf_counter()\n", " print(f'Time to estimate RuCl Ham with no external field: {t1-t0}')" @@ -1449,7 +1470,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3.11.10" } }, "nbformat": 4, diff --git a/notebooks/pdfs/RuClExample.pdf b/notebooks/pdfs/RuClExample.pdf index be06ce2..ad1f810 100644 Binary files a/notebooks/pdfs/RuClExample.pdf and b/notebooks/pdfs/RuClExample.pdf differ diff --git a/requirements.txt b/requirements.txt index 123a2a5..816808b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -pyLIQTR == 1.3.0 +pyLIQTR == 1.3.4 matplotlib networkx numpy diff --git a/scripts/RuCl-RE.py b/scripts/RuCl-RE.py index a36dd5e..42c30c3 100644 --- a/scripts/RuCl-RE.py +++ b/scripts/RuCl-RE.py @@ -149,10 +149,16 @@ def assign_hexagon_labels_rucl(graph): if (r-1, c+2) in graph and (r + c)%2 == 1: graph.add_edge(n, (r-1, c+2), label= 'Y3') -def generate_rucl_hamiltonian(lattice_size, data_series, s=0, field_x=lambda s: 0, field_y=lambda s: 0, field_z=lambda s: 0): + + +def build_rucl_graph(lattice_size): graph = hexagonal_lattice_graph(lattice_size,lattice_size) assign_hexagon_labels_rucl(graph) graph = flatten_nx_graph(graph) + return graph + + +def generate_rucl_hamiltonian(graph, data_series, s=0, field_x=lambda s: 0, field_y=lambda s: 0, field_z=lambda s: 0): H_constant = nx_rucl_terms(graph, data_series) H_time_varied = generate_time_varying_terms(graph, s, x=field_x, y = field_y, z = field_z) H = H_constant + H_time_varied @@ -200,12 +206,20 @@ def gen_args(): ) parser.add_argument( - '-D', - '--directory', + '-I', + '--input_dir', type=str, - help='Directoty with pathway datafiles.', + help='Input directory containing datafiles. (Ex: RuCl_input.csv file)', default='../data/' ) + + parser.add_argument( + '-O', + '--output_dir', + type=str, + help="Parent directory for resource-estimation outputs (default: RuCl_RE/)", + default = "RuCl_RE/" + ) return parser.parse_args() def generate_rucl_dynamics_re( @@ -223,8 +237,9 @@ def generate_rucl_dynamics_re( if not os.path.exists(outdir): os.makedirs(outdir) for rucl_idx in range(len(df_rucl)): + graph = build_rucl_graph(lattice_size) H_rucl = generate_rucl_hamiltonian( - lattice_size, + graph, df_rucl.iloc[rucl_idx], field_x = lambda s: 1/sqrt(6)/2, field_y = lambda s: 1/sqrt(6)/2, @@ -255,7 +270,7 @@ def generate_rucl_dynamics_re( metadata=trotter_metadata, outdir=outdir, trotter_order=trotter_order, - hamiltonian_name=f'trotter_rucl_size_{lattice_size}_row_{rucl_idx}', + hamiltonian_name=f'Dynamics_trotter_rucl_size_{lattice_size}_row_{rucl_idx}', nsteps=nsteps, is_extrapolated=is_extrapolated ) @@ -279,12 +294,11 @@ def generate_rucl_dynamics_re( energy_precision=energy_precision, metadata=qsp_metadata, outdir=outdir, - hamiltonian_name=f'qsp_rucl_size_{lattice_size}_row_{rucl_idx}', + hamiltonian_name=f'Dynamics_qsp_rucl_size_{lattice_size}_row_{rucl_idx}', write_circuits=False ) def generate_rucl_gsee_re( - energy_precision:float, bits_precision:float, lattice_size: int, evolution_time:float, @@ -295,13 +309,14 @@ def generate_rucl_gsee_re( gate_synth_accuracy = 10 trotter_order = 2 is_extrapolated=True - init_state = [0] * lattice_size * lattice_size * 2 #TODO: use DMRG as initial state prep + if not os.path.exists(outdir): os.makedirs(outdir) for rucl_idx in range(len(df_rucl)): + graph = build_rucl_graph(lattice_size) H_rucl_no_fields = generate_rucl_hamiltonian( - lattice_size, + graph, df_rucl.iloc[rucl_idx], field_x = lambda s: 0, field_y = lambda s: 0, @@ -310,6 +325,7 @@ def generate_rucl_gsee_re( H_rucl__no_fields_pyliqtr = pyH(H_rucl_no_fields) openfermion_hamiltonian_rucl_no_fields = pyliqtr_hamiltonian_to_openfermion_qubit_operator(H_rucl__no_fields_pyliqtr) + init_state = [0] * len(graph.nodes) E_min = -len(openfermion_hamiltonian_rucl_no_fields.terms) E_max = 0 @@ -328,7 +344,7 @@ def generate_rucl_gsee_re( evolution_time = evolution_time, nsteps = nsteps, trotter_order = trotter_order, - energy_precision=energy_precision, + bits_precision = bits_precision, is_extrapolated=is_extrapolated, ) @@ -341,25 +357,26 @@ def generate_rucl_gsee_re( 'trot_num' : nsteps } gsee_resource_estimation( - outdir='GSEE/RuCl_GSEE/No_Field/', + outdir=outdir, nsteps=nsteps, gsee_args=gsee_args, init_state=init_state, precision_order=1, bits_precision=bits_precision, phase_offset=phase_offset, - metadata = gsee_metadata + metadata = gsee_metadata, + circuit_name = f'GSEE_rucl_size_{lattice_size}_row_{rucl_idx}' ) def rucl_estimate(): args = gen_args() - RuCl_csv_directory=args.directory + RuCl_csv_directory=args.input_dir df_rucl = pd.read_csv(f"{RuCl_csv_directory}RuCl_test_input.csv") if args.mode == 'dynamics': - re_dir = 'temp_RE/Dynamics/' + re_dir = os.path.join(args.output_dir, "Dynamics/") generate_rucl_dynamics_re( energy_precision=1e-3, lattice_size=args.lattice_size, @@ -369,9 +386,8 @@ def rucl_estimate(): outdir=re_dir ) elif args.mode == 'gsee': - re_dir = 'temp_RE/GSEE/' + re_dir = os.path.join(args.output_dir, "GSEE/") generate_rucl_gsee_re( - energy_precision=1e-3, bits_precision = 10, lattice_size=args.lattice_size, evolution_time=args.evolution_time,