@@ -32,16 +32,6 @@ def initial_parameters(config):
3232 )
3333
3434
35- def observable_signs (config ):
36- basis = np .arange (2 ** config ["n_qubits" ], dtype = np .uint32 )
37- signs = []
38- for q in range (config ["n_qubits" ]):
39- bits = (basis >> (config ["n_qubits" ] - 1 - q )) & 1
40- signs .append (1.0 - 2.0 * bits .astype (np .float32 ))
41- signs .append (np .prod (np .stack (signs ), axis = 0 ))
42- return K .convert_to_tensor (np .stack (signs ))
43-
44-
4535def asymmetric_bitflip_kraus (p01 , p10 ):
4636 zero = K .cast (K .convert_to_tensor (0.0 ), "complex64" )
4737 k0 = K .stack (
@@ -92,45 +82,48 @@ def prepare_initial_state(circuit, probe_index, config):
9282 circuit .h (i )
9383
9484
95- def probe_observables (probe_index , p01 , p10 , config , signs ):
85+ def probe_observables (probe_index , p01 , p10 , config ):
9686 circuit = tc .DMCircuit (config ["n_qubits" ])
9787 kraus = asymmetric_bitflip_kraus (p01 , p10 )
9888 prepare_initial_state (circuit , probe_index , config )
9989 apply_noisy_entangler_layer (circuit , kraus , config )
100- probabilities = circuit .probability ()
101- return K .real (K .tensordot (signs , probabilities , 1 ))
90+ values = [
91+ K .real (circuit .expectation ((tc .gates .z (), [i ]), reuse = False ))
92+ for i in range (config ["n_qubits" ])
93+ ]
94+ parity_ops = [(tc .gates .z (), [i ]) for i in range (config ["n_qubits" ])]
95+ values .append (K .real (circuit .expectation (* parity_ops , reuse = False )))
96+ return K .stack (values )
10297
10398
104- def observable_table (p01 , p10 , config , signs ):
99+ def observable_table (p01 , p10 , config ):
105100 return K .stack (
106101 [
107- probe_observables (probe_index , p01 , p10 , config , signs )
102+ probe_observables (probe_index , p01 , p10 , config )
108103 for probe_index in range (PROBE_COUNT )
109104 ]
110105 )
111106
112107
113- def loss_and_observables (raw_params , target_expectations , config , signs ):
108+ def loss_and_observables (raw_params , target_expectations , config ):
114109 p01 , p10 = probabilities (raw_params )
115- fitted_expectations = observable_table (p01 , p10 , config , signs )
110+ fitted_expectations = observable_table (p01 , p10 , config )
116111 loss = K .mean ((fitted_expectations - target_expectations ) ** 2 )
117112 return loss , (p01 , p10 , fitted_expectations )
118113
119114
120115def run_solution (config ):
121- signs = observable_signs (config )
122116 true_target = observable_table (
123117 K .convert_to_tensor (config ["true_p01" ]),
124118 K .convert_to_tensor (config ["true_p10" ]),
125119 config ,
126- signs ,
127120 )
128121 params = initial_parameters (config )
129122 optimizer = optax .adam (config ["learning_rate" ])
130123 opt_state = optimizer .init (params )
131124
132125 def loss_fn (p ):
133- return loss_and_observables (p , true_target , config , signs )
126+ return loss_and_observables (p , true_target , config )
134127
135128 def train_step (p , state ):
136129 (loss , aux ), grads = K .value_and_grad (loss_fn , has_aux = True )(p )
0 commit comments