diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ba918a7..b89972d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 - uses: haskell-actions/run-fourmolu@v11 with: - version: "0.18.0.0" + version: "0.19.0.0" pattern: | src/**/*.hs test/**/*.hs diff --git a/examples/Makefile b/examples/Makefile index 3c9673da..4e7f87ab 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = basic cryptanalysis matrix_search tree_generator hillclimb search +SUBDIRS = basic primitives cryptanalysis matrix_search tree_generator hillclimb search all: $(SUBDIRS) diff --git a/examples/cryptanalysis/3_round_feistel.qpl b/examples/cryptanalysis/3_round_feistel.qpl index 29cb32bb..7ac1943a 100644 --- a/examples/cryptanalysis/3_round_feistel.qpl +++ b/examples/cryptanalysis/3_round_feistel.qpl @@ -87,6 +87,7 @@ uproc USimon(ret : OUT Fin<2>, ret_1 : OUT BitVec<20>, USimon_aux : AUX Arr<32, call SimonOneRound_U(USimon_aux[#i], USimon_aux_1[#i], USimon_aux_2[#i], USimon_aux_3[#i], USimon_aux_4[#i], USimon_aux_5[#i], USimon_aux_6[#i], USimon_aux_7[#i], USimon_aux_8[#i], USimon_aux_9[#i], USimon_aux_10[#i], USimon_aux_11[#i], USimon_aux_12[#i], USimon_aux_13[#i], USimon_aux_14[#i], USimon_aux_15[#i], USimon_aux_16[#i], USimon_aux_17[#i], USimon_aux_18[#i], USimon_aux_19[#i], USimon_aux_20[#i], USimon_aux_21[#i], USimon_aux_22[#i], USimon_aux_23[#i], USimon_aux_24[#i], USimon_aux_25[#i], USimon_aux_26[#i], USimon_aux_27[#i], USimon_aux_28[#i], USimon_aux_29[#i], USimon_aux_30[#i], USimon_aux_31[#i], USimon_aux_32[#i], USimon_aux_33[#i]); } // simon's post-processing: unitarily solve linear system: (ret, ret_1) . (USimon_aux, USimon_aux_1) = 0 + ret, ret_1, USimon_aux, USimon_aux_1 *= NamedGate("SolveLinearSystem"); } uproc AttackThreeRoundFeistel_U(s : OUT BitVec<20>, zero : AUX Fin<2>, zero_2 : AUX Fin<2>, s_1 : AUX BitVec<20>, x_1 : AUX Fin<2>, x_2 : AUX BitVec<20>, y : AUX Fin<2>, y_1 : AUX BitVec<20>, yy : AUX Fin<2>, yy_1 : AUX BitVec<20>, aux_20 : AUX BitVec<20>, aux_21 : AUX BitVec<20>, aux_22 : AUX BitVec<20>, aux_23 : AUX BitVec<20>, aux_24 : AUX BitVec<20>, aux_25 : AUX BitVec<20>, aux_26 : AUX BitVec<20>, aux_27 : AUX BitVec<20>, aux_28 : AUX BitVec<20>, aux_29 : AUX BitVec<20>, aux_30 : AUX BitVec<20>, aux_31 : AUX BitVec<20>, aux_32 : AUX BitVec<20>, aux_33 : AUX BitVec<20>, aux_34 : AUX BitVec<20>, aux_35 : AUX BitVec<20>, aux_36 : AUX BitVec<20>, aux_37 : AUX BitVec<20>, aux_38 : AUX BitVec<20>, aux_39 : AUX BitVec<20>, aux_40 : AUX BitVec<20>, aux_41 : AUX BitVec<20>, aux_42 : AUX BitVec<20>, aux_43 : AUX BitVec<20>, aux_44 : AUX BitVec<20>, aux_45 : AUX BitVec<20>, aux_46 : AUX BitVec<20>, aux_47 : AUX Fin<2>, USimon_aux : AUX Arr<32, Fin<2>>, USimon_aux_1 : AUX Arr<32, BitVec<20>>, USimon_aux_2 : AUX Arr<32, Fin<2>>, USimon_aux_3 : AUX Arr<32, BitVec<20>>, USimon_aux_4 : AUX Arr<32, Fin<2>>, USimon_aux_5 : AUX Arr<32, BitVec<20>>, USimon_aux_6 : AUX Arr<32, BitVec<20>>, USimon_aux_7 : AUX Arr<32, BitVec<20>>, USimon_aux_8 : AUX Arr<32, BitVec<20>>, USimon_aux_9 : AUX Arr<32, BitVec<20>>, USimon_aux_10 : AUX Arr<32, BitVec<20>>, USimon_aux_11 : AUX Arr<32, BitVec<20>>, USimon_aux_12 : AUX Arr<32, BitVec<20>>, USimon_aux_13 : AUX Arr<32, BitVec<20>>, USimon_aux_14 : AUX Arr<32, BitVec<20>>, USimon_aux_15 : AUX Arr<32, BitVec<20>>, USimon_aux_16 : AUX Arr<32, BitVec<20>>, USimon_aux_17 : AUX Arr<32, BitVec<20>>, USimon_aux_18 : AUX Arr<32, BitVec<20>>, USimon_aux_19 : AUX Arr<32, BitVec<20>>, USimon_aux_20 : AUX Arr<32, BitVec<20>>, USimon_aux_21 : AUX Arr<32, BitVec<20>>, USimon_aux_22 : AUX Arr<32, BitVec<20>>, USimon_aux_23 : AUX Arr<32, BitVec<20>>, USimon_aux_24 : AUX Arr<32, BitVec<20>>, USimon_aux_25 : AUX Arr<32, BitVec<20>>, USimon_aux_26 : AUX Arr<32, BitVec<20>>, USimon_aux_27 : AUX Arr<32, BitVec<20>>, USimon_aux_28 : AUX Arr<32, BitVec<20>>, USimon_aux_29 : AUX Arr<32, BitVec<20>>, USimon_aux_30 : AUX Arr<32, BitVec<20>>, USimon_aux_31 : AUX Arr<32, BitVec<20>>, USimon_aux_32 : AUX Arr<32, BitVec<20>>, USimon_aux_33 : AUX Arr<32, Fin<2>>, aux_prim : AUX Arr<32, Fin<2>>, aux_prim_1 : AUX Arr<32, BitVec<20>>, aux_prim_2 : AUX Arr<32, Fin<2>>, aux_prim_3 : AUX Arr<32, BitVec<20>>, aux_prim_4 : AUX Arr<32, Fin<2>>, aux_prim_5 : AUX Arr<32, BitVec<20>>, aux_prim_6 : AUX Arr<32, BitVec<20>>, aux_prim_7 : AUX Arr<32, BitVec<20>>, aux_prim_8 : AUX Arr<32, BitVec<20>>, aux_prim_9 : AUX Arr<32, BitVec<20>>, aux_prim_10 : AUX Arr<32, BitVec<20>>, aux_prim_11 : AUX Arr<32, BitVec<20>>, aux_prim_12 : AUX Arr<32, BitVec<20>>, aux_prim_13 : AUX Arr<32, BitVec<20>>, aux_prim_14 : AUX Arr<32, BitVec<20>>, aux_prim_15 : AUX Arr<32, BitVec<20>>, aux_prim_16 : AUX Arr<32, BitVec<20>>, aux_prim_17 : AUX Arr<32, BitVec<20>>, aux_prim_18 : AUX Arr<32, BitVec<20>>, aux_prim_19 : AUX Arr<32, BitVec<20>>, aux_prim_20 : AUX Arr<32, BitVec<20>>, aux_prim_21 : AUX Arr<32, BitVec<20>>, aux_prim_22 : AUX Arr<32, BitVec<20>>, aux_prim_23 : AUX Arr<32, BitVec<20>>, aux_prim_24 : AUX Arr<32, BitVec<20>>, aux_prim_25 : AUX Arr<32, BitVec<20>>, aux_prim_26 : AUX Arr<32, BitVec<20>>, aux_prim_27 : AUX Arr<32, BitVec<20>>, aux_prim_28 : AUX Arr<32, BitVec<20>>, aux_prim_29 : AUX Arr<32, BitVec<20>>, aux_prim_30 : AUX Arr<32, BitVec<20>>, aux_prim_31 : AUX Arr<32, BitVec<20>>, aux_prim_32 : AUX Arr<32, BitVec<20>>, aux_prim_33 : AUX Arr<32, Fin<2>>) { @@ -110,6 +111,7 @@ proc QSimon(ret_2 : Fin<2>, ret_3 : BitVec<20>) { locals : (QSimon__u : Arr<32, meas SimonOneRound_U_1(QSimon__u[#i_1], QSimon__u_1[#i_1]); } // simon's post-processing: solve linear system: (ret_2, ret_3) . (QSimon__u, QSimon__u_1) = 0 + call "SolveLinearSystem"(ret_2, ret_3, QSimon__u, QSimon__u_1); } proc AttackThreeRoundFeistel(s : BitVec<20>) { locals : (zero : Fin<2>, x_3 : Fin<2>, x_4 : BitVec<20>, y_2 : Fin<2>, y_3 : BitVec<20>, yy_2 : Fin<2>, yy_3 : BitVec<20>, aux_48 : BitVec<20>, aux_49 : BitVec<20>, aux_50 : BitVec<20>, aux_51 : BitVec<20>, aux_52 : BitVec<20>, aux_53 : BitVec<20>, aux_54 : BitVec<20>, aux_55 : BitVec<20>, aux_56 : BitVec<20>, aux_57 : BitVec<20>, aux_58 : BitVec<20>, aux_59 : BitVec<20>, aux_60 : BitVec<20>, aux_61 : BitVec<20>, aux_62 : BitVec<20>, aux_63 : BitVec<20>, aux_64 : BitVec<20>, aux_65 : BitVec<20>, aux_66 : BitVec<20>, aux_67 : BitVec<20>, aux_68 : BitVec<20>, aux_69 : BitVec<20>, aux_70 : BitVec<20>, aux_71 : BitVec<20>, aux_72 : BitVec<20>, aux_73 : BitVec<20>, aux_74 : BitVec<20>, aux_75 : Fin<2>, QSimon__u : Arr<32, Fin<2>>, QSimon__u_1 : Arr<32, BitVec<20>>) } { diff --git a/examples/cryptanalysis/even_mansour.qpl b/examples/cryptanalysis/even_mansour.qpl index cfe93b1e..c0971800 100644 --- a/examples/cryptanalysis/even_mansour.qpl +++ b/examples/cryptanalysis/even_mansour.qpl @@ -34,6 +34,7 @@ uproc USimon(ret : OUT BitVec<20>, USimon_aux : AUX Arr<31, BitVec<20>>, USimon_ call SimonOneRound_U(USimon_aux[#i], USimon_aux_1[#i], USimon_aux_2[#i], USimon_aux_3[#i], USimon_aux_4[#i], USimon_aux_5[#i], USimon_aux_6[#i], USimon_aux_7[#i]); } // simon's post-processing: unitarily solve linear system: (ret) . (USimon_aux) = 0 + ret, USimon_aux *= NamedGate("SolveLinearSystem"); } uproc BreakEM_U(k1 : OUT BitVec<20>, k2 : OUT BitVec<20>, ze : AUX BitVec<20>, e_0 : AUX BitVec<20>, p_k1 : AUX BitVec<20>, ze_1 : AUX BitVec<20>, k1_1 : AUX BitVec<20>, x_1 : AUX BitVec<20>, y : AUX BitVec<20>, yy : AUX BitVec<20>, aux : AUX BitVec<20>, aux_1 : AUX BitVec<20>, aux_2 : AUX BitVec<20>, aux_3 : AUX BitVec<20>, aux_4 : AUX BitVec<20>, USimon_aux : AUX Arr<31, BitVec<20>>, USimon_aux_1 : AUX Arr<31, BitVec<20>>, USimon_aux_2 : AUX Arr<31, BitVec<20>>, USimon_aux_3 : AUX Arr<31, BitVec<20>>, USimon_aux_4 : AUX Arr<31, BitVec<20>>, USimon_aux_5 : AUX Arr<31, BitVec<20>>, USimon_aux_6 : AUX Arr<31, BitVec<20>>, USimon_aux_7 : AUX Arr<31, BitVec<20>>, aux_prim : AUX Arr<31, BitVec<20>>, aux_prim_1 : AUX Arr<31, BitVec<20>>, aux_prim_2 : AUX Arr<31, BitVec<20>>, aux_prim_3 : AUX Arr<31, BitVec<20>>, aux_prim_4 : AUX Arr<31, BitVec<20>>, aux_prim_5 : AUX Arr<31, BitVec<20>>, aux_prim_6 : AUX Arr<31, BitVec<20>>, aux_prim_7 : AUX Arr<31, BitVec<20>>, e_0_1 : AUX BitVec<20>, p_k1_1 : AUX BitVec<20>, k2_1 : AUX BitVec<20>) { @@ -62,6 +63,7 @@ proc QSimon(ret_1 : BitVec<20>) { locals : (QSimon__u : Arr<31, BitVec<20>>) } { meas SimonOneRound_U_1(QSimon__u[#i_1]); } // simon's post-processing: solve linear system: (ret_1) . (QSimon__u) = 0 + call "SolveLinearSystem"(ret_1, QSimon__u); } proc BreakEM(k1 : BitVec<20>, k2 : BitVec<20>) { locals : (ze : BitVec<20>, e_0 : BitVec<20>, p_k1 : BitVec<20>, x_2 : BitVec<20>, y_1 : BitVec<20>, yy_1 : BitVec<20>, aux_5 : BitVec<20>, aux_6 : BitVec<20>, aux_7 : BitVec<20>, aux_8 : BitVec<20>, aux_9 : BitVec<20>, QSimon__u : Arr<31, BitVec<20>>) } { diff --git a/examples/cryptanalysis/grover_meets_simon.qpl b/examples/cryptanalysis/grover_meets_simon.qpl index a81a0820..39c18fba 100644 --- a/examples/cryptanalysis/grover_meets_simon.qpl +++ b/examples/cryptanalysis/grover_meets_simon.qpl @@ -38,6 +38,7 @@ uproc USimon(k : BitVec<20>, ret : OUT BitVec<20>, USimon_aux : AUX Arr<79, BitV call SimonOneRound_U(k, USimon_aux[#i], USimon_aux_1[#i], USimon_aux_2[#i], USimon_aux_3[#i], USimon_aux_4[#i], USimon_aux_5[#i], USimon_aux_6[#i], USimon_aux_7[#i]); } // simon's post-processing: unitarily solve linear system: (ret) . (USimon_aux) = 0 + ret, USimon_aux *= NamedGate("SolveLinearSystem"); } uproc innerAttack_U(k : IN BitVec<20>, res : OUT Fin<2>, k1 : AUX BitVec<20>, k1_1 : AUX BitVec<20>, x_1 : AUX BitVec<20>, y : AUX BitVec<20>, yy : AUX BitVec<20>, aux : AUX BitVec<20>, aux_1 : AUX BitVec<20>, aux_2 : AUX BitVec<20>, aux_3 : AUX BitVec<20>, aux_4 : AUX BitVec<20>, USimon_aux : AUX Arr<79, BitVec<20>>, USimon_aux_1 : AUX Arr<79, BitVec<20>>, USimon_aux_2 : AUX Arr<79, BitVec<20>>, USimon_aux_3 : AUX Arr<79, BitVec<20>>, USimon_aux_4 : AUX Arr<79, BitVec<20>>, USimon_aux_5 : AUX Arr<79, BitVec<20>>, USimon_aux_6 : AUX Arr<79, BitVec<20>>, USimon_aux_7 : AUX Arr<79, BitVec<20>>, aux_prim : AUX Arr<79, BitVec<20>>, aux_prim_1 : AUX Arr<79, BitVec<20>>, aux_prim_2 : AUX Arr<79, BitVec<20>>, aux_prim_3 : AUX Arr<79, BitVec<20>>, aux_prim_4 : AUX Arr<79, BitVec<20>>, aux_prim_5 : AUX Arr<79, BitVec<20>>, aux_prim_6 : AUX Arr<79, BitVec<20>>, aux_prim_7 : AUX Arr<79, BitVec<20>>, res_1 : AUX Fin<2>) { @@ -60,6 +61,7 @@ proc QSimon(k : BitVec<20>, ret_1 : BitVec<20>) { locals : (QSimon__u : Arr<79, meas SimonOneRound_U_1(QSimon__u[#i_1]); } // simon's post-processing: solve linear system: (ret_1) . (QSimon__u) = 0 + call "SolveLinearSystem"(ret_1, QSimon__u); } proc innerAttack(k : BitVec<20>, res : Fin<2>) { locals : (k1 : BitVec<20>, x_2 : BitVec<20>, y_1 : BitVec<20>, yy_1 : BitVec<20>, aux_5 : BitVec<20>, aux_6 : BitVec<20>, aux_7 : BitVec<20>, aux_8 : BitVec<20>, aux_9 : BitVec<20>, QSimon__u : Arr<79, BitVec<20>>) } { @@ -67,7 +69,6 @@ proc innerAttack(k : BitVec<20>, res : Fin<2>) { locals : (k1 : BitVec<20>, x_2 call classifier(k, k1, res); } -// USearch[Bitvec 20, 5.0e-4] uproc USearch(ret_2 : OUT Fin<2>, ret_3 : OUT BitVec<20>, aux_10 : AUX BitVec<20>, aux_11 : AUX BitVec<20>, aux_12 : AUX BitVec<20>, aux_13 : AUX BitVec<20>, aux_14 : AUX BitVec<20>, aux_15 : AUX BitVec<20>, aux_16 : AUX BitVec<20>, aux_17 : AUX BitVec<20>, aux_18 : AUX BitVec<20>, aux_19 : AUX BitVec<20>, aux_20 : AUX Arr<79, BitVec<20>>, aux_21 : AUX Arr<79, BitVec<20>>, aux_22 : AUX Arr<79, BitVec<20>>, aux_23 : AUX Arr<79, BitVec<20>>, aux_24 : AUX Arr<79, BitVec<20>>, aux_25 : AUX Arr<79, BitVec<20>>, aux_26 : AUX Arr<79, BitVec<20>>, aux_27 : AUX Arr<79, BitVec<20>>, aux_28 : AUX Arr<79, BitVec<20>>, aux_29 : AUX Arr<79, BitVec<20>>, aux_30 : AUX Arr<79, BitVec<20>>, aux_31 : AUX Arr<79, BitVec<20>>, aux_32 : AUX Arr<79, BitVec<20>>, aux_33 : AUX Arr<79, BitVec<20>>, aux_34 : AUX Arr<79, BitVec<20>>, aux_35 : AUX Arr<79, BitVec<20>>, aux_36 : AUX Fin<2>, aux_37 : AUX Fin<2>, ctrl : AUX Arr<16, Fin<2>>, pred_out : AUX Arr<16, Fin<2>>, n_iter : AUX Arr<16, Fin<805>>, s_arg : AUX Arr<16, BitVec<20>>) { for (#run_ix in 0 .. < 16) { n_iter[#run_ix] *= Distr[uniform : Fin<805>]; @@ -102,7 +103,6 @@ uproc outerAttack_U(k0 : OUT BitVec<20>, ok : AUX Fin<2>, ok_1 : AUX Fin<2>, k0_ ok, k0, ok_1, k0_1 *= SWAP; } -// Grover[...] uproc Grover[k](x_3 : IN BitVec<20>, ret_4 : OUT Fin<2>, aux_38 : AUX BitVec<20>, aux_39 : AUX BitVec<20>, aux_40 : AUX BitVec<20>, aux_41 : AUX BitVec<20>, aux_42 : AUX BitVec<20>, aux_43 : AUX BitVec<20>, aux_44 : AUX BitVec<20>, aux_45 : AUX BitVec<20>, aux_46 : AUX BitVec<20>, aux_47 : AUX BitVec<20>, aux_48 : AUX Arr<79, BitVec<20>>, aux_49 : AUX Arr<79, BitVec<20>>, aux_50 : AUX Arr<79, BitVec<20>>, aux_51 : AUX Arr<79, BitVec<20>>, aux_52 : AUX Arr<79, BitVec<20>>, aux_53 : AUX Arr<79, BitVec<20>>, aux_54 : AUX Arr<79, BitVec<20>>, aux_55 : AUX Arr<79, BitVec<20>>, aux_56 : AUX Arr<79, BitVec<20>>, aux_57 : AUX Arr<79, BitVec<20>>, aux_58 : AUX Arr<79, BitVec<20>>, aux_59 : AUX Arr<79, BitVec<20>>, aux_60 : AUX Arr<79, BitVec<20>>, aux_61 : AUX Arr<79, BitVec<20>>, aux_62 : AUX Arr<79, BitVec<20>>, aux_63 : AUX Arr<79, BitVec<20>>, aux_64 : AUX Fin<2>) { ret_4 *= X; ret_4 *= H; diff --git a/examples/cryptanalysis/period_finding.qpl b/examples/cryptanalysis/period_finding.qpl index 0944fc54..c778f9db 100644 --- a/examples/cryptanalysis/period_finding.qpl +++ b/examples/cryptanalysis/period_finding.qpl @@ -15,6 +15,7 @@ uproc USimon(ret : OUT BitVec<20>, USimon_aux : AUX Arr<31, BitVec<20>>, USimon_ call SimonOneRound_U(USimon_aux[#i], USimon_aux_1[#i], USimon_aux_2[#i]); } // simon's post-processing: unitarily solve linear system: (ret) . (USimon_aux) = 0 + ret, USimon_aux *= NamedGate("SolveLinearSystem"); } uproc main_U(s : OUT BitVec<20>, s_1 : AUX BitVec<20>, x : AUX BitVec<20>, y : AUX BitVec<20>, yy : AUX BitVec<20>, USimon_aux : AUX Arr<31, BitVec<20>>, USimon_aux_1 : AUX Arr<31, BitVec<20>>, USimon_aux_2 : AUX Arr<31, BitVec<20>>, aux_prim : AUX Arr<31, BitVec<20>>, aux_prim_1 : AUX Arr<31, BitVec<20>>, aux_prim_2 : AUX Arr<31, BitVec<20>>) { @@ -35,6 +36,7 @@ proc QSimon(ret_1 : BitVec<20>) { locals : (QSimon__u : Arr<31, BitVec<20>>) } { meas SimonOneRound_U_1(QSimon__u[#i_1]); } // simon's post-processing: solve linear system: (ret_1) . (QSimon__u) = 0 + call "SolveLinearSystem"(ret_1, QSimon__u); } proc main(s : BitVec<20>) { locals : (x_1 : BitVec<20>, y_1 : BitVec<20>, yy_1 : BitVec<20>, QSimon__u : Arr<31, BitVec<20>>) } { diff --git a/examples/hillclimb/max_sat_hillclimb.qpl b/examples/hillclimb/max_sat_hillclimb.qpl index f89293f9..74e8e2ad 100644 --- a/examples/hillclimb/max_sat_hillclimb.qpl +++ b/examples/hillclimb/max_sat_hillclimb.qpl @@ -26,7 +26,6 @@ proc good(x : Arr<20, Fin<2>>, i : Fin<20>, ok : Fin<2>) { locals : (w : Fin<100 ok := (w < w'); } -// USearch[Fin 20, 3.333333333333333e-4] uproc USearch(x : Arr<20, Fin<2>>, ret : OUT Fin<2>, ret_1 : OUT Fin<20>, aux : AUX Fin<1000>, aux_1 : AUX Fin<2>, aux_2 : AUX Fin<2>, aux_3 : AUX Arr<20, Fin<2>>, aux_4 : AUX Fin<1000>, aux_5 : AUX Fin<1000>, aux_6 : AUX Fin<2>, aux_7 : AUX Fin<2>, aux_8 : AUX Arr<20, Fin<2>>, aux_9 : AUX Fin<1000>, aux_10 : AUX Fin<2>, aux_11 : AUX Fin<2>, ctrl : AUX Arr<17, Fin<2>>, pred_out : AUX Arr<17, Fin<2>>, n_iter : AUX Arr<17, Fin<4>>, s_arg : AUX Arr<17, Fin<20>>) { for (#run_ix in 0 .. < 17) { n_iter[#run_ix] *= Distr[uniform : Fin<4>]; @@ -67,7 +66,6 @@ uproc hillclimb_iter_U(x : IN Arr<20, Fin<2>>, x' : OUT Arr<20, Fin<2>>, ok : AU x', x'_2 *= SWAP; } -// Grover[...] uproc Grover[k](x : Arr<20, Fin<2>>, x_4 : IN Fin<20>, ret_2 : OUT Fin<2>, aux_12 : AUX Fin<1000>, aux_13 : AUX Fin<2>, aux_14 : AUX Fin<2>, aux_15 : AUX Arr<20, Fin<2>>, aux_16 : AUX Fin<1000>, aux_17 : AUX Fin<1000>, aux_18 : AUX Fin<2>, aux_19 : AUX Fin<2>, aux_20 : AUX Arr<20, Fin<2>>, aux_21 : AUX Fin<1000>, aux_22 : AUX Fin<2>) { ret_2 *= X; ret_2 *= H; diff --git a/examples/hillclimb/steep_max_sat.qpl b/examples/hillclimb/steep_max_sat.qpl index 0a54d9dc..1ae42622 100644 --- a/examples/hillclimb/steep_max_sat.qpl +++ b/examples/hillclimb/steep_max_sat.qpl @@ -27,7 +27,8 @@ uproc UMax(x : Arr<20, Fin<2>>, ret : Fin<1000>, ret_1 : Fin<20>, inp : AUX Arr< for (#x_4 in Fin<20>) { call good_U(x, inp[#x_4], out[#x_4], aux[#x_4], aux_1[#x_4], aux_2[#x_4], aux_3[#x_4], aux_4[#x_4], aux_5[#x_4], aux_6[#x_4], aux_7[#x_4], aux_8[#x_4]); } - // unitarily compute: ret := max(out); ret_1 := argmax(out); + out, ret *= NamedGate("max"); + out, ret_1 *= NamedGate("argmax"); } uproc hillclimb_iter_U(x : IN Arr<20, Fin<2>>, x' : OUT Arr<20, Fin<2>>, w : AUX Fin<1000>, i : AUX Fin<20>, b : AUX Fin<2>, b' : AUX Fin<2>, w_2 : AUX Fin<1000>, i_1 : AUX Fin<20>, aux_prim : AUX Arr<20, Fin<20>>, aux_prim_1 : AUX Arr<20, Fin<1000>>, aux_prim_2 : AUX Arr<20, Fin<1000>>, aux_prim_3 : AUX Arr<20, Fin<2>>, aux_prim_4 : AUX Arr<20, Fin<2>>, aux_prim_5 : AUX Arr<20, Arr<20, Fin<2>>>, aux_prim_6 : AUX Arr<20, Fin<1000>>, aux_prim_7 : AUX Arr<20, Fin<2>>, aux_prim_8 : AUX Arr<20, Fin<2>>, aux_prim_9 : AUX Arr<20, Arr<20, Fin<2>>>, aux_prim_10 : AUX Arr<20, Fin<1000>>, b_2 : AUX Fin<2>, b'_2 : AUX Fin<2>, x'_2 : AUX Arr<20, Fin<2>>) { diff --git a/examples/matrix_search/depth3_NAND_formula.qpl b/examples/matrix_search/depth3_NAND_formula.qpl index 57ef2201..a42cd4c7 100644 --- a/examples/matrix_search/depth3_NAND_formula.qpl +++ b/examples/matrix_search/depth3_NAND_formula.qpl @@ -14,7 +14,6 @@ proc NOR_0(i0 : Fin<20>, j0 : Fin<10>, k0 : Fin<10>, e' : Fin<2>) { locals : (e e' := not e; } -// UAny[Fin 10, 3.801194009254654e-32] uproc UAny(i1 : Fin<20>, j1 : Fin<10>, ret : OUT Fin<2>, s_result : OUT Fin<10>, aux : AUX Fin<2>, aux_1 : AUX Fin<2>, aux_2 : AUX Fin<2>, aux_3 : AUX Fin<2>, ctrl : AUX Arr<146, Fin<2>>, pred_out : AUX Arr<146, Fin<2>>, n_iter : AUX Arr<146, Fin<3>>, s_arg : AUX Arr<146, Fin<10>>) { for (#run_ix in 0 .. < 146) { n_iter[#run_ix] *= Distr[uniform : Fin<3>]; @@ -51,7 +50,6 @@ uproc NOR_1_U(i1 : IN Fin<20>, j1 : IN Fin<10>, nor_1 : OUT Fin<2>, or_1 : AUX F nor_1, nor_1_1 *= SWAP; } -// Grover[...] uproc Grover[k](i1 : Fin<20>, j1 : Fin<10>, x : IN Fin<10>, ret_1 : OUT Fin<2>, aux_4 : AUX Fin<2>, aux_5 : AUX Fin<2>, aux_6 : AUX Fin<2>) { ret_1 *= X; ret_1 *= H; @@ -89,7 +87,6 @@ proc NOR_1(i1 : Fin<20>, j1 : Fin<10>, nor_1 : Fin<2>) { locals : (or_1 : Fin<2> nor_1 := not or_1; } -// UAny[Fin 10, 1.3387056295712027e-13] uproc UAny_1(i2 : Fin<20>, ret_2 : OUT Fin<2>, s_result_2 : OUT Fin<10>, aux_7 : AUX Fin<2>, aux_8 : AUX Fin<2>, aux_9 : AUX Fin<10>, aux_10 : AUX Fin<2>, aux_11 : AUX Fin<2>, aux_12 : AUX Fin<2>, aux_13 : AUX Fin<2>, aux_14 : AUX Arr<146, Fin<2>>, aux_15 : AUX Arr<146, Fin<2>>, aux_16 : AUX Arr<146, Fin<3>>, aux_17 : AUX Arr<146, Fin<10>>, aux_18 : AUX Fin<10>, aux_19 : AUX Fin<2>, aux_20 : AUX Fin<2>, aux_21 : AUX Fin<2>, aux_22 : AUX Fin<2>, aux_23 : AUX Arr<146, Fin<2>>, aux_24 : AUX Arr<146, Fin<2>>, aux_25 : AUX Arr<146, Fin<3>>, aux_26 : AUX Arr<146, Fin<10>>, aux_27 : AUX Fin<2>, aux_28 : AUX Fin<2>, ctrl_1 : AUX Arr<60, Fin<2>>, pred_out_1 : AUX Arr<60, Fin<2>>, n_iter_1 : AUX Arr<60, Fin<3>>, s_arg_1 : AUX Arr<60, Fin<10>>) { for (#run_ix in 0 .. < 60) { n_iter_1[#run_ix] *= Distr[uniform : Fin<3>]; @@ -126,7 +123,6 @@ uproc NOR_2_U(i2 : IN Fin<20>, nor_2 : OUT Fin<2>, or_2 : AUX Fin<2>, or_2_1 : A nor_2, nor_2_1 *= SWAP; } -// Grover[...] uproc Grover_1[k](i2 : Fin<20>, x_1 : IN Fin<10>, ret_3 : OUT Fin<2>, aux_29 : AUX Fin<2>, aux_30 : AUX Fin<2>, aux_31 : AUX Fin<10>, aux_32 : AUX Fin<2>, aux_33 : AUX Fin<2>, aux_34 : AUX Fin<2>, aux_35 : AUX Fin<2>, aux_36 : AUX Arr<146, Fin<2>>, aux_37 : AUX Arr<146, Fin<2>>, aux_38 : AUX Arr<146, Fin<3>>, aux_39 : AUX Arr<146, Fin<10>>, aux_40 : AUX Fin<10>, aux_41 : AUX Fin<2>, aux_42 : AUX Fin<2>, aux_43 : AUX Fin<2>, aux_44 : AUX Fin<2>, aux_45 : AUX Arr<146, Fin<2>>, aux_46 : AUX Arr<146, Fin<2>>, aux_47 : AUX Arr<146, Fin<3>>, aux_48 : AUX Arr<146, Fin<10>>, aux_49 : AUX Fin<2>) { ret_3 *= X; ret_3 *= H; @@ -164,7 +160,6 @@ proc NOR_2(i2 : Fin<20>, nor_2 : Fin<2>) { locals : (or_2 : Fin<2>) } { nor_2 := not or_2; } -// UAny[Fin 20, 5.0e-4] uproc UAny_2(ret_4 : OUT Fin<2>, s_result_4 : OUT Fin<20>, aux_50 : AUX Fin<2>, aux_51 : AUX Fin<2>, aux_52 : AUX Fin<10>, aux_53 : AUX Fin<2>, aux_54 : AUX Fin<2>, aux_55 : AUX Fin<10>, aux_56 : AUX Fin<2>, aux_57 : AUX Fin<2>, aux_58 : AUX Fin<2>, aux_59 : AUX Fin<2>, aux_60 : AUX Arr<146, Fin<2>>, aux_61 : AUX Arr<146, Fin<2>>, aux_62 : AUX Arr<146, Fin<3>>, aux_63 : AUX Arr<146, Fin<10>>, aux_64 : AUX Fin<10>, aux_65 : AUX Fin<2>, aux_66 : AUX Fin<2>, aux_67 : AUX Fin<2>, aux_68 : AUX Fin<2>, aux_69 : AUX Arr<146, Fin<2>>, aux_70 : AUX Arr<146, Fin<2>>, aux_71 : AUX Arr<146, Fin<3>>, aux_72 : AUX Arr<146, Fin<10>>, aux_73 : AUX Fin<2>, aux_74 : AUX Fin<2>, aux_75 : AUX Arr<60, Fin<2>>, aux_76 : AUX Arr<60, Fin<2>>, aux_77 : AUX Arr<60, Fin<3>>, aux_78 : AUX Arr<60, Fin<10>>, aux_79 : AUX Fin<10>, aux_80 : AUX Fin<2>, aux_81 : AUX Fin<2>, aux_82 : AUX Fin<10>, aux_83 : AUX Fin<2>, aux_84 : AUX Fin<2>, aux_85 : AUX Fin<2>, aux_86 : AUX Fin<2>, aux_87 : AUX Arr<146, Fin<2>>, aux_88 : AUX Arr<146, Fin<2>>, aux_89 : AUX Arr<146, Fin<3>>, aux_90 : AUX Arr<146, Fin<10>>, aux_91 : AUX Fin<10>, aux_92 : AUX Fin<2>, aux_93 : AUX Fin<2>, aux_94 : AUX Fin<2>, aux_95 : AUX Fin<2>, aux_96 : AUX Arr<146, Fin<2>>, aux_97 : AUX Arr<146, Fin<2>>, aux_98 : AUX Arr<146, Fin<3>>, aux_99 : AUX Arr<146, Fin<10>>, aux_100 : AUX Fin<2>, aux_101 : AUX Fin<2>, aux_102 : AUX Arr<60, Fin<2>>, aux_103 : AUX Arr<60, Fin<2>>, aux_104 : AUX Arr<60, Fin<3>>, aux_105 : AUX Arr<60, Fin<10>>, aux_106 : AUX Fin<2>, aux_107 : AUX Fin<2>, ctrl_2 : AUX Arr<16, Fin<2>>, pred_out_2 : AUX Arr<16, Fin<2>>, n_iter_2 : AUX Arr<16, Fin<4>>, s_arg_2 : AUX Arr<16, Fin<20>>) { for (#run_ix in 0 .. < 16) { n_iter_2[#run_ix] *= Distr[uniform : Fin<4>]; @@ -199,7 +194,6 @@ uproc Depth3Nand_U(or_3 : OUT Fin<2>, or_3_1 : AUX Fin<2>, s_result_4 : AUX Fin< or_3, or_3_1 *= SWAP; } -// Grover[...] uproc Grover_2[k](x_2 : IN Fin<20>, ret_5 : OUT Fin<2>, aux_108 : AUX Fin<2>, aux_109 : AUX Fin<2>, aux_110 : AUX Fin<10>, aux_111 : AUX Fin<2>, aux_112 : AUX Fin<2>, aux_113 : AUX Fin<10>, aux_114 : AUX Fin<2>, aux_115 : AUX Fin<2>, aux_116 : AUX Fin<2>, aux_117 : AUX Fin<2>, aux_118 : AUX Arr<146, Fin<2>>, aux_119 : AUX Arr<146, Fin<2>>, aux_120 : AUX Arr<146, Fin<3>>, aux_121 : AUX Arr<146, Fin<10>>, aux_122 : AUX Fin<10>, aux_123 : AUX Fin<2>, aux_124 : AUX Fin<2>, aux_125 : AUX Fin<2>, aux_126 : AUX Fin<2>, aux_127 : AUX Arr<146, Fin<2>>, aux_128 : AUX Arr<146, Fin<2>>, aux_129 : AUX Arr<146, Fin<3>>, aux_130 : AUX Arr<146, Fin<10>>, aux_131 : AUX Fin<2>, aux_132 : AUX Fin<2>, aux_133 : AUX Arr<60, Fin<2>>, aux_134 : AUX Arr<60, Fin<2>>, aux_135 : AUX Arr<60, Fin<3>>, aux_136 : AUX Arr<60, Fin<10>>, aux_137 : AUX Fin<10>, aux_138 : AUX Fin<2>, aux_139 : AUX Fin<2>, aux_140 : AUX Fin<10>, aux_141 : AUX Fin<2>, aux_142 : AUX Fin<2>, aux_143 : AUX Fin<2>, aux_144 : AUX Fin<2>, aux_145 : AUX Arr<146, Fin<2>>, aux_146 : AUX Arr<146, Fin<2>>, aux_147 : AUX Arr<146, Fin<3>>, aux_148 : AUX Arr<146, Fin<10>>, aux_149 : AUX Fin<10>, aux_150 : AUX Fin<2>, aux_151 : AUX Fin<2>, aux_152 : AUX Fin<2>, aux_153 : AUX Fin<2>, aux_154 : AUX Arr<146, Fin<2>>, aux_155 : AUX Arr<146, Fin<2>>, aux_156 : AUX Arr<146, Fin<3>>, aux_157 : AUX Arr<146, Fin<10>>, aux_158 : AUX Fin<2>, aux_159 : AUX Fin<2>, aux_160 : AUX Arr<60, Fin<2>>, aux_161 : AUX Arr<60, Fin<2>>, aux_162 : AUX Arr<60, Fin<3>>, aux_163 : AUX Arr<60, Fin<10>>, aux_164 : AUX Fin<2>) { ret_5 *= X; ret_5 *= H; diff --git a/examples/matrix_search/matrix_search.qpl b/examples/matrix_search/matrix_search.qpl index d7f7a868..770ad853 100644 --- a/examples/matrix_search/matrix_search.qpl +++ b/examples/matrix_search/matrix_search.qpl @@ -14,7 +14,6 @@ proc IsEntryZero(i : Fin<20>, j : Fin<10>, e : Fin<2>) { locals : () } { e := not e; } -// UAny[Fin 10, 2.6774112591424054e-13] uproc UAny(i : Fin<20>, ret : OUT Fin<2>, s_result : OUT Fin<10>, aux : AUX Fin<2>, aux_1 : AUX Fin<2>, aux_2 : AUX Fin<2>, ctrl : AUX Arr<59, Fin<2>>, pred_out : AUX Arr<59, Fin<2>>, n_iter : AUX Arr<59, Fin<3>>, s_arg : AUX Arr<59, Fin<10>>) { for (#run_ix in 0 .. < 59) { n_iter[#run_ix] *= Distr[uniform : Fin<3>]; @@ -51,7 +50,6 @@ uproc IsRowAllOnes_U(i : IN Fin<20>, ok : OUT Fin<2>, hasZero : AUX Fin<2>, hasZ ok, ok_1 *= SWAP; } -// Grover[...] uproc Grover[k](i : Fin<20>, x : IN Fin<10>, ret_1 : OUT Fin<2>, aux_3 : AUX Fin<2>, aux_4 : AUX Fin<2>) { ret_1 *= X; ret_1 *= H; @@ -89,7 +87,6 @@ proc IsRowAllOnes(i : Fin<20>, ok : Fin<2>) { locals : (hasZero : Fin<2>) } { ok := not hasZero; } -// UAny[Fin 20, 5.0e-4] uproc UAny_1(ret_2 : OUT Fin<2>, s_result_2 : OUT Fin<20>, aux_5 : AUX Fin<2>, aux_6 : AUX Fin<2>, aux_7 : AUX Fin<10>, aux_8 : AUX Fin<2>, aux_9 : AUX Fin<2>, aux_10 : AUX Fin<2>, aux_11 : AUX Arr<59, Fin<2>>, aux_12 : AUX Arr<59, Fin<2>>, aux_13 : AUX Arr<59, Fin<3>>, aux_14 : AUX Arr<59, Fin<10>>, aux_15 : AUX Fin<10>, aux_16 : AUX Fin<2>, aux_17 : AUX Fin<2>, aux_18 : AUX Fin<2>, aux_19 : AUX Arr<59, Fin<2>>, aux_20 : AUX Arr<59, Fin<2>>, aux_21 : AUX Arr<59, Fin<3>>, aux_22 : AUX Arr<59, Fin<10>>, aux_23 : AUX Fin<2>, aux_24 : AUX Fin<2>, ctrl_1 : AUX Arr<16, Fin<2>>, pred_out_1 : AUX Arr<16, Fin<2>>, n_iter_1 : AUX Arr<16, Fin<4>>, s_arg_1 : AUX Arr<16, Fin<20>>) { for (#run_ix in 0 .. < 16) { n_iter_1[#run_ix] *= Distr[uniform : Fin<4>]; @@ -124,7 +121,6 @@ uproc HasAllOnesRow_U(ok : OUT Fin<2>, ok_2 : AUX Fin<2>, s_result_2 : AUX Fin<2 ok, ok_2 *= SWAP; } -// Grover[...] uproc Grover_1[k](x_1 : IN Fin<20>, ret_3 : OUT Fin<2>, aux_25 : AUX Fin<2>, aux_26 : AUX Fin<2>, aux_27 : AUX Fin<10>, aux_28 : AUX Fin<2>, aux_29 : AUX Fin<2>, aux_30 : AUX Fin<2>, aux_31 : AUX Arr<59, Fin<2>>, aux_32 : AUX Arr<59, Fin<2>>, aux_33 : AUX Arr<59, Fin<3>>, aux_34 : AUX Arr<59, Fin<10>>, aux_35 : AUX Fin<10>, aux_36 : AUX Fin<2>, aux_37 : AUX Fin<2>, aux_38 : AUX Fin<2>, aux_39 : AUX Arr<59, Fin<2>>, aux_40 : AUX Arr<59, Fin<2>>, aux_41 : AUX Arr<59, Fin<3>>, aux_42 : AUX Arr<59, Fin<10>>, aux_43 : AUX Fin<2>) { ret_3 *= X; ret_3 *= H; diff --git a/examples/primitives/Makefile b/examples/primitives/Makefile index 5e710970..da185e9a 100644 --- a/examples/primitives/Makefile +++ b/examples/primitives/Makefile @@ -1,9 +1,17 @@ PROJ_DEPS=../../src ../../tools ../../traq.cabal -all: max.qpl +all: any.qpl any-qiskit.py max.qpl %.qpl: %.traq $(PROJ_DEPS) cd ../../ && cabal run traq -- \ -i examples/primitives/$< \ -o examples/primitives/$@ \ -p 0.01 + +%-qiskit.py: %.traq + cd ../../ && cabal run traq -- \ + -i examples/primitives/$< \ + -o examples/primitives/$@ \ + -p 0.01 \ + --target Qiskit + black $@ diff --git a/examples/primitives/any-qiskit.py b/examples/primitives/any-qiskit.py new file mode 100644 index 00000000..0ee62de0 --- /dev/null +++ b/examples/primitives/any-qiskit.py @@ -0,0 +1,199 @@ +import random +import numpy as np +import qiskit +import qiskit.circuit +from qiskit.circuit import ClassicalRegister, QuantumRegister + + +def Oracle_U(): + q_1 = qiskit.circuit.QuantumRegister(5, "q_1") + q_2 = qiskit.circuit.QuantumRegister(1, "q_2") + qc = qiskit.circuit.QuantumCircuit(q_1, q_2, name="Oracle_U") + return qc + + +def Oracle(): + c_1 = qiskit.circuit.ClassicalRegister(5, "c_1") + c_2 = qiskit.circuit.ClassicalRegister(1, "c_2") + qc = qiskit.circuit.QuantumCircuit(c_1, c_2, name="Oracle") + return qc + + +def UAny(): + ret = qiskit.circuit.QuantumRegister(1, "ret") + s_result = qiskit.circuit.QuantumRegister(5, "s_result") + aux = qiskit.circuit.QuantumRegister(1, "aux") + ctrl = qiskit.circuit.QuantumRegister(10, "ctrl") + pred_out = qiskit.circuit.QuantumRegister(10, "pred_out") + n_iter = qiskit.circuit.QuantumRegister(20, "n_iter") + s_arg = qiskit.circuit.QuantumRegister(50, "s_arg") + + qc = qiskit.circuit.QuantumCircuit( + ret, s_result, aux, ctrl, pred_out, n_iter, s_arg, name="UAny" + ) + + qc.append(qiskit.circuit.Gate("UForInRangeS", qc.num_qubits, []), qc.qubits) + qc.append( + qiskit.circuit.Gate( + "RevEmbedU [a] (UnOpE {un_op = AnyOp, operand = VarE {var = a}})", 11, [] + ), + [*pred_out, *ret], + ) + qc.append( + qiskit.circuit.Gate( + "RevEmbedU [a,f] (BinOpE {bin_op = VecSelectOp, lhs = VarE {var = a}, rhs = VarE {var = f}})", + 65, + [], + ), + [*s_arg, *pred_out, *s_result], + ) + + return qc + + +def main_U(): + ok = qiskit.circuit.QuantumRegister(1, "ok") + ok_1 = qiskit.circuit.QuantumRegister(1, "ok_1") + s_result = qiskit.circuit.QuantumRegister(5, "s_result") + aux = qiskit.circuit.QuantumRegister(1, "aux") + ctrl = qiskit.circuit.QuantumRegister(10, "ctrl") + pred_out = qiskit.circuit.QuantumRegister(10, "pred_out") + n_iter = qiskit.circuit.QuantumRegister(20, "n_iter") + s_arg = qiskit.circuit.QuantumRegister(50, "s_arg") + aux_prim = qiskit.circuit.QuantumRegister(5, "aux_prim") + aux_prim_1 = qiskit.circuit.QuantumRegister(1, "aux_prim_1") + aux_prim_2 = qiskit.circuit.QuantumRegister(10, "aux_prim_2") + aux_prim_3 = qiskit.circuit.QuantumRegister(10, "aux_prim_3") + aux_prim_4 = qiskit.circuit.QuantumRegister(20, "aux_prim_4") + aux_prim_5 = qiskit.circuit.QuantumRegister(50, "aux_prim_5") + + qc = qiskit.circuit.QuantumCircuit( + ok, + ok_1, + s_result, + aux, + ctrl, + pred_out, + n_iter, + s_arg, + aux_prim, + aux_prim_1, + aux_prim_2, + aux_prim_3, + aux_prim_4, + aux_prim_5, + name="main_U", + ) + + qc.append( + UAny().to_gate(), + [ + *ok_1, + *aux_prim, + *aux_prim_1, + *aux_prim_2, + *aux_prim_3, + *aux_prim_4, + *aux_prim_5, + ], + ) + qc.append(qiskit.circuit.library.SwapGate(), [*ok, *ok_1]) + + return qc + + +def Grover(): + k = qiskit.circuit.Parameter("k") + x = qiskit.circuit.QuantumRegister(5, "x") + ret_1 = qiskit.circuit.QuantumRegister(1, "ret_1") + + qc = qiskit.circuit.QuantumCircuit(x, ret_1, name="Grover") + + qc.append(qiskit.circuit.library.XGate(), [*ret_1]) + qc.append(qiskit.circuit.library.HGate(), [*ret_1]) + qc.append( + qiskit.circuit.Gate("DistrU (UniformE {sample_ty = Fin 20})", 5, []), [*x] + ) + with qc.for_loop(range(k)): + qc.append(Oracle_U().to_gate(), [*x, *ret_1]) + qc.append( + qiskit.circuit.Gate( + "DistrU (UniformE {sample_ty = Fin 20})", 5, [] + ).inverse(), + [*x], + ) + qc.append(qiskit.circuit.Gate("PhaseOnZero(3.141592653589793)", 5, []), [*x]) + qc.append( + qiskit.circuit.Gate("DistrU (UniformE {sample_ty = Fin 20})", 5, []), [*x] + ) + qc.append(qiskit.circuit.library.HGate(), [*ret_1]) + qc.append(qiskit.circuit.library.XGate(), [*ret_1]) + + return qc + + +def QAny(): + ret_1 = qiskit.circuit.ClassicalRegister(1, "ret_1") + s_result_1 = qiskit.circuit.ClassicalRegister(5, "s_result_1") + not_done = qiskit.circuit.ClassicalRegister(1, "not_done") + Q_sum = qiskit.circuit.ClassicalRegister(6, "Q_sum") + j = qiskit.circuit.ClassicalRegister(6, "j") + j_lim = qiskit.circuit.ClassicalRegister(6, "j_lim") + qc = qiskit.circuit.QuantumCircuit( + ret_1, s_result_1, not_done, Q_sum, j, j_lim, name="QAny" + ) + for _ in range(5): + Q_sum = 0 + for j_lim in [1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4]: + j = random.randrange(j_lim) + Q_sum = Q_sum + j + not_done = not_done and (Q_sum <= j_lim) + if not_done: + qc.append( + qiskit.circuit.Gate("UProcAndMeas", qc.num_qubits, []), qc.qubits + ) + qc.append( + qiskit.circuit.Gate("UProcAndMeas", qc.num_qubits, []), qc.qubits + ) + not_done = not_done and ret_1 + else: + pass + return qc + + +def main(): + ok = qiskit.circuit.ClassicalRegister(1, "ok") + qc = qiskit.circuit.QuantumCircuit(ok, name="main") + qc.append(QAny().to_instruction(), [], [*ok]) + return qc + + +EXTERN_DEFS = () +ENTRY_POINT = "main" + + +def cli(): + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument( + "--draw", type=str, metavar="FILE", help="Render the main circuit to a PDF file" + ) + parser.add_argument( + "--qasm", action="store_true", help="Output OpenQASM 3 for the main circuit" + ) + args = parser.parse_args() + + qc = main() + + if args.draw: + qc.draw("mpl", filename=args.draw) + + if args.qasm: + from qiskit.qasm3 import dumps + + print(dumps(qc)) + + +if __name__ == "__main__": + cli() diff --git a/examples/primitives/any.qpl b/examples/primitives/any.qpl new file mode 100644 index 00000000..d73c98f4 --- /dev/null +++ b/examples/primitives/any.qpl @@ -0,0 +1,76 @@ +ext uproc Oracle_U(Fin<20>, Fin<2>); + +ext proc Oracle(Fin<20>, Fin<2>); + +uproc UAny(ret : OUT Fin<2>, s_result : OUT Fin<20>, aux : AUX Fin<2>, ctrl : AUX Arr<10, Fin<2>>, pred_out : AUX Arr<10, Fin<2>>, n_iter : AUX Arr<10, Fin<4>>, s_arg : AUX Arr<10, Fin<20>>) { + for (#run_ix in 0 .. < 10) { + n_iter[#run_ix] *= Distr[uniform : Fin<4>]; + pred_out[#run_ix] *= X; + pred_out[#run_ix] *= H; + s_arg[#run_ix] *= Distr[uniform : Fin<20>]; + for (#LIM in 0 .. < 4) { + n_iter[#run_ix], ctrl[#run_ix] *= Embed[(a) => (a <= #LIM)]; + call Oracle_U(s_arg[#run_ix], aux); + ctrl[#run_ix], aux, pred_out[#run_ix] *= Toffoli; + call-adj Oracle_U(s_arg[#run_ix], aux); + s_arg[#run_ix] *= Adj-Distr[uniform : Fin<20>]; + s_arg[#run_ix] *= PhaseOnZero(3.141592653589793); + s_arg[#run_ix] *= Distr[uniform : Fin<20>]; + n_iter[#run_ix], ctrl[#run_ix] *= Embed[(a) => (a <= #LIM)]; + } + pred_out[#run_ix] *= H; + pred_out[#run_ix] *= X; + n_iter[#run_ix] *= Adj-Distr[uniform : Fin<4>]; + ctrl[#run_ix] *= X; + call Oracle_U(s_arg[#run_ix], aux); + ctrl[#run_ix], aux, pred_out[#run_ix] *= Toffoli; + call-adj Oracle_U(s_arg[#run_ix], aux); + ctrl[#run_ix] *= X; + } + pred_out, ret *= Embed[(a) => multi_or a]; + s_arg, pred_out, s_result *= Embed[(a, f) => (a selectOn f)]; +} + +uproc main_U(ok : OUT Fin<2>, ok_1 : AUX Fin<2>, s_result : AUX Fin<20>, aux : AUX Fin<2>, ctrl : AUX Arr<10, Fin<2>>, pred_out : AUX Arr<10, Fin<2>>, n_iter : AUX Arr<10, Fin<4>>, s_arg : AUX Arr<10, Fin<20>>, aux_prim : AUX Fin<20>, aux_prim_1 : AUX Fin<2>, aux_prim_2 : AUX Arr<10, Fin<2>>, aux_prim_3 : AUX Arr<10, Fin<2>>, aux_prim_4 : AUX Arr<10, Fin<4>>, aux_prim_5 : AUX Arr<10, Fin<20>>) { + call UAny(ok_1, aux_prim, aux_prim_1, aux_prim_2, aux_prim_3, aux_prim_4, aux_prim_5); + ok, ok_1 *= SWAP; +} + +uproc Grover[k](x : IN Fin<20>, ret_1 : OUT Fin<2>) { + ret_1 *= X; + ret_1 *= H; + x *= Distr[uniform : Fin<20>]; + repeat (#k) { + call Oracle_U(x, ret_1); + x *= Adj-Distr[uniform : Fin<20>]; + x *= PhaseOnZero(3.141592653589793); + x *= Distr[uniform : Fin<20>]; + } + ret_1 *= H; + ret_1 *= X; +} + +proc QAny(ret_1 : Fin<2>) { locals : (s_result_1 : Fin<20>, not_done : Fin<2>, Q_sum : Fin<42>, j : Fin<42>, j_lim : Fin<42>) } { + repeat (5) { + Q_sum := const 0:Fin<42>; + for (j_lim in [const 1:Fin<42>, const 1:Fin<42>, const 1:Fin<42>, const 2:Fin<42>, const 2:Fin<42>, const 2:Fin<42>, const 3:Fin<42>, const 4:Fin<42>, const 4:Fin<42>, const 4:Fin<42>, const 4:Fin<42>, const 4:Fin<42>, const 4:Fin<42>, const 4:Fin<42>]) { + j :=$ [1 .. j_lim]; + Q_sum := (Q_sum + j); + not_done := (not_done && (Q_sum <= j_lim)); + if (not_done) { + meas Grover[j](s_result_1, ret_1); + meas Oracle_U(s_result_1, ret_1); + not_done := (not_done && ret_1); + } else { + skip; + } + } + } +} + +proc main(ok : Fin<2>) { locals : () } { + call QAny(ok); +} + + +// qubits: 194 diff --git a/examples/primitives/any.traq b/examples/primitives/any.traq index e3462506..fb7fe205 100644 --- a/examples/primitives/any.traq +++ b/examples/primitives/any.traq @@ -1,6 +1,6 @@ ext fn Oracle(Fin<20>) -> Bool end fn main() -> Bool do - ok <- @any[Oracle]() + ok <- @any>[Oracle(_)]; return ok end diff --git a/examples/primitives/any_q.qpl b/examples/primitives/any_q.qpl deleted file mode 100644 index dab213b4..00000000 --- a/examples/primitives/any_q.qpl +++ /dev/null @@ -1,37 +0,0 @@ -@Oracle -uproc Oracle[](in_0 : IN Fin<20>, out_0 : OUT Fin<2>); - -uproc Grover[#k](x : IN Fin<20>, ok : OUT Fin<2>) do - ok *= X; - ok *= H; - x *= Unif[Fin<20>]; - repeat #k do - call Oracle(x, ok); - x *= Unif†[Fin<20>]; - x *= (2|0><0| - I)[Fin<20>]; - x *= Unif[Fin<20>]; - end - ok *= H; - ok *= X; -end - -proc QSearch[5.0e-4][](ok: Fin<2>) { locals: (not_done: Fin<2>, Q_sum: Fin<42>, j: Fin<42>, j_lim: Fin<42>, x_1: Fin<20>) } do - repeat 7 do - Q_sum := 0 : Fin<42>; - for j_lim in [1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4] do - j :=$ [1 .. j_lim]; - Q_sum := (Q_sum + j); - not_done := (not_done && (Q_sum <= j_lim)); - if (not_done) then - call_uproc_and_meas Grover[j](x_1, ok); - call_uproc_and_meas Oracle[](x_1, ok); - not_done := (not_done && !ok); - else - skip; - end - end - end -end - -call QSearch[5.0e-4][](ok); - diff --git a/examples/primitives/any_u.qpl b/examples/primitives/any_u.qpl deleted file mode 100644 index 78f219ab..00000000 --- a/examples/primitives/any_u.qpl +++ /dev/null @@ -1,729 +0,0 @@ -// Cost : 1.0 -// Formula Cost : () -@Oracle -uproc Ctrl_Oracle[](ctrl : CTRL Fin<2>, in_0 : IN Fin<20>, out_0 : OUT Fin<2>); - -// Cost : 170.0 -// Formula Cost : () -uproc QSearch[20, 5.0e-4, Ctrl_Oracle][](ok : OUT Fin<2>, n_iter : AUX Fin<4>, ctrl_1 : AUX Fin<2>, s_arg : AUX Fin<20>, pred_out : AUX Fin<2>, n_iter_1 : AUX Fin<4>, ctrl_2 : AUX Fin<2>, s_arg_1 : AUX Fin<20>, pred_out_1 : AUX Fin<2>, n_iter_2 : AUX Fin<4>, ctrl_3 : AUX Fin<2>, s_arg_2 : AUX Fin<20>, pred_out_2 : AUX Fin<2>, n_iter_3 : AUX Fin<4>, ctrl_4 : AUX Fin<2>, s_arg_3 : AUX Fin<20>, pred_out_3 : AUX Fin<2>, n_iter_4 : AUX Fin<4>, ctrl_5 : AUX Fin<2>, s_arg_4 : AUX Fin<20>, pred_out_4 : AUX Fin<2>, n_iter_5 : AUX Fin<4>, ctrl_6 : AUX Fin<2>, s_arg_5 : AUX Fin<20>, pred_out_5 : AUX Fin<2>, n_iter_6 : AUX Fin<4>, ctrl_7 : AUX Fin<2>, s_arg_6 : AUX Fin<20>, pred_out_6 : AUX Fin<2>, n_iter_7 : AUX Fin<4>, ctrl_8 : AUX Fin<2>, s_arg_7 : AUX Fin<20>, pred_out_7 : AUX Fin<2>, n_iter_8 : AUX Fin<4>, ctrl_9 : AUX Fin<2>, s_arg_8 : AUX Fin<20>, pred_out_8 : AUX Fin<2>, n_iter_9 : AUX Fin<4>, ctrl_10 : AUX Fin<2>, s_arg_9 : AUX Fin<20>, pred_out_9 : AUX Fin<2>, n_iter_10 : AUX Fin<4>, ctrl_11 : AUX Fin<2>, s_arg_10 : AUX Fin<20>, pred_out_10 : AUX Fin<2>, n_iter_11 : AUX Fin<4>, ctrl_12 : AUX Fin<2>, s_arg_11 : AUX Fin<20>, pred_out_11 : AUX Fin<2>, n_iter_12 : AUX Fin<4>, ctrl_13 : AUX Fin<2>, s_arg_12 : AUX Fin<20>, pred_out_12 : AUX Fin<2>, n_iter_13 : AUX Fin<4>, ctrl_14 : AUX Fin<2>, s_arg_13 : AUX Fin<20>, pred_out_13 : AUX Fin<2>, n_iter_14 : AUX Fin<4>, ctrl_15 : AUX Fin<2>, s_arg_14 : AUX Fin<20>, pred_out_14 : AUX Fin<2>, n_iter_15 : AUX Fin<4>, ctrl_16 : AUX Fin<2>, s_arg_15 : AUX Fin<20>, pred_out_15 : AUX Fin<2>, n_iter_16 : AUX Fin<4>, ctrl_17 : AUX Fin<2>, s_arg_16 : AUX Fin<20>, pred_out_16 : AUX Fin<2>, n_iter_17 : AUX Fin<4>, ctrl_18 : AUX Fin<2>, s_arg_17 : AUX Fin<20>, pred_out_17 : AUX Fin<2>, n_iter_18 : AUX Fin<4>, ctrl_19 : AUX Fin<2>, s_arg_18 : AUX Fin<20>, pred_out_18 : AUX Fin<2>, n_iter_19 : AUX Fin<4>, ctrl_20 : AUX Fin<2>, s_arg_19 : AUX Fin<20>, pred_out_19 : AUX Fin<2>, n_iter_20 : AUX Fin<4>, ctrl_21 : AUX Fin<2>, s_arg_20 : AUX Fin<20>, pred_out_20 : AUX Fin<2>, n_iter_21 : AUX Fin<4>, ctrl_22 : AUX Fin<2>, s_arg_21 : AUX Fin<20>, pred_out_21 : AUX Fin<2>, n_iter_22 : AUX Fin<4>, ctrl_23 : AUX Fin<2>, s_arg_22 : AUX Fin<20>, pred_out_22 : AUX Fin<2>, n_iter_23 : AUX Fin<4>, ctrl_24 : AUX Fin<2>, s_arg_23 : AUX Fin<20>, pred_out_23 : AUX Fin<2>, n_iter_24 : AUX Fin<4>, ctrl_25 : AUX Fin<2>, s_arg_24 : AUX Fin<20>, pred_out_24 : AUX Fin<2>, n_iter_25 : AUX Fin<4>, ctrl_26 : AUX Fin<2>, s_arg_25 : AUX Fin<20>, pred_out_25 : AUX Fin<2>, n_iter_26 : AUX Fin<4>, ctrl_27 : AUX Fin<2>, s_arg_26 : AUX Fin<20>, pred_out_26 : AUX Fin<2>, n_iter_27 : AUX Fin<4>, ctrl_28 : AUX Fin<2>, s_arg_27 : AUX Fin<20>, pred_out_27 : AUX Fin<2>, n_iter_28 : AUX Fin<4>, ctrl_29 : AUX Fin<2>, s_arg_28 : AUX Fin<20>, pred_out_28 : AUX Fin<2>, n_iter_29 : AUX Fin<4>, ctrl_30 : AUX Fin<2>, s_arg_29 : AUX Fin<20>, pred_out_29 : AUX Fin<2>, n_iter_30 : AUX Fin<4>, ctrl_31 : AUX Fin<2>, s_arg_30 : AUX Fin<20>, pred_out_30 : AUX Fin<2>, n_iter_31 : AUX Fin<4>, ctrl_32 : AUX Fin<2>, s_arg_31 : AUX Fin<20>, pred_out_31 : AUX Fin<2>, n_iter_32 : AUX Fin<4>, ctrl_33 : AUX Fin<2>, s_arg_32 : AUX Fin<20>, pred_out_32 : AUX Fin<2>, n_iter_33 : AUX Fin<4>, ctrl_34 : AUX Fin<2>, s_arg_33 : AUX Fin<20>, pred_out_33 : AUX Fin<2>) do - // - // Run 1 - // - n_iter *= Unif[Fin<4>]; - pred_out *= X; - pred_out *= H; - s_arg *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter, ctrl_1 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_1, s_arg, pred_out); - s_arg *= Unif†[Fin<20>]; - s_arg *= (2|0><0| - I)[Fin<20>]; - s_arg *= Unif[Fin<20>]; - n_iter, ctrl_1 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out *= H; - pred_out *= X; - n_iter *= Unif†[Fin<4>]; - ctrl_1 *= X; - call Ctrl_Oracle(ctrl_1, s_arg, pred_out); - ctrl_1 *= X; - // - // Run 2 - // - n_iter_1 *= Unif[Fin<4>]; - pred_out_1 *= X; - pred_out_1 *= H; - s_arg_1 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_1, ctrl_2 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_2, s_arg_1, pred_out_1); - s_arg_1 *= Unif†[Fin<20>]; - s_arg_1 *= (2|0><0| - I)[Fin<20>]; - s_arg_1 *= Unif[Fin<20>]; - n_iter_1, ctrl_2 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_1 *= H; - pred_out_1 *= X; - n_iter_1 *= Unif†[Fin<4>]; - ctrl_2 *= X; - call Ctrl_Oracle(ctrl_2, s_arg_1, pred_out_1); - ctrl_2 *= X; - // - // Run 3 - // - n_iter_2 *= Unif[Fin<4>]; - pred_out_2 *= X; - pred_out_2 *= H; - s_arg_2 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_2, ctrl_3 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_3, s_arg_2, pred_out_2); - s_arg_2 *= Unif†[Fin<20>]; - s_arg_2 *= (2|0><0| - I)[Fin<20>]; - s_arg_2 *= Unif[Fin<20>]; - n_iter_2, ctrl_3 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_2 *= H; - pred_out_2 *= X; - n_iter_2 *= Unif†[Fin<4>]; - ctrl_3 *= X; - call Ctrl_Oracle(ctrl_3, s_arg_2, pred_out_2); - ctrl_3 *= X; - // - // Run 4 - // - n_iter_3 *= Unif[Fin<4>]; - pred_out_3 *= X; - pred_out_3 *= H; - s_arg_3 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_3, ctrl_4 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_4, s_arg_3, pred_out_3); - s_arg_3 *= Unif†[Fin<20>]; - s_arg_3 *= (2|0><0| - I)[Fin<20>]; - s_arg_3 *= Unif[Fin<20>]; - n_iter_3, ctrl_4 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_3 *= H; - pred_out_3 *= X; - n_iter_3 *= Unif†[Fin<4>]; - ctrl_4 *= X; - call Ctrl_Oracle(ctrl_4, s_arg_3, pred_out_3); - ctrl_4 *= X; - // - // Run 5 - // - n_iter_4 *= Unif[Fin<4>]; - pred_out_4 *= X; - pred_out_4 *= H; - s_arg_4 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_4, ctrl_5 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_5, s_arg_4, pred_out_4); - s_arg_4 *= Unif†[Fin<20>]; - s_arg_4 *= (2|0><0| - I)[Fin<20>]; - s_arg_4 *= Unif[Fin<20>]; - n_iter_4, ctrl_5 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_4 *= H; - pred_out_4 *= X; - n_iter_4 *= Unif†[Fin<4>]; - ctrl_5 *= X; - call Ctrl_Oracle(ctrl_5, s_arg_4, pred_out_4); - ctrl_5 *= X; - // - // Run 6 - // - n_iter_5 *= Unif[Fin<4>]; - pred_out_5 *= X; - pred_out_5 *= H; - s_arg_5 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_5, ctrl_6 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_6, s_arg_5, pred_out_5); - s_arg_5 *= Unif†[Fin<20>]; - s_arg_5 *= (2|0><0| - I)[Fin<20>]; - s_arg_5 *= Unif[Fin<20>]; - n_iter_5, ctrl_6 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_5 *= H; - pred_out_5 *= X; - n_iter_5 *= Unif†[Fin<4>]; - ctrl_6 *= X; - call Ctrl_Oracle(ctrl_6, s_arg_5, pred_out_5); - ctrl_6 *= X; - // - // Run 7 - // - n_iter_6 *= Unif[Fin<4>]; - pred_out_6 *= X; - pred_out_6 *= H; - s_arg_6 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_6, ctrl_7 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_7, s_arg_6, pred_out_6); - s_arg_6 *= Unif†[Fin<20>]; - s_arg_6 *= (2|0><0| - I)[Fin<20>]; - s_arg_6 *= Unif[Fin<20>]; - n_iter_6, ctrl_7 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_6 *= H; - pred_out_6 *= X; - n_iter_6 *= Unif†[Fin<4>]; - ctrl_7 *= X; - call Ctrl_Oracle(ctrl_7, s_arg_6, pred_out_6); - ctrl_7 *= X; - // - // Run 8 - // - n_iter_7 *= Unif[Fin<4>]; - pred_out_7 *= X; - pred_out_7 *= H; - s_arg_7 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_7, ctrl_8 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_8, s_arg_7, pred_out_7); - s_arg_7 *= Unif†[Fin<20>]; - s_arg_7 *= (2|0><0| - I)[Fin<20>]; - s_arg_7 *= Unif[Fin<20>]; - n_iter_7, ctrl_8 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_7 *= H; - pred_out_7 *= X; - n_iter_7 *= Unif†[Fin<4>]; - ctrl_8 *= X; - call Ctrl_Oracle(ctrl_8, s_arg_7, pred_out_7); - ctrl_8 *= X; - // - // Run 9 - // - n_iter_8 *= Unif[Fin<4>]; - pred_out_8 *= X; - pred_out_8 *= H; - s_arg_8 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_8, ctrl_9 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_9, s_arg_8, pred_out_8); - s_arg_8 *= Unif†[Fin<20>]; - s_arg_8 *= (2|0><0| - I)[Fin<20>]; - s_arg_8 *= Unif[Fin<20>]; - n_iter_8, ctrl_9 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_8 *= H; - pred_out_8 *= X; - n_iter_8 *= Unif†[Fin<4>]; - ctrl_9 *= X; - call Ctrl_Oracle(ctrl_9, s_arg_8, pred_out_8); - ctrl_9 *= X; - // - // Run 10 - // - n_iter_9 *= Unif[Fin<4>]; - pred_out_9 *= X; - pred_out_9 *= H; - s_arg_9 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_9, ctrl_10 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_10, s_arg_9, pred_out_9); - s_arg_9 *= Unif†[Fin<20>]; - s_arg_9 *= (2|0><0| - I)[Fin<20>]; - s_arg_9 *= Unif[Fin<20>]; - n_iter_9, ctrl_10 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_9 *= H; - pred_out_9 *= X; - n_iter_9 *= Unif†[Fin<4>]; - ctrl_10 *= X; - call Ctrl_Oracle(ctrl_10, s_arg_9, pred_out_9); - ctrl_10 *= X; - // - // Run 11 - // - n_iter_10 *= Unif[Fin<4>]; - pred_out_10 *= X; - pred_out_10 *= H; - s_arg_10 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_10, ctrl_11 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_11, s_arg_10, pred_out_10); - s_arg_10 *= Unif†[Fin<20>]; - s_arg_10 *= (2|0><0| - I)[Fin<20>]; - s_arg_10 *= Unif[Fin<20>]; - n_iter_10, ctrl_11 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_10 *= H; - pred_out_10 *= X; - n_iter_10 *= Unif†[Fin<4>]; - ctrl_11 *= X; - call Ctrl_Oracle(ctrl_11, s_arg_10, pred_out_10); - ctrl_11 *= X; - // - // Run 12 - // - n_iter_11 *= Unif[Fin<4>]; - pred_out_11 *= X; - pred_out_11 *= H; - s_arg_11 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_11, ctrl_12 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_12, s_arg_11, pred_out_11); - s_arg_11 *= Unif†[Fin<20>]; - s_arg_11 *= (2|0><0| - I)[Fin<20>]; - s_arg_11 *= Unif[Fin<20>]; - n_iter_11, ctrl_12 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_11 *= H; - pred_out_11 *= X; - n_iter_11 *= Unif†[Fin<4>]; - ctrl_12 *= X; - call Ctrl_Oracle(ctrl_12, s_arg_11, pred_out_11); - ctrl_12 *= X; - // - // Run 13 - // - n_iter_12 *= Unif[Fin<4>]; - pred_out_12 *= X; - pred_out_12 *= H; - s_arg_12 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_12, ctrl_13 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_13, s_arg_12, pred_out_12); - s_arg_12 *= Unif†[Fin<20>]; - s_arg_12 *= (2|0><0| - I)[Fin<20>]; - s_arg_12 *= Unif[Fin<20>]; - n_iter_12, ctrl_13 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_12 *= H; - pred_out_12 *= X; - n_iter_12 *= Unif†[Fin<4>]; - ctrl_13 *= X; - call Ctrl_Oracle(ctrl_13, s_arg_12, pred_out_12); - ctrl_13 *= X; - // - // Run 14 - // - n_iter_13 *= Unif[Fin<4>]; - pred_out_13 *= X; - pred_out_13 *= H; - s_arg_13 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_13, ctrl_14 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_14, s_arg_13, pred_out_13); - s_arg_13 *= Unif†[Fin<20>]; - s_arg_13 *= (2|0><0| - I)[Fin<20>]; - s_arg_13 *= Unif[Fin<20>]; - n_iter_13, ctrl_14 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_13 *= H; - pred_out_13 *= X; - n_iter_13 *= Unif†[Fin<4>]; - ctrl_14 *= X; - call Ctrl_Oracle(ctrl_14, s_arg_13, pred_out_13); - ctrl_14 *= X; - // - // Run 15 - // - n_iter_14 *= Unif[Fin<4>]; - pred_out_14 *= X; - pred_out_14 *= H; - s_arg_14 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_14, ctrl_15 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_15, s_arg_14, pred_out_14); - s_arg_14 *= Unif†[Fin<20>]; - s_arg_14 *= (2|0><0| - I)[Fin<20>]; - s_arg_14 *= Unif[Fin<20>]; - n_iter_14, ctrl_15 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_14 *= H; - pred_out_14 *= X; - n_iter_14 *= Unif†[Fin<4>]; - ctrl_15 *= X; - call Ctrl_Oracle(ctrl_15, s_arg_14, pred_out_14); - ctrl_15 *= X; - // - // Run 16 - // - n_iter_15 *= Unif[Fin<4>]; - pred_out_15 *= X; - pred_out_15 *= H; - s_arg_15 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_15, ctrl_16 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_16, s_arg_15, pred_out_15); - s_arg_15 *= Unif†[Fin<20>]; - s_arg_15 *= (2|0><0| - I)[Fin<20>]; - s_arg_15 *= Unif[Fin<20>]; - n_iter_15, ctrl_16 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_15 *= H; - pred_out_15 *= X; - n_iter_15 *= Unif†[Fin<4>]; - ctrl_16 *= X; - call Ctrl_Oracle(ctrl_16, s_arg_15, pred_out_15); - ctrl_16 *= X; - // - // Run 17 - // - n_iter_16 *= Unif[Fin<4>]; - pred_out_16 *= X; - pred_out_16 *= H; - s_arg_16 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_16, ctrl_17 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_17, s_arg_16, pred_out_16); - s_arg_16 *= Unif†[Fin<20>]; - s_arg_16 *= (2|0><0| - I)[Fin<20>]; - s_arg_16 *= Unif[Fin<20>]; - n_iter_16, ctrl_17 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_16 *= H; - pred_out_16 *= X; - n_iter_16 *= Unif†[Fin<4>]; - ctrl_17 *= X; - call Ctrl_Oracle(ctrl_17, s_arg_16, pred_out_16); - ctrl_17 *= X; - // - // Run 18 - // - n_iter_17 *= Unif[Fin<4>]; - pred_out_17 *= X; - pred_out_17 *= H; - s_arg_17 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_17, ctrl_18 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_18, s_arg_17, pred_out_17); - s_arg_17 *= Unif†[Fin<20>]; - s_arg_17 *= (2|0><0| - I)[Fin<20>]; - s_arg_17 *= Unif[Fin<20>]; - n_iter_17, ctrl_18 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_17 *= H; - pred_out_17 *= X; - n_iter_17 *= Unif†[Fin<4>]; - ctrl_18 *= X; - call Ctrl_Oracle(ctrl_18, s_arg_17, pred_out_17); - ctrl_18 *= X; - // - // Run 19 - // - n_iter_18 *= Unif[Fin<4>]; - pred_out_18 *= X; - pred_out_18 *= H; - s_arg_18 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_18, ctrl_19 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_19, s_arg_18, pred_out_18); - s_arg_18 *= Unif†[Fin<20>]; - s_arg_18 *= (2|0><0| - I)[Fin<20>]; - s_arg_18 *= Unif[Fin<20>]; - n_iter_18, ctrl_19 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_18 *= H; - pred_out_18 *= X; - n_iter_18 *= Unif†[Fin<4>]; - ctrl_19 *= X; - call Ctrl_Oracle(ctrl_19, s_arg_18, pred_out_18); - ctrl_19 *= X; - // - // Run 20 - // - n_iter_19 *= Unif[Fin<4>]; - pred_out_19 *= X; - pred_out_19 *= H; - s_arg_19 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_19, ctrl_20 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_20, s_arg_19, pred_out_19); - s_arg_19 *= Unif†[Fin<20>]; - s_arg_19 *= (2|0><0| - I)[Fin<20>]; - s_arg_19 *= Unif[Fin<20>]; - n_iter_19, ctrl_20 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_19 *= H; - pred_out_19 *= X; - n_iter_19 *= Unif†[Fin<4>]; - ctrl_20 *= X; - call Ctrl_Oracle(ctrl_20, s_arg_19, pred_out_19); - ctrl_20 *= X; - // - // Run 21 - // - n_iter_20 *= Unif[Fin<4>]; - pred_out_20 *= X; - pred_out_20 *= H; - s_arg_20 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_20, ctrl_21 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_21, s_arg_20, pred_out_20); - s_arg_20 *= Unif†[Fin<20>]; - s_arg_20 *= (2|0><0| - I)[Fin<20>]; - s_arg_20 *= Unif[Fin<20>]; - n_iter_20, ctrl_21 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_20 *= H; - pred_out_20 *= X; - n_iter_20 *= Unif†[Fin<4>]; - ctrl_21 *= X; - call Ctrl_Oracle(ctrl_21, s_arg_20, pred_out_20); - ctrl_21 *= X; - // - // Run 22 - // - n_iter_21 *= Unif[Fin<4>]; - pred_out_21 *= X; - pred_out_21 *= H; - s_arg_21 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_21, ctrl_22 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_22, s_arg_21, pred_out_21); - s_arg_21 *= Unif†[Fin<20>]; - s_arg_21 *= (2|0><0| - I)[Fin<20>]; - s_arg_21 *= Unif[Fin<20>]; - n_iter_21, ctrl_22 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_21 *= H; - pred_out_21 *= X; - n_iter_21 *= Unif†[Fin<4>]; - ctrl_22 *= X; - call Ctrl_Oracle(ctrl_22, s_arg_21, pred_out_21); - ctrl_22 *= X; - // - // Run 23 - // - n_iter_22 *= Unif[Fin<4>]; - pred_out_22 *= X; - pred_out_22 *= H; - s_arg_22 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_22, ctrl_23 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_23, s_arg_22, pred_out_22); - s_arg_22 *= Unif†[Fin<20>]; - s_arg_22 *= (2|0><0| - I)[Fin<20>]; - s_arg_22 *= Unif[Fin<20>]; - n_iter_22, ctrl_23 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_22 *= H; - pred_out_22 *= X; - n_iter_22 *= Unif†[Fin<4>]; - ctrl_23 *= X; - call Ctrl_Oracle(ctrl_23, s_arg_22, pred_out_22); - ctrl_23 *= X; - // - // Run 24 - // - n_iter_23 *= Unif[Fin<4>]; - pred_out_23 *= X; - pred_out_23 *= H; - s_arg_23 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_23, ctrl_24 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_24, s_arg_23, pred_out_23); - s_arg_23 *= Unif†[Fin<20>]; - s_arg_23 *= (2|0><0| - I)[Fin<20>]; - s_arg_23 *= Unif[Fin<20>]; - n_iter_23, ctrl_24 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_23 *= H; - pred_out_23 *= X; - n_iter_23 *= Unif†[Fin<4>]; - ctrl_24 *= X; - call Ctrl_Oracle(ctrl_24, s_arg_23, pred_out_23); - ctrl_24 *= X; - // - // Run 25 - // - n_iter_24 *= Unif[Fin<4>]; - pred_out_24 *= X; - pred_out_24 *= H; - s_arg_24 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_24, ctrl_25 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_25, s_arg_24, pred_out_24); - s_arg_24 *= Unif†[Fin<20>]; - s_arg_24 *= (2|0><0| - I)[Fin<20>]; - s_arg_24 *= Unif[Fin<20>]; - n_iter_24, ctrl_25 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_24 *= H; - pred_out_24 *= X; - n_iter_24 *= Unif†[Fin<4>]; - ctrl_25 *= X; - call Ctrl_Oracle(ctrl_25, s_arg_24, pred_out_24); - ctrl_25 *= X; - // - // Run 26 - // - n_iter_25 *= Unif[Fin<4>]; - pred_out_25 *= X; - pred_out_25 *= H; - s_arg_25 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_25, ctrl_26 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_26, s_arg_25, pred_out_25); - s_arg_25 *= Unif†[Fin<20>]; - s_arg_25 *= (2|0><0| - I)[Fin<20>]; - s_arg_25 *= Unif[Fin<20>]; - n_iter_25, ctrl_26 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_25 *= H; - pred_out_25 *= X; - n_iter_25 *= Unif†[Fin<4>]; - ctrl_26 *= X; - call Ctrl_Oracle(ctrl_26, s_arg_25, pred_out_25); - ctrl_26 *= X; - // - // Run 27 - // - n_iter_26 *= Unif[Fin<4>]; - pred_out_26 *= X; - pred_out_26 *= H; - s_arg_26 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_26, ctrl_27 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_27, s_arg_26, pred_out_26); - s_arg_26 *= Unif†[Fin<20>]; - s_arg_26 *= (2|0><0| - I)[Fin<20>]; - s_arg_26 *= Unif[Fin<20>]; - n_iter_26, ctrl_27 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_26 *= H; - pred_out_26 *= X; - n_iter_26 *= Unif†[Fin<4>]; - ctrl_27 *= X; - call Ctrl_Oracle(ctrl_27, s_arg_26, pred_out_26); - ctrl_27 *= X; - // - // Run 28 - // - n_iter_27 *= Unif[Fin<4>]; - pred_out_27 *= X; - pred_out_27 *= H; - s_arg_27 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_27, ctrl_28 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_28, s_arg_27, pred_out_27); - s_arg_27 *= Unif†[Fin<20>]; - s_arg_27 *= (2|0><0| - I)[Fin<20>]; - s_arg_27 *= Unif[Fin<20>]; - n_iter_27, ctrl_28 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_27 *= H; - pred_out_27 *= X; - n_iter_27 *= Unif†[Fin<4>]; - ctrl_28 *= X; - call Ctrl_Oracle(ctrl_28, s_arg_27, pred_out_27); - ctrl_28 *= X; - // - // Run 29 - // - n_iter_28 *= Unif[Fin<4>]; - pred_out_28 *= X; - pred_out_28 *= H; - s_arg_28 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_28, ctrl_29 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_29, s_arg_28, pred_out_28); - s_arg_28 *= Unif†[Fin<20>]; - s_arg_28 *= (2|0><0| - I)[Fin<20>]; - s_arg_28 *= Unif[Fin<20>]; - n_iter_28, ctrl_29 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_28 *= H; - pred_out_28 *= X; - n_iter_28 *= Unif†[Fin<4>]; - ctrl_29 *= X; - call Ctrl_Oracle(ctrl_29, s_arg_28, pred_out_28); - ctrl_29 *= X; - // - // Run 30 - // - n_iter_29 *= Unif[Fin<4>]; - pred_out_29 *= X; - pred_out_29 *= H; - s_arg_29 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_29, ctrl_30 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_30, s_arg_29, pred_out_29); - s_arg_29 *= Unif†[Fin<20>]; - s_arg_29 *= (2|0><0| - I)[Fin<20>]; - s_arg_29 *= Unif[Fin<20>]; - n_iter_29, ctrl_30 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_29 *= H; - pred_out_29 *= X; - n_iter_29 *= Unif†[Fin<4>]; - ctrl_30 *= X; - call Ctrl_Oracle(ctrl_30, s_arg_29, pred_out_29); - ctrl_30 *= X; - // - // Run 31 - // - n_iter_30 *= Unif[Fin<4>]; - pred_out_30 *= X; - pred_out_30 *= H; - s_arg_30 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_30, ctrl_31 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_31, s_arg_30, pred_out_30); - s_arg_30 *= Unif†[Fin<20>]; - s_arg_30 *= (2|0><0| - I)[Fin<20>]; - s_arg_30 *= Unif[Fin<20>]; - n_iter_30, ctrl_31 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_30 *= H; - pred_out_30 *= X; - n_iter_30 *= Unif†[Fin<4>]; - ctrl_31 *= X; - call Ctrl_Oracle(ctrl_31, s_arg_30, pred_out_30); - ctrl_31 *= X; - // - // Run 32 - // - n_iter_31 *= Unif[Fin<4>]; - pred_out_31 *= X; - pred_out_31 *= H; - s_arg_31 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_31, ctrl_32 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_32, s_arg_31, pred_out_31); - s_arg_31 *= Unif†[Fin<20>]; - s_arg_31 *= (2|0><0| - I)[Fin<20>]; - s_arg_31 *= Unif[Fin<20>]; - n_iter_31, ctrl_32 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_31 *= H; - pred_out_31 *= X; - n_iter_31 *= Unif†[Fin<4>]; - ctrl_32 *= X; - call Ctrl_Oracle(ctrl_32, s_arg_31, pred_out_31); - ctrl_32 *= X; - // - // Run 33 - // - n_iter_32 *= Unif[Fin<4>]; - pred_out_32 *= X; - pred_out_32 *= H; - s_arg_32 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_32, ctrl_33 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_33, s_arg_32, pred_out_32); - s_arg_32 *= Unif†[Fin<20>]; - s_arg_32 *= (2|0><0| - I)[Fin<20>]; - s_arg_32 *= Unif[Fin<20>]; - n_iter_32, ctrl_33 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_32 *= H; - pred_out_32 *= X; - n_iter_32 *= Unif†[Fin<4>]; - ctrl_33 *= X; - call Ctrl_Oracle(ctrl_33, s_arg_32, pred_out_32); - ctrl_33 *= X; - // - // Run 34 - // - n_iter_33 *= Unif[Fin<4>]; - pred_out_33 *= X; - pred_out_33 *= H; - s_arg_33 *= Unif[Fin<20>]; - for #LIM in 0 .. < 4 do - n_iter_33, ctrl_34 *= RevEmbed[x : Fin<4> => x≤#LIM]; - call Ctrl_Oracle(ctrl_34, s_arg_33, pred_out_33); - s_arg_33 *= Unif†[Fin<20>]; - s_arg_33 *= (2|0><0| - I)[Fin<20>]; - s_arg_33 *= Unif[Fin<20>]; - n_iter_33, ctrl_34 *= RevEmbed[x : Fin<4> => x≤#LIM]; - end - pred_out_33 *= H; - pred_out_33 *= X; - n_iter_33 *= Unif†[Fin<4>]; - ctrl_34 *= X; - call Ctrl_Oracle(ctrl_34, s_arg_33, pred_out_33); - ctrl_34 *= X; - pred_out, pred_out_1, pred_out_2, pred_out_3, pred_out_4, pred_out_5, pred_out_6, pred_out_7, pred_out_8, pred_out_9, pred_out_10, pred_out_11, pred_out_12, pred_out_13, pred_out_14, pred_out_15, pred_out_16, pred_out_17, pred_out_18, pred_out_19, pred_out_20, pred_out_21, pred_out_22, pred_out_23, pred_out_24, pred_out_25, pred_out_26, pred_out_27, pred_out_28, pred_out_29, pred_out_30, pred_out_31, pred_out_32, pred_out_33, ok *= RevEmbed[(x) => OR_34(x)]; -end - -// Actual Cost : 170.0 -// Formula Cost: 267.22995 -call QSearch[20, 5.0e-4, Ctrl_Oracle](ok, n_iter, ctrl_1, s_arg, pred_out, n_iter_1, ctrl_2, s_arg_1, pred_out_1, n_iter_2, ctrl_3, s_arg_2, pred_out_2, n_iter_3, ctrl_4, s_arg_3, pred_out_3, n_iter_4, ctrl_5, s_arg_4, pred_out_4, n_iter_5, ctrl_6, s_arg_5, pred_out_5, n_iter_6, ctrl_7, s_arg_6, pred_out_6, n_iter_7, ctrl_8, s_arg_7, pred_out_7, n_iter_8, ctrl_9, s_arg_8, pred_out_8, n_iter_9, ctrl_10, s_arg_9, pred_out_9, n_iter_10, ctrl_11, s_arg_10, pred_out_10, n_iter_11, ctrl_12, s_arg_11, pred_out_11, n_iter_12, ctrl_13, s_arg_12, pred_out_12, n_iter_13, ctrl_14, s_arg_13, pred_out_13, n_iter_14, ctrl_15, s_arg_14, pred_out_14, n_iter_15, ctrl_16, s_arg_15, pred_out_15, n_iter_16, ctrl_17, s_arg_16, pred_out_16, n_iter_17, ctrl_18, s_arg_17, pred_out_17, n_iter_18, ctrl_19, s_arg_18, pred_out_18, n_iter_19, ctrl_20, s_arg_19, pred_out_19, n_iter_20, ctrl_21, s_arg_20, pred_out_20, n_iter_21, ctrl_22, s_arg_21, pred_out_21, n_iter_22, ctrl_23, s_arg_22, pred_out_22, n_iter_23, ctrl_24, s_arg_23, pred_out_23, n_iter_24, ctrl_25, s_arg_24, pred_out_24, n_iter_25, ctrl_26, s_arg_25, pred_out_25, n_iter_26, ctrl_27, s_arg_26, pred_out_26, n_iter_27, ctrl_28, s_arg_27, pred_out_27, n_iter_28, ctrl_29, s_arg_28, pred_out_28, n_iter_29, ctrl_30, s_arg_29, pred_out_29, n_iter_30, ctrl_31, s_arg_30, pred_out_30, n_iter_31, ctrl_32, s_arg_31, pred_out_31, n_iter_32, ctrl_33, s_arg_32, pred_out_32, n_iter_33, ctrl_34, s_arg_33, pred_out_33); - diff --git a/examples/primitives/max.qpl b/examples/primitives/max.qpl index 728422f9..957757f5 100644 --- a/examples/primitives/max.qpl +++ b/examples/primitives/max.qpl @@ -6,7 +6,8 @@ uproc UMax(ret : Fin<30>, ret_1 : Fin<20>, inp : AUX Arr<20, Fin<20>>, out : AUX for (#x_2 in Fin<20>) { call Oracle_U(inp[#x_2], out[#x_2]); } - // unitarily compute: ret := max(out); ret_1 := argmax(out); + out, ret *= NamedGate("max"); + out, ret_1 *= NamedGate("argmax"); } uproc main_U(y : OUT Fin<30>, x : AUX Fin<20>, y_1 : AUX Fin<30>, x_1 : AUX Fin<20>, aux_prim : AUX Arr<20, Fin<20>>, aux_prim_1 : AUX Arr<20, Fin<30>>) { diff --git a/examples/search/clustering.qpl b/examples/search/clustering.qpl index 5bde3122..b4fe8cb8 100644 --- a/examples/search/clustering.qpl +++ b/examples/search/clustering.qpl @@ -30,7 +30,6 @@ proc check(dmax : Fin<100>, ij : Tup, Fin<10>>, ok : Fin<2>) { locals : ok := (dmax < dist'); } -// USearch[Tup [Fin 10,Fin 10], 2.5e-4] uproc USearch(dmax : Fin<100>, ret : OUT Fin<2>, ret_1 : OUT Tup, Fin<10>>, aux : AUX Fin<10>, aux_1 : AUX Fin<10>, aux_2 : AUX Arr<10, Fin<100>>, aux_3 : AUX Arr<10, Fin<100>>, aux_4 : AUX Fin<100>, aux_5 : AUX Fin<10>, aux_6 : AUX Fin<10>, aux_7 : AUX Arr<10, Fin<100>>, aux_8 : AUX Arr<10, Fin<100>>, aux_9 : AUX Fin<100>, aux_10 : AUX Fin<2>, aux_11 : AUX Fin<2>, ctrl : AUX Arr<17, Fin<2>>, pred_out : AUX Arr<17, Fin<2>>, n_iter : AUX Arr<17, Fin<8>>, s_arg : AUX Arr<17, Tup, Fin<10>>>) { for (#run_ix in 0 .. < 17) { n_iter[#run_ix] *= Distr[uniform : Fin<8>]; @@ -75,7 +74,6 @@ uproc loop_body_U(i : IN Fin<10>, j : IN Fin<10>, i' : OUT Fin<10>, j' : OUT Fin j', j'_1 *= SWAP; } -// Grover[...] uproc Grover[k](dmax : Fin<100>, x : IN Tup, Fin<10>>, ret_2 : OUT Fin<2>, aux_12 : AUX Fin<10>, aux_13 : AUX Fin<10>, aux_14 : AUX Arr<10, Fin<100>>, aux_15 : AUX Arr<10, Fin<100>>, aux_16 : AUX Fin<100>, aux_17 : AUX Fin<10>, aux_18 : AUX Fin<10>, aux_19 : AUX Arr<10, Fin<100>>, aux_20 : AUX Arr<10, Fin<100>>, aux_21 : AUX Fin<100>, aux_22 : AUX Fin<2>) { ret_2 *= X; ret_2 *= H; diff --git a/examples/search/triangle_finding.qpl b/examples/search/triangle_finding.qpl index 9f2240c8..7ba7ebb5 100644 --- a/examples/search/triangle_finding.qpl +++ b/examples/search/triangle_finding.qpl @@ -44,7 +44,6 @@ proc CompletesTriangle(i : Fin<10>, j : Fin<10>, k : Fin<10>, result : Fin<2>) { result := (temp && edge_ki); } -// UAny[Fin 10, 5.640182571230681e-14] uproc UAny(i : Fin<10>, j : Fin<10>, ret : OUT Fin<2>, s_result : OUT Fin<10>, aux : AUX Fin<2>, aux_1 : AUX Fin<2>, aux_2 : AUX Fin<2>, aux_3 : AUX Fin<2>, aux_4 : AUX Fin<2>, aux_5 : AUX Fin<2>, aux_6 : AUX Fin<2>, aux_7 : AUX Fin<2>, aux_8 : AUX Fin<2>, aux_9 : AUX Fin<2>, aux_10 : AUX Fin<2>, aux_11 : AUX Fin<2>, aux_12 : AUX Fin<2>, aux_13 : AUX Fin<2>, aux_14 : AUX Fin<2>, aux_15 : AUX Fin<2>, aux_16 : AUX Fin<2>, aux_17 : AUX Fin<2>, aux_18 : AUX Fin<2>, aux_19 : AUX Fin<2>, aux_20 : AUX Fin<2>, aux_21 : AUX Fin<2>, aux_22 : AUX Fin<2>, aux_23 : AUX Fin<2>, ctrl : AUX Arr<62, Fin<2>>, pred_out : AUX Arr<62, Fin<2>>, n_iter : AUX Arr<62, Fin<3>>, s_arg : AUX Arr<62, Fin<10>>) { for (#run_ix in 0 .. < 62) { n_iter[#run_ix] *= Distr[uniform : Fin<3>]; @@ -87,7 +86,6 @@ uproc HasTriangleCycle_U(ij : IN Tup, Fin<10>>, result : OUT Fin<2>, i : result, result_2 *= SWAP; } -// Grover[...] uproc Grover[k](i : Fin<10>, j : Fin<10>, x : IN Fin<10>, ret_1 : OUT Fin<2>, aux_24 : AUX Fin<2>, aux_25 : AUX Fin<2>, aux_26 : AUX Fin<2>, aux_27 : AUX Fin<2>, aux_28 : AUX Fin<2>, aux_29 : AUX Fin<2>, aux_30 : AUX Fin<2>, aux_31 : AUX Fin<2>, aux_32 : AUX Fin<2>, aux_33 : AUX Fin<2>, aux_34 : AUX Fin<2>, aux_35 : AUX Fin<2>, aux_36 : AUX Fin<2>, aux_37 : AUX Fin<2>, aux_38 : AUX Fin<2>, aux_39 : AUX Fin<2>, aux_40 : AUX Fin<2>, aux_41 : AUX Fin<2>, aux_42 : AUX Fin<2>, aux_43 : AUX Fin<2>, aux_44 : AUX Fin<2>, aux_45 : AUX Fin<2>, aux_46 : AUX Fin<2>) { ret_1 *= X; ret_1 *= H; @@ -128,7 +126,6 @@ proc HasTriangleCycle(ij : Tup, Fin<10>>, result : Fin<2>) { locals : (i result := (edge_ij && found_k); } -// UAny[Tup [Fin 10,Fin 10], 5.0e-4] uproc UAny_1(ret_2 : OUT Fin<2>, s_result_2 : OUT Tup, Fin<10>>, aux_47 : AUX Fin<10>, aux_48 : AUX Fin<10>, aux_49 : AUX Fin<2>, aux_50 : AUX Fin<2>, aux_51 : AUX Fin<10>, aux_52 : AUX Fin<10>, aux_53 : AUX Fin<2>, aux_54 : AUX Fin<2>, aux_55 : AUX Fin<10>, aux_56 : AUX Fin<2>, aux_57 : AUX Fin<2>, aux_58 : AUX Fin<2>, aux_59 : AUX Fin<2>, aux_60 : AUX Fin<2>, aux_61 : AUX Fin<2>, aux_62 : AUX Fin<2>, aux_63 : AUX Fin<2>, aux_64 : AUX Fin<2>, aux_65 : AUX Fin<2>, aux_66 : AUX Fin<2>, aux_67 : AUX Fin<2>, aux_68 : AUX Fin<2>, aux_69 : AUX Fin<2>, aux_70 : AUX Fin<2>, aux_71 : AUX Fin<2>, aux_72 : AUX Fin<2>, aux_73 : AUX Fin<2>, aux_74 : AUX Fin<2>, aux_75 : AUX Fin<2>, aux_76 : AUX Fin<2>, aux_77 : AUX Fin<2>, aux_78 : AUX Fin<2>, aux_79 : AUX Fin<2>, aux_80 : AUX Arr<62, Fin<2>>, aux_81 : AUX Arr<62, Fin<2>>, aux_82 : AUX Arr<62, Fin<3>>, aux_83 : AUX Arr<62, Fin<10>>, aux_84 : AUX Fin<10>, aux_85 : AUX Fin<2>, aux_86 : AUX Fin<2>, aux_87 : AUX Fin<2>, aux_88 : AUX Fin<2>, aux_89 : AUX Fin<2>, aux_90 : AUX Fin<2>, aux_91 : AUX Fin<2>, aux_92 : AUX Fin<2>, aux_93 : AUX Fin<2>, aux_94 : AUX Fin<2>, aux_95 : AUX Fin<2>, aux_96 : AUX Fin<2>, aux_97 : AUX Fin<2>, aux_98 : AUX Fin<2>, aux_99 : AUX Fin<2>, aux_100 : AUX Fin<2>, aux_101 : AUX Fin<2>, aux_102 : AUX Fin<2>, aux_103 : AUX Fin<2>, aux_104 : AUX Fin<2>, aux_105 : AUX Fin<2>, aux_106 : AUX Fin<2>, aux_107 : AUX Fin<2>, aux_108 : AUX Fin<2>, aux_109 : AUX Arr<62, Fin<2>>, aux_110 : AUX Arr<62, Fin<2>>, aux_111 : AUX Arr<62, Fin<3>>, aux_112 : AUX Arr<62, Fin<10>>, aux_113 : AUX Fin<2>, aux_114 : AUX Fin<2>, ctrl_1 : AUX Arr<16, Fin<2>>, pred_out_1 : AUX Arr<16, Fin<2>>, n_iter_1 : AUX Arr<16, Fin<8>>, s_arg_1 : AUX Arr<16, Tup, Fin<10>>>) { for (#run_ix in 0 .. < 16) { n_iter_1[#run_ix] *= Distr[uniform : Fin<8>]; @@ -163,7 +160,6 @@ uproc HasTriangle_U(found_triangle : OUT Fin<2>, found_triangle_1 : AUX Fin<2>, found_triangle, found_triangle_1 *= SWAP; } -// Grover[...] uproc Grover_1[k](x_1 : IN Tup, Fin<10>>, ret_3 : OUT Fin<2>, aux_115 : AUX Fin<10>, aux_116 : AUX Fin<10>, aux_117 : AUX Fin<2>, aux_118 : AUX Fin<2>, aux_119 : AUX Fin<10>, aux_120 : AUX Fin<10>, aux_121 : AUX Fin<2>, aux_122 : AUX Fin<2>, aux_123 : AUX Fin<10>, aux_124 : AUX Fin<2>, aux_125 : AUX Fin<2>, aux_126 : AUX Fin<2>, aux_127 : AUX Fin<2>, aux_128 : AUX Fin<2>, aux_129 : AUX Fin<2>, aux_130 : AUX Fin<2>, aux_131 : AUX Fin<2>, aux_132 : AUX Fin<2>, aux_133 : AUX Fin<2>, aux_134 : AUX Fin<2>, aux_135 : AUX Fin<2>, aux_136 : AUX Fin<2>, aux_137 : AUX Fin<2>, aux_138 : AUX Fin<2>, aux_139 : AUX Fin<2>, aux_140 : AUX Fin<2>, aux_141 : AUX Fin<2>, aux_142 : AUX Fin<2>, aux_143 : AUX Fin<2>, aux_144 : AUX Fin<2>, aux_145 : AUX Fin<2>, aux_146 : AUX Fin<2>, aux_147 : AUX Fin<2>, aux_148 : AUX Arr<62, Fin<2>>, aux_149 : AUX Arr<62, Fin<2>>, aux_150 : AUX Arr<62, Fin<3>>, aux_151 : AUX Arr<62, Fin<10>>, aux_152 : AUX Fin<10>, aux_153 : AUX Fin<2>, aux_154 : AUX Fin<2>, aux_155 : AUX Fin<2>, aux_156 : AUX Fin<2>, aux_157 : AUX Fin<2>, aux_158 : AUX Fin<2>, aux_159 : AUX Fin<2>, aux_160 : AUX Fin<2>, aux_161 : AUX Fin<2>, aux_162 : AUX Fin<2>, aux_163 : AUX Fin<2>, aux_164 : AUX Fin<2>, aux_165 : AUX Fin<2>, aux_166 : AUX Fin<2>, aux_167 : AUX Fin<2>, aux_168 : AUX Fin<2>, aux_169 : AUX Fin<2>, aux_170 : AUX Fin<2>, aux_171 : AUX Fin<2>, aux_172 : AUX Fin<2>, aux_173 : AUX Fin<2>, aux_174 : AUX Fin<2>, aux_175 : AUX Fin<2>, aux_176 : AUX Fin<2>, aux_177 : AUX Arr<62, Fin<2>>, aux_178 : AUX Arr<62, Fin<2>>, aux_179 : AUX Arr<62, Fin<3>>, aux_180 : AUX Arr<62, Fin<10>>, aux_181 : AUX Fin<2>) { ret_3 *= X; ret_3 *= H; diff --git a/src/Traq/Compiler/Prelude.hs b/src/Traq/Compiler/Prelude.hs index 56eb4974..6fd65aae 100644 --- a/src/Traq/Compiler/Prelude.hs +++ b/src/Traq/Compiler/Prelude.hs @@ -261,8 +261,7 @@ buildProcHelper is_uproc proc_name_basic proc_meta_params params m = do ([], _, False) -> pure $ QPL.ProcDef - { info_comment = "" - , proc_name + { proc_name , proc_meta_params , proc_param_types = map snd params , proc_body = @@ -276,8 +275,7 @@ buildProcHelper is_uproc proc_name_basic proc_meta_params params m = do (_, [], True) -> pure $ QPL.ProcDef - { info_comment = "" - , proc_name + { proc_name , proc_meta_params , proc_param_types = map snd params ++ map snd local_vars , proc_body = diff --git a/src/Traq/Compiler/Python.hs b/src/Traq/Compiler/Python.hs index 9dc849da..c77d6e8d 100644 --- a/src/Traq/Compiler/Python.hs +++ b/src/Traq/Compiler/Python.hs @@ -27,16 +27,17 @@ module Traq.Compiler.Python ( py_unOp, py_binOp, py_naryOp, + py_tupled, toPyType, ) where -import Control.Monad.Reader (ReaderT (..)) import Prettyprinter ((<+>)) import qualified Prettyprinter as PP import Text.Printf (printf) import Lens.Micro.GHC -import Lens.Micro.Mtl + +import Traq.Control.Monad import qualified Traq.CPL as CPL import Traq.Prelude @@ -48,9 +49,6 @@ import qualified Traq.QPL as QPL type Py ann = PP.Doc ann -withEnv :: (Monad m) => r -> ReaderT r m a -> ReaderT r' m a -withEnv r = magnify (lens (const r) const) - py_indent :: Py ann -> Py ann py_indent = PP.indent tabwidth where @@ -79,6 +77,11 @@ py_comment c = PP.vsep $ lines c <&> \l -> PP.pretty $ "# " <> l py_pass :: Py ann py_pass = PP.pretty "pass" +-- | Python tuple literal, handling the singleton case with a trailing comma. +py_tupled :: [Py ann] -> Py ann +py_tupled [x] = PP.parens (x <> PP.comma) +py_tupled xs = PP.tupled xs + py_ifte :: String -> Py ann -> Py ann -> Py ann py_ifte b s_t s_f = PP.vsep diff --git a/src/Traq/Compiler/Qiskit.hs b/src/Traq/Compiler/Qiskit.hs index acf7316b..42d55855 100644 --- a/src/Traq/Compiler/Qiskit.hs +++ b/src/Traq/Compiler/Qiskit.hs @@ -1,5 +1,6 @@ {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RecordWildCards #-} {- HLINT ignore "Use camelCase" -} @@ -9,14 +10,17 @@ module Traq.Compiler.Qiskit ( ) where import Control.Monad.Except (runExceptT) -import Control.Monad.Reader (Reader, runReader) +import Control.Monad.RWS (RWS, runRWS) import Data.List (intersperse) +import qualified Data.Set as Set import Prettyprinter ((<+>)) import qualified Prettyprinter as PP +import Lens.Micro.GHC import Lens.Micro.Mtl import qualified Traq.Data.Context as Ctx +import Traq.Data.Default import qualified Traq.CPL as CPL import Traq.Compiler.Python @@ -27,16 +31,22 @@ import qualified Traq.QPL as QPL -- Compile QPL -> py (+Qiskit) -- ============================================================ +newtype QiskitState = QiskitState (Set.Set Ident) + deriving (HasDefault) + +_externDefNames :: Lens' QiskitState (Set.Set Ident) +_externDefNames focus (QiskitState s) = focus s <&> QiskitState + -- | Build python code string. class ToQiskitPy a where type Ctx a - mkPy :: a -> Reader (Ctx a) (Py ann) + mkPy :: a -> RWS (Ctx a) () QiskitState (Py ann) -- | Convert a QPL program to a python code string. toPy :: QPL.Program SizeT -> String toPy prog = - let pyDoc = runReader (mkPy prog) () + let (pyDoc, _, _) = runRWS (mkPy prog) () default_ in show pyDoc -- ============================================================ @@ -46,17 +56,23 @@ toPy prog = instance (Show size, Integral size) => ToQiskitPy (QPL.Program size) where type Ctx (QPL.Program size) = () - mkPy (QPL.Program ps) = - PP.vsep . intersperse PP.line <$> mapM mkPy ps + mkPy (QPL.Program ps) = do + code <- PP.vsep . intersperse PP.line <$> mapM mkPy ps + exts <- py_tupled . map (PP.dquotes . PP.pretty) . Set.toList <$> use _externDefNames + pure $ + PP.vsep + [ code + , PP.pretty "EXTERN_DEFS" <+> PP.equals <+> exts + , PP.pretty "ENTRY_POINT" <+> PP.equals <+> (PP.dquotes . PP.pretty . QPL.proc_name $ last ps) + ] instance (Show size, Integral size) => ToQiskitPy (QPL.ProcDef size) where type Ctx (QPL.ProcDef size) = () - mkPy QPL.ProcDef{info_comment, proc_name, proc_meta_params, proc_param_types, proc_body} = + mkPy QPL.ProcDef{proc_name, proc_meta_params, proc_param_types, proc_body} = PP.vsep <$> sequence - [ pure $ py_comment info_comment - , withEnv + [ withEnv (ProcBuildCtx{..}) (mkPy proc_body) ] @@ -87,6 +103,49 @@ blackbox name = , PP.pretty "qc.qubits" ] +-- | Emit a custom named gate with a given qubit count. +customGate :: (Show size) => String -> size -> Py ann +customGate name n = + PP.pretty "qiskit.circuit.Gate" + <> PP.tupled [PP.dquotes (PP.pretty name), PP.pretty (show n), PP.pretty "[]"] + +-- | Emit a Qiskit library gate constructor. +libGate :: String -> Py ann +libGate name = PP.pretty $ "qiskit.circuit.library." <> name <> "()" + +-- | Emit a parameterized Qiskit library gate constructor. +libGateParam :: String -> String -> Py ann +libGateParam name param = PP.pretty $ "qiskit.circuit.library." <> name <> "(" <> param <> ")" + +{- | Generate qubit reference for a QPL argument with type-aware slicing. +For whole registers: *reg +For array elements: *reg[start:end] (slice for the element's qubit range) +-} +py_qarg :: (Show size, Integral size) => QPL.Arg size -> CPL.VarType size -> Py ann +py_qarg (QPL.Arg x) _ = PP.pretty "*" <> py_sanitizeIdent x +py_qarg (QPL.ArrElemArg (QPL.Arg x) (CPL.MetaSize i)) elemTy = + let s = CPL.bestBitsize elemTy + start = fromIntegral i * fromIntegral s :: Integer + end = (fromIntegral i + 1) * fromIntegral s :: Integer + in PP.pretty "*" <> py_sanitizeIdent x <> PP.brackets (PP.pretty (show start) <> PP.colon <> PP.pretty (show end)) +py_qarg (QPL.ArrElemArg (QPL.Arg x) (CPL.MetaName n)) elemTy = + let s = CPL.bestBitsize elemTy + in if s == 1 + then PP.pretty "*" <> py_sanitizeIdent x <> PP.brackets (py_sanitizeIdent n <> PP.colon <> py_sanitizeIdent n <+> PP.pretty "+" <+> PP.pretty "1") + else + PP.pretty "*" + <> py_sanitizeIdent x + <> PP.brackets + ( py_sanitizeIdent n + <+> PP.pretty "*" + <+> PP.pretty (show s) + <> PP.colon + <> PP.parens (py_sanitizeIdent n <+> PP.pretty "+" <+> PP.pretty "1") + <+> PP.pretty "*" + <+> PP.pretty (show s) + ) +py_qarg arg _ = PP.pretty "*" <> py_arg arg + -- ============================================================ -- Unitary: Emit Qiskit unitary circuits -- ============================================================ @@ -153,8 +212,11 @@ instance (Show size, Integral size) => ToQiskitPy (QPL.UProcBody size) where PP.vsep $ param_defs ++ reg_defs - ++ [ qc_def + ++ [ mempty + , qc_def + , mempty , stmt_body + , mempty , PP.pretty "return qc" ] pure $ py_def proc_name [] body @@ -167,18 +229,23 @@ instance (Show size, Integral size) => ToQiskitPy (QPL.UStmt size) where mkPy QPL.UnitaryS{qargs, unitary} = do tys <- fmap (either (error . show) id) . runExceptT $ do mapM QPL.getArgTy qargs - let n_qubits = sum $ map CPL.bestBitsize tys - let name = filter (\c -> c /= '"' && c /= '\\') $ show unitary - let gate = PP.pretty "qiskit.circuit.Gate" <> PP.tupled [PP.dquotes (PP.pretty name), PP.pretty (show n_qubits), PP.pretty "[]"] - let qubits = PP.hsep $ PP.punctuate PP.comma [PP.pretty "*" <> py_arg q | q <- qargs] - pure $ PP.pretty "qc.append" <> PP.tupled [gate, PP.brackets qubits] + gateExpr <- withEnv tys $ mkPy unitary + let qubits = PP.hsep $ PP.punctuate PP.comma $ zipWith py_qarg qargs tys + pure $ PP.pretty "qc.append" <> PP.tupled [gateExpr, PP.brackets qubits] mkPy QPL.UCallS{uproc_id, dagger, qargs} = do let gate = py_sanitizeIdent uproc_id <> PP.pretty "().to_gate()" let gateExpr = if dagger then gate <> PP.pretty ".inverse()" else gate let qubits = PP.hsep $ PP.punctuate PP.comma [PP.pretty "*" <> py_arg q | q <- qargs] pure $ PP.pretty "qc.append" <> PP.tupled [gateExpr, PP.brackets qubits] mkPy (QPL.USeqS ss) = PP.vsep <$> mapM mkPy ss - mkPy QPL.URepeatS{} = pure $ blackbox "URepeatS" + mkPy QPL.URepeatS{n_iter, uloop_body} = do + body <- mkPy uloop_body + let n = py_metaParam (Left n_iter) + pure $ + PP.vsep + [ PP.pretty "with qc.for_loop" <> PP.parens (PP.pretty "range" <> PP.parens n) <> PP.colon + , py_indent body + ] mkPy QPL.UForInRangeS{} = pure $ blackbox "UForInRangeS" mkPy QPL.UForInDomainS{} = pure $ blackbox "UForInDomainS" mkPy QPL.UWithComputedS{} = pure $ blackbox "UWithComputedS" @@ -187,23 +254,38 @@ instance (Show size, Integral size) => ToQiskitPy (QPL.Unitary Double size) wher type Ctx (QPL.Unitary Double size) = [CPL.VarType size] mkPy (QPL.BasicGateU g) = mkPy g - mkPy (QPL.DistrU d) = error "TODO DistrU" - mkPy (QPL.Controlled u) = error "TODO Controlled" - mkPy (QPL.Adjoint u) = error "TODO Adjoint" - mkPy (QPL.RevEmbedU xs e) = error "TODO RevEmbedU" + mkPy (QPL.DistrU d) = do + tys <- view id + let n = sum $ map CPL.bestBitsize tys + let name = filter (\c -> c /= '"' && c /= '\\') $ show d + pure $ customGate ("DistrU (" ++ name ++ ")") n + mkPy (QPL.Controlled u) = do + inner <- mkPy u + pure $ inner <> PP.pretty ".control(1)" + mkPy (QPL.Adjoint u) = do + inner <- mkPy u + pure $ inner <> PP.pretty ".inverse()" + mkPy (QPL.RevEmbedU xs e) = do + tys <- view id + let n = sum $ map CPL.bestBitsize tys + let name = filter (\c -> c /= '"' && c /= '\\') $ show (QPL.RevEmbedU xs e :: QPL.Unitary Double size) + pure $ customGate name n instance (Show size, Integral size) => ToQiskitPy (QPL.BasicGate size) where type Ctx (QPL.BasicGate size) = [CPL.VarType size] - mkPy QPL.Toffoli = error "TODO Toffoli" - mkPy QPL.CNOT = error "TODO CNOT" - mkPy QPL.XGate = error "TODO XGate" - mkPy QPL.HGate = error "TODO HGate" - mkPy QPL.ZGate = error "TODO ZGate" - mkPy (QPL.Rz theta) = error "TODO Rz" - mkPy QPL.COPY = error "TODO COPY" - mkPy QPL.SWAP = error "TODO SWAP" - mkPy (QPL.PhaseOnZero theta) = error "TODO PhaseOnZero" + mkPy QPL.XGate = pure $ libGate "XGate" + mkPy QPL.HGate = pure $ libGate "HGate" + mkPy QPL.ZGate = pure $ libGate "ZGate" + mkPy QPL.CNOT = pure $ libGate "CXGate" + mkPy QPL.Toffoli = pure $ libGate "CCXGate" + mkPy QPL.SWAP = pure $ libGate "SwapGate" + mkPy QPL.COPY = pure $ libGate "CXGate" + mkPy (QPL.Rz theta) = pure $ libGateParam "RZGate" (show theta) + mkPy (QPL.PhaseOnZero theta) = do + tys <- view id + let n = sum $ map CPL.bestBitsize tys + pure $ customGate ("PhaseOnZero(" ++ show theta ++ ")") n -- ============================================================ -- Classical: Emit Qiskit circuits with control-flow diff --git a/src/Traq/Compiler/Qualtran.hs b/src/Traq/Compiler/Qualtran.hs index e46fc8f8..68ae993d 100644 --- a/src/Traq/Compiler/Qualtran.hs +++ b/src/Traq/Compiler/Qualtran.hs @@ -85,11 +85,10 @@ instance (Show size, Integral size) => ToQualtranPy (QPL.Program size) where instance (Show size, Integral size) => ToQualtranPy (QPL.ProcDef size) where type Ctx (QPL.ProcDef size) = () - mkPy QPL.ProcDef{info_comment, proc_name, proc_meta_params, proc_param_types, proc_body} = + mkPy QPL.ProcDef{proc_name, proc_meta_params, proc_param_types, proc_body} = PP.vsep <$> sequence - [ pure $ py_comment info_comment - , withEnv + [ withEnv (ProcBuildCtx{..}) (mkPy proc_body) ] diff --git a/src/Traq/Compiler/Quantum.hs b/src/Traq/Compiler/Quantum.hs index 7d0e9829..43acf91c 100644 --- a/src/Traq/Compiler/Quantum.hs +++ b/src/Traq/Compiler/Quantum.hs @@ -131,8 +131,7 @@ instance CompileQ1 CPL.FunDef where compileQ1 proc_name CPL.FunDef{CPL.param_types, CPL.ret_types, CPL.mbody = Nothing} = do return ProcDef - { info_comment = "" - , proc_name + { proc_name , proc_meta_params = [] , proc_param_types = param_types ++ ret_types , proc_body = ProcBodyC CProcDecl @@ -142,8 +141,7 @@ instance CompileQ1 CPL.FunDef where return ProcDef - { info_comment = "" - , proc_name + { proc_name , proc_meta_params = [] , proc_param_types = param_types ++ ret_types , proc_body = ProcBodyC cproc_body diff --git a/src/Traq/Compiler/Unitary.hs b/src/Traq/Compiler/Unitary.hs index 1bc04013..d5df0cb0 100644 --- a/src/Traq/Compiler/Unitary.hs +++ b/src/Traq/Compiler/Unitary.hs @@ -211,7 +211,6 @@ instance CompileU1 CPL.FunDef where -- ext fn: compile as-is to ext uproc compileU1 proc_name CPL.FunDef{param_types, ret_types, mbody = Nothing} = do - let info_comment = "" let proc_meta_params = [] let proc_param_types = param_types ++ ret_types let proc_body = QPL.ProcBodyU QPL.UProcDecl @@ -220,7 +219,6 @@ instance CompileU1 CPL.FunDef where -- fn: compile to uproc, and pass aux types. compileU1 proc_name CPL.FunDef{param_types, ret_types, mbody = Just body} = do - let info_comment = "" let proc_meta_params = [] (body', aux_tys) <- compileU1 (param_types, ret_types) body diff --git a/src/Traq/Control/Monad.hs b/src/Traq/Control/Monad.hs index adc43c7f..8ed54d55 100644 --- a/src/Traq/Control/Monad.hs +++ b/src/Traq/Control/Monad.hs @@ -6,6 +6,9 @@ module Traq.Control.Monad ( mapAccumM, forAccumM, + -- * MonadReader + withEnv, + -- * MonadState withSandboxOf, withSandbox, @@ -42,9 +45,17 @@ import Data.Tuple (swap) import Lens.Micro.GHC import Lens.Micro.Mtl +import Lens.Micro.Mtl.Internal (Magnified, Magnify) import Traq.Data.Errors +-- ================================================================================ +-- Reader +-- ================================================================================ + +withEnv :: (Magnify m n r r', Functor (Magnified m a)) => r -> m a -> n a +withEnv r = magnify (lens (const r) const) + -- ================================================================================ -- Writer -- ================================================================================ diff --git a/src/Traq/Primitives/Amplify/QAmplify.hs b/src/Traq/Primitives/Amplify/QAmplify.hs index 76753bc2..c29745f7 100644 --- a/src/Traq/Primitives/Amplify/QAmplify.hs +++ b/src/Traq/Primitives/Amplify/QAmplify.hs @@ -179,8 +179,7 @@ instance (Floating prec, RealFrac prec, Eq size) => UnitaryCompilePrim (QAmplify return QPL.ProcDef - { QPL.info_comment = "" - , QPL.proc_name = qamplify_proc_name + { QPL.proc_name = qamplify_proc_name , QPL.proc_meta_params = [] , QPL.proc_param_types = map (view _3) all_params , QPL.proc_body = diff --git a/src/Traq/Primitives/Max/QMax.hs b/src/Traq/Primitives/Max/QMax.hs index 0c5fd10c..fd0ea9b5 100644 --- a/src/Traq/Primitives/Max/QMax.hs +++ b/src/Traq/Primitives/Max/QMax.hs @@ -141,7 +141,8 @@ instance (CPL.TypingReqs size, Integral size, RealFloat prec, Show prec) => Unit Compiler.addUStmt $ call_ufun (inp_ix : oup_ix : aux_ix) - Compiler.addUStmt $ QPL.UCommentS $ printf "unitarily compute: %s := max(%s); %s := argmax(%s);" res_var oup argmax_var oup + Compiler.addUStmt $ QPL.UnitaryS [QPL.Arg oup, QPL.Arg res_var] $ QPL.NamedGateU "max" + Compiler.addUStmt $ QPL.UnitaryS [QPL.Arg oup, QPL.Arg argmax_var] $ QPL.NamedGateU "argmax" -- ================================================================================ -- Quantum diff --git a/src/Traq/Primitives/Search/QSearchCFNW.hs b/src/Traq/Primitives/Search/QSearchCFNW.hs index e0e7794e..87bb572e 100644 --- a/src/Traq/Primitives/Search/QSearchCFNW.hs +++ b/src/Traq/Primitives/Search/QSearchCFNW.hs @@ -40,7 +40,6 @@ import Control.Monad.Writer (censor, listen) import Data.Maybe (fromJust) import Data.String (fromString) import GHC.Generics (Generic) -import Text.Printf (printf) import Lens.Micro.GHC import Lens.Micro.Mtl @@ -429,12 +428,6 @@ instance -- name: let prim_name = (case search_kind of AnyK -> "UAny"; AllK -> "UAll"; SearchK -> "USearch") qsearch_proc_name <- lift $ Compiler.newIdent prim_name - let info_comment = - (printf :: String -> String -> String -> String -> String) - "%s[%s, %s]" - prim_name - (show search_ty) - (show $ A.getFailProb eps) let all_params = Compiler.withTag QPL.ParamOut [(ret, CPL.tbool), (x_out, search_ty)] ++ Compiler.withTag QPL.ParamAux (zip pred_ancilla pred_aux_tys) @@ -442,8 +435,7 @@ instance return QPL.ProcDef - { QPL.info_comment = info_comment - , QPL.proc_name = qsearch_proc_name + { QPL.proc_name = qsearch_proc_name , QPL.proc_meta_params = [] , QPL.proc_param_types = map (view _3) all_params , QPL.proc_body = @@ -649,8 +641,7 @@ instance ++ Compiler.withTag QPL.ParamAux (zip upred_aux_vars pred_aux_tys) let uproc_grover_k = QPL.ProcDef - { QPL.info_comment = "Grover[...]" - , QPL.proc_name = uproc_grover_k_name + { QPL.proc_name = uproc_grover_k_name , QPL.proc_meta_params = ["k"] , QPL.proc_param_types = map (view _3) uproc_grover_k_params , QPL.proc_body = diff --git a/src/Traq/Primitives/Simons/Quantum.hs b/src/Traq/Primitives/Simons/Quantum.hs index de4ae39a..ac65a71f 100644 --- a/src/Traq/Primitives/Simons/Quantum.hs +++ b/src/Traq/Primitives/Simons/Quantum.hs @@ -162,8 +162,7 @@ simonsOneRound arg_tys = do return QPL.ProcDef - { QPL.info_comment = "" - , QPL.proc_name + { QPL.proc_name , QPL.proc_meta_params = [] , QPL.proc_param_types = arg_tys ++ arg_tys ++ arg_tys ++ pred_aux_tys , QPL.proc_body = @@ -217,12 +216,14 @@ instance "simon's post-processing: unitarily solve linear system: (%s) . (%s) = 0" (PP.commaList rets) (PP.commaList $ take (length arg_tys) $ map fst xts) + , QPL.UnitaryS + (map QPL.Arg $ rets ++ take (length arg_tys) (map fst xts)) + $ QPL.NamedGateU "SolveLinearSystem" ] return QPL.ProcDef - { QPL.info_comment = "" - , QPL.proc_name + { QPL.proc_name , QPL.proc_meta_params = [] , QPL.proc_param_types = arg_tys ++ map snd xts , QPL.proc_body = @@ -271,12 +272,12 @@ instance "simon's post-processing: solve linear system: (%s) . (%s) = 0" (PP.commaList rets) (PP.commaList $ map fst xts) + , QPL.BlackBoxS (rets ++ map fst xts) "SolveLinearSystem" ] return QPL.ProcDef - { QPL.info_comment = "" - , QPL.proc_name + { QPL.proc_name , QPL.proc_meta_params = [] , QPL.proc_param_types = arg_tys , QPL.proc_body = diff --git a/src/Traq/QPL/Cost.hs b/src/Traq/QPL/Cost.hs index f9841b9e..4fb6a863 100644 --- a/src/Traq/QPL/Cost.hs +++ b/src/Traq/QPL/Cost.hs @@ -78,6 +78,7 @@ instance HasCost (Stmt size) where cost SkipS = return Alg.zero cost (CommentS _) = return Alg.zero cost AssignS{} = return Alg.zero + cost BlackBoxS{} = return Alg.zero cost RandomS{} = return Alg.zero cost RandomDynS{} = return Alg.zero -- single statements diff --git a/src/Traq/QPL/Syntax.hs b/src/Traq/QPL/Syntax.hs index b67ebb23..883df6ac 100644 --- a/src/Traq/QPL/Syntax.hs +++ b/src/Traq/QPL/Syntax.hs @@ -109,6 +109,7 @@ instance HasAdjoint (BasicGate size) where -- | Unitary operators in QPL data Unitary prec size = BasicGateU (BasicGate size) + | NamedGateU Ident | RevEmbedU [Ident] (CPL.BasicExpr size) | DistrU (CPL.DistrExpr prec size) | Controlled (Unitary prec size) @@ -120,6 +121,7 @@ type instance PrecType (Unitary prec size) = prec instance (Show prec, Show size) => PP.ToCodeString (Unitary prec size) where build (BasicGateU g) = PP.build g + build (NamedGateU g) = PP.putWord $ "NamedGate(" <> show g <> ")" build (RevEmbedU xs e) = do e_s <- PP.fromBuild e PP.putWord $ printf "Embed[(%s) => %s]" (PP.commaList xs) e_s @@ -235,6 +237,7 @@ data Stmt size = SkipS | CommentS String | AssignS {rets :: [Ident], expr :: CPL.BasicExpr size} + | BlackBoxS {rets :: [Ident], bbname :: Ident} | RandomS {rets :: [Ident], distr_expr :: CPL.DistrExpr Double size} | RandomDynS {ret :: Ident, max_var :: Ident} | CallS {fun :: FunctionCall, meta_params :: [Either (MetaParam size) Ident], args :: [Arg size]} @@ -258,6 +261,8 @@ instance (Show size) => PP.ToCodeString (Stmt size) where build AssignS{rets, expr} = do e_s <- PP.fromBuild expr PP.putLine $ printf "%s := %s;" (PP.commaList rets) e_s + build BlackBoxS{rets, bbname} = + PP.putLine $ printf "call %s(%s);" (show bbname) (PP.commaList rets) build RandomS{rets, distr_expr} = do distr_s <- PP.fromBuild distr_expr PP.putLine $ printf "%s :=$ %s;" (PP.commaList rets) distr_s @@ -412,8 +417,7 @@ buildProcBody (ProcBodyC p) = buildCProcBody p data ProcDef size = ProcDef - { info_comment :: String - , proc_name :: Ident + { proc_name :: Ident , proc_meta_params :: [Ident] , proc_param_types :: [VarType size] , proc_body :: ProcBody size @@ -427,9 +431,7 @@ instance ClassifyProc (ProcDef size) where type instance SizeType (ProcDef size) = size instance (Show size) => PP.ToCodeString (ProcDef size) where - build ProcDef{info_comment, proc_name, proc_meta_params, proc_param_types, proc_body} = do - PP.putComment info_comment - + build ProcDef{proc_name, proc_meta_params, proc_param_types, proc_body} = do let full_proc_name = printf "%s%s" diff --git a/src/Traq/QPL/TypeCheck.hs b/src/Traq/QPL/TypeCheck.hs index 6d3c6fb0..3d80080f 100644 --- a/src/Traq/QPL/TypeCheck.hs +++ b/src/Traq/QPL/TypeCheck.hs @@ -145,6 +145,7 @@ typeCheckBasicGate Unif _ = return () typeCheckUnitary :: forall size prec. (CPL.TypingReqs size) => Unitary prec size -> [CPL.VarType size] -> TypeChecker size () typeCheckUnitary (BasicGateU g) tys = typeCheckBasicGate g tys +typeCheckUnitary (NamedGateU _) _ = pure () typeCheckUnitary (DistrU (CPL.UniformE ty)) tys = verifyArgTys tys [ty, ty] typeCheckUnitary (DistrU (CPL.BernoulliE _)) tys = verifyArgTys tys [CPL.tbool, CPL.tbool] typeCheckUnitary (RevEmbedU xs e) tys = do @@ -267,6 +268,7 @@ typeCheckStmt ForInRangeS{loop_body, iter_meta_var, iter_lim} = do CPL.MetaName _ -> Err.throwErrorMessage "cannot find iteration" local (CPL._typingCtx . Ctx.ins ('#' : iter_meta_var) .~ iter_ty) $ typeCheckStmt loop_body +typeCheckStmt BlackBoxS{} = return () -- try by desugaring typeCheckStmt s = case desugarS s of Just s' -> typeCheckStmt s' diff --git a/test/Traq/Examples/SearchSpec.hs b/test/Traq/Examples/SearchSpec.hs index 79b7e794..53f8bff7 100644 --- a/test/Traq/Examples/SearchSpec.hs +++ b/test/Traq/Examples/SearchSpec.hs @@ -6,6 +6,11 @@ module Traq.Examples.SearchSpec (spec) where import Control.DeepSeq (force) import Control.Exception (evaluate) import qualified Data.Map as Map +import Text.Parsec.String (parseFromFile) + +import Lens.Micro.GHC + +import qualified Traq.Data.Symbolic as Sym import qualified Traq.Analysis as A import Traq.Analysis.CostModel.QueryCost (SimpleQueryCost (..)) @@ -15,6 +20,7 @@ import qualified Traq.Compiler.Qiskit as Qiskit import qualified Traq.Compiler.Qualtran as Qualtran import Traq.Examples.Search import Traq.Prelude +import Traq.Primitives import Traq.Primitives.Search.QSearchCFNW (_EQSearch, _QSearchZalka) import qualified Traq.QPL as QPL import qualified Traq.Utils.Printing as PP @@ -128,3 +134,18 @@ spec = describe "SearchSpec" $ do let res = CPL.runProgram @_ @Double ex interpCtx [] res `shouldBeDistribution` [([CPL.FinV 1, CPL.FinV i], 1 / 3) | i <- planted_sols] + + describe "any" $ do + let load = + parseFromFile (CPL.programParser @(DefaultPrims (Sym.Sym SizeT) (Sym.Sym Double))) "examples/primitives/any.traq" + >>= expectRight + <&> CPL.mapSize Sym.unSym + <&> CPL.mapPrec Sym.unSym + <&> A.annotateProgWith (CPL._exts (A.annSinglePrim (A.failProb 0.01))) + >>= expectRight + + beforeAll load $ do + xit "target-qiskit" $ \ex -> do + ex_qpl <- expectRight $ Compiler.lowerProgram ex + _ <- evaluate $ force $ Qiskit.toPy ex_qpl + return () diff --git a/test/Traq/Primitives/Search/QSearchCFNWSpec.hs b/test/Traq/Primitives/Search/QSearchCFNWSpec.hs index 0d3dfdba..f51d6fae 100644 --- a/test/Traq/Primitives/Search/QSearchCFNWSpec.hs +++ b/test/Traq/Primitives/Search/QSearchCFNWSpec.hs @@ -77,15 +77,13 @@ spec = do let uprog = QPL.Program [ QPL.ProcDef - { QPL.info_comment = "" - , QPL.proc_name = "Oracle" + { QPL.proc_name = "Oracle" , QPL.proc_meta_params = [] , QPL.proc_param_types = [] , QPL.proc_body = QPL.ProcBodyU QPL.UProcDecl } , QPL.ProcDef - { QPL.info_comment = "" - , QPL.proc_name = "main" + { QPL.proc_name = "main" , QPL.proc_meta_params = [] , QPL.proc_param_types = undefined , QPL.proc_body = diff --git a/tools/qiskit_prelude.py b/tools/qiskit_prelude.py index 2eefa151..32c112d3 100644 --- a/tools/qiskit_prelude.py +++ b/tools/qiskit_prelude.py @@ -2,3 +2,29 @@ import numpy as np import qiskit import qiskit.circuit +from qiskit.circuit import ClassicalRegister, QuantumRegister + +# ===CODE-HERE=== + + +def cli(): + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("--draw", type=str, metavar="FILE", help="Render the main circuit to a PDF file") + parser.add_argument("--qasm", action="store_true", help="Output OpenQASM 3 for the main circuit") + args = parser.parse_args() + + qc = main() + + if args.draw: + qc.draw("mpl", filename=args.draw) + + if args.qasm: + from qiskit.qasm3 import dumps + + print(dumps(qc)) + + +if __name__ == "__main__": + cli() diff --git a/tools/qualtran_prelude.py b/tools/qualtran_prelude.py index fd2d8307..cce08e8a 100644 --- a/tools/qualtran_prelude.py +++ b/tools/qualtran_prelude.py @@ -99,3 +99,5 @@ def bloq_call_and_meas(bloq: qlt.Bloq, *args): # run the circuit and measure the first len(args) output registers # return the measurement outcomes raise NotImplementedError("bloq_call_and_meas") + +# ===CODE-HERE=== diff --git a/tools/traq.hs b/tools/traq.hs index 6e9c3db1..914047ce 100644 --- a/tools/traq.hs +++ b/tools/traq.hs @@ -2,8 +2,10 @@ module Main (main) where +import Control.Monad (unless) import Control.Monad.Reader (ReaderT, runReaderT) import Control.Monad.Trans (lift) +import Data.List (isPrefixOf) import Options.Applicative import System.FilePath (takeExtension) import Text.Printf (printf) @@ -39,6 +41,7 @@ data Options = Options , eps :: Maybe Double , params :: [(Ident, SizeT)] , paramsf :: [(Ident, Double)] + , experimental :: Bool } deriving (Show) @@ -90,21 +93,32 @@ emitQPL qpl_prog = do let nqubits = QPL.numQubits qpl_prog pure $ unlines [PP.toCodeString qpl_prog, printf "// qubits: %d" nqubits] +-- | Insert generated code at the ===CODE-HERE=== marker in a template file. +emitWithTemplate :: FilePath -> String -> IO String +emitWithTemplate templatePath code = do + template <- readFile templatePath + let marker = "# ===CODE-HERE===" + pure $ case break (marker `isPrefixOf`) (lines template) of + (before, _ : after) -> unlines $ before ++ [code] ++ after + _ -> unlines [template, code] + emitQualtran :: QPL.Program SizeT -> IO String -emitQualtran qpl_prog = do - py_preamble <- readFile "tools/qualtran_prelude.py" - let py_prog_str = Qualtran.toPy qpl_prog - pure $ unlines [py_preamble, py_prog_str] +emitQualtran = emitWithTemplate "tools/qualtran_prelude.py" . Qualtran.toPy emitQiskit :: QPL.Program SizeT -> IO String -emitQiskit qpl_prog = do - py_preamble <- readFile "tools/qiskit_prelude.py" - let py_prog_str = Qiskit.toPy qpl_prog - pure $ unlines [py_preamble, py_prog_str] +emitQiskit = emitWithTemplate "tools/qiskit_prelude.py" . Qiskit.toPy -- ============================================================ -- CLI parser -- ============================================================ +parseKeyValue :: (Read a) => String -> Maybe (String, a) +parseKeyValue s = do + let (key, rest) = break (== '=') s + valS <- case rest of + '=' : v -> Just v + _ -> Nothing + val <- readMaybe valS + return (key, val) opts :: ParserInfo Options opts = @@ -112,59 +126,69 @@ opts = (options <**> helper) (fullDesc <> header "Traq: Compile CPL programs to QPL, Qualtran, or Qiskit.") where - options = - Options - <$> option - auto - ( long "target" - <> short 't' - <> metavar "TARGET" - <> help "Output target: QPL | Qualtran | Qiskit" - <> value QPL - <> showDefault - ) - <*> strOption - ( long "input" - <> short 'i' - <> metavar "INPUT" - <> help "Input file (.traq or .qpl)" - ) - <*> optional - ( strOption - ( long "output" - <> short 'o' - <> metavar "OUTPUT" - <> help "Output file (default: stdout)" - ) - ) - <*> optional - ( option - auto - ( long "failprob" - <> short 'p' - <> metavar "FLOAT" - <> help "The maximum failure probability of the entire program" - ) - ) - <*> many (option (maybeReader parseKeyValue) (long "arg" <> help "parameters..." <> metavar "NAME=VALUE")) - <*> many (option (maybeReader parseKeyValueF) (long "argf" <> help "float parameters..." <> metavar "NAME=VALUE")) - - parseKeyValue s = do - let key = takeWhile (/= '=') s - let valS = tail $ dropWhile (/= '=') s - val <- readMaybe valS - return (key, val) - - parseKeyValueF s = do - let key = takeWhile (/= '=') s - let valS = tail $ dropWhile (/= '=') s - val <- readMaybe valS - return (key, val :: Double) + options = do + target <- + option auto $ + long "target" + <> short 't' + <> metavar "TARGET" + <> help "Output target: QPL | Qualtran (experimental) | Qiskit (experimental)" + <> value QPL + <> showDefault + + in_file <- + strOption $ + long "input" + <> short 'i' + <> metavar "INPUT" + <> help "Input file (.traq or .qpl)" + + out_file <- + optional $ + strOption $ + long "output" + <> short 'o' + <> metavar "OUTPUT" + <> help "Output file (default: stdout)" + + eps <- + optional $ + option auto $ + long "failprob" + <> short 'p' + <> metavar "FLOAT" + <> help "The maximum failure probability of the entire program" + + params <- + many $ + option (maybeReader parseKeyValue) $ + long "arg" + <> help "parameters..." + <> metavar "NAME=VALUE" + + paramsf <- + many $ + option (maybeReader parseKeyValue) $ + long "argf" + <> help "float parameters..." + <> metavar "NAME=VALUE" + + experimental <- + switch $ + long "experimental" + <> help "Enable experimental features" + + pure Options{..} main :: IO () main = do options@Options{..} <- execParser opts + let guardExperimental feat = + unless experimental $ + fail $ + "feature " <> feat <> " is experimental; pass --experimental to run it anyway" + qpl_prog <- (runReaderT ?? options) $ do case takeExtension in_file of ".traq" -> do @@ -177,6 +201,6 @@ main = do out_str <- case target of QPL -> emitQPL qpl_prog - Qualtran -> emitQualtran qpl_prog - Qiskit -> emitQiskit qpl_prog + Qualtran -> guardExperimental "backend:Qualtran" >> emitQualtran qpl_prog + Qiskit -> guardExperimental "backend:Qiskit" >> emitQiskit qpl_prog maybe putStr writeFile out_file out_str