-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix measurement #290
base: dev
Are you sure you want to change the base?
Fix measurement #290
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import numpy as np | ||
import torchquantum as tq | ||
|
||
|
||
def test_non_trivial_pauli_expectation(): | ||
class TestCircuit(tq.QuantumModule): | ||
def __init__(self): | ||
super().__init__() | ||
|
||
self.meas = tq.measurement.MeasureMultipleTimes([ | ||
{'wires': range(2), 'observables': 'xx'}, | ||
{'wires': range(2), 'observables': 'yy'}, | ||
{'wires': range(2), 'observables': 'zz'}, | ||
]) | ||
|
||
def forward(self, qdev: tq.QuantumDevice): | ||
""" | ||
Prepare and measure the expexctation value of the state | ||
exp(-i pi/8)/sqrt(2) * (cos pi/12, | ||
-i sin pi/12, | ||
-i sin pi/12 * exp(i pi/4), | ||
-i sin pi/12 * exp(i pi/4)) | ||
""" | ||
# prepare bell state | ||
tq.h(qdev, 0) | ||
tq.cnot(qdev, [0, 1]) | ||
|
||
# add some phases | ||
tq.rz(qdev, wires=0, params=np.pi / 4) | ||
tq.rx(qdev, wires=1, params=np.pi / 6) | ||
return self.meas(qdev) | ||
|
||
test_circuit = TestCircuit() | ||
qdev = tq.QuantumDevice(bsz=1, n_wires=2) # Batch size 1 for testing | ||
|
||
# Run the circuit | ||
meas_results = test_circuit(qdev)[0] | ||
|
||
# analytical results for XX, YY, ZZ expval respectively | ||
expval_xx = np.cos(np.pi / 4) | ||
expval_yy = -np.cos(np.pi / 4) * np.cos(np.pi / 6) | ||
expval_zz = np.cos(np.pi / 6) | ||
|
||
atol = 1e-6 | ||
|
||
assert np.isclose(meas_results[0].item(), expval_xx, atol=atol), \ | ||
f"Expected {expval_xx}, got {meas_results[0].item()}" | ||
assert np.isclose(meas_results[1].item(), expval_yy, atol=atol), \ | ||
f"Expected {expval_yy}, got {meas_results[1].item()}" | ||
assert np.isclose(meas_results[2].item(), expval_zz, atol=atol), \ | ||
f"Expected {expval_zz}, got {meas_results[2].item()}" | ||
|
||
print("Test passed!") | ||
|
||
|
||
if __name__ == "__main__": | ||
test_non_trivial_pauli_expectation() |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -23,7 +23,6 @@ | |||||||||||||||||||||||||||||||||||||||||||||
"expval", | ||||||||||||||||||||||||||||||||||||||||||||||
"MeasureAll", | ||||||||||||||||||||||||||||||||||||||||||||||
"MeasureMultipleTimes", | ||||||||||||||||||||||||||||||||||||||||||||||
"MeasureMultiPauliSum", | ||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we no longer adding this as a function to export? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the function, because it was not correctly implemented. You can check the example pauli_sum_op.py, changing the coefficients has no effect on the outcome of the measurement (see my first post). The coefficient part of the input is not taken into account. Thinking about it, I think we could implement this easily by using torchquantum/torchquantum/algorithm/hamiltonian.py Lines 93 to 112 in 611cc2a
and using the matrix of the hamiltonian. Alternatively, we could change torchquantum/torchquantum/measurement/measurements.py Lines 270 to 271 in 611cc2a
But then we would have to change the other expval functions as well to match this. If you think there is a real use case for this measurement and it is worth changing the expval functions we can do that, otherwise just remove as done here. |
||||||||||||||||||||||||||||||||||||||||||||||
"MeasureMultiQubitPauliSum", | ||||||||||||||||||||||||||||||||||||||||||||||
"gen_bitstrings", | ||||||||||||||||||||||||||||||||||||||||||||||
"measure", | ||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -367,15 +366,14 @@ def forward(self, qdev: tq.QuantumDevice): | |||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
observables = [] | ||||||||||||||||||||||||||||||||||||||||||||||
for wire in range(qdev.n_wires): | ||||||||||||||||||||||||||||||||||||||||||||||
observables.append(tq.I()) | ||||||||||||||||||||||||||||||||||||||||||||||
observables.append("I") | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
for wire, observable in zip(layer["wires"], layer["observables"]): | ||||||||||||||||||||||||||||||||||||||||||||||
observables[wire] = tq.op_name_dict[observable]() | ||||||||||||||||||||||||||||||||||||||||||||||
observables[wire] = observable | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
res = expval( | ||||||||||||||||||||||||||||||||||||||||||||||
res = expval_joint_analytical( | ||||||||||||||||||||||||||||||||||||||||||||||
qdev_new, | ||||||||||||||||||||||||||||||||||||||||||||||
wires=list(range(qdev.n_wires)), | ||||||||||||||||||||||||||||||||||||||||||||||
observables=observables, | ||||||||||||||||||||||||||||||||||||||||||||||
observable="".join(observables), | ||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
if self.v_c_reg_mapping is not None: | ||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -390,42 +388,13 @@ def forward(self, qdev: tq.QuantumDevice): | |||||||||||||||||||||||||||||||||||||||||||||
res = res[:, perm] | ||||||||||||||||||||||||||||||||||||||||||||||
res_all.append(res) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
return torch.cat(res_all) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
return torch.stack(res_all, dim=-1) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
def set_v_c_reg_mapping(self, mapping): | ||||||||||||||||||||||||||||||||||||||||||||||
self.v_c_reg_mapping = mapping | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
class MeasureMultiPauliSum(tq.QuantumModule): | ||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||
similar to qiskit.opflow PauliSumOp | ||||||||||||||||||||||||||||||||||||||||||||||
obs list: | ||||||||||||||||||||||||||||||||||||||||||||||
list of dict: example | ||||||||||||||||||||||||||||||||||||||||||||||
[{'wires': [0, 2, 3, 1], | ||||||||||||||||||||||||||||||||||||||||||||||
'observables': ['x', 'y', 'z', 'i'], | ||||||||||||||||||||||||||||||||||||||||||||||
'coefficient': [1, 0.5, 0.4, 0.3] | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
{'wires': [0, 2, 3, 1], | ||||||||||||||||||||||||||||||||||||||||||||||
'observables': ['x', 'y', 'z', 'i'], | ||||||||||||||||||||||||||||||||||||||||||||||
'coefficient': [1, 0.5, 0.4, 0.3] | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
def __init__(self, obs_list, v_c_reg_mapping=None): | ||||||||||||||||||||||||||||||||||||||||||||||
super().__init__() | ||||||||||||||||||||||||||||||||||||||||||||||
self.obs_list = obs_list | ||||||||||||||||||||||||||||||||||||||||||||||
self.v_c_reg_mapping = v_c_reg_mapping | ||||||||||||||||||||||||||||||||||||||||||||||
self.measure_multiple_times = MeasureMultipleTimes( | ||||||||||||||||||||||||||||||||||||||||||||||
obs_list=obs_list, v_c_reg_mapping=v_c_reg_mapping | ||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
def forward(self, qdev: tq.QuantumDevice): | ||||||||||||||||||||||||||||||||||||||||||||||
res_all = self.measure_multiple_times(qdev).prod(-1) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
return res_all.sum(-1) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
class MeasureMultiQubitPauliSum(tq.QuantumModule): | ||||||||||||||||||||||||||||||||||||||||||||||
"""obs list: | ||||||||||||||||||||||||||||||||||||||||||||||
list of dict: example | ||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -449,8 +418,9 @@ def __init__(self, obs_list, v_c_reg_mapping=None): | |||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
def forward(self, qdev: tq.QuantumDevice): | ||||||||||||||||||||||||||||||||||||||||||||||
res_all = self.measure_multiple_times(qdev).prod(-1) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
# returns batch x len(obs_list) object, return sum times coefficient | ||||||||||||||||||||||||||||||||||||||||||||||
res_all = self.measure_multiple_times(qdev) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
return (res_all * torch.tensor(self.obs_list[0]["coefficient"])).sum(-1) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this file be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is an empty file in the examples section, I do not really see what function it is accomplishing, so I removed it, but I can put it back if you do not feel comfortable removing it.