@@ -808,6 +808,106 @@ def test_simulate_moment_steps_intermediate_measurement(dtype):
808
808
np .testing .assert_almost_equal (step .density_matrix (), expected )
809
809
810
810
811
+ @pytest .mark .parametrize ('dtype' , [np .complex64 , np .complex128 ])
812
+ def test_simulate_expectation_values (dtype ):
813
+ # Compare with test_expectation_from_state_vector_two_qubit_states
814
+ # in file: cirq/ops/linear_combinations_test.py
815
+ q0 , q1 = cirq .LineQubit .range (2 )
816
+ psum1 = cirq .Z (q0 ) + 3.2 * cirq .Z (q1 )
817
+ psum2 = - 1 * cirq .X (q0 ) + 2 * cirq .X (q1 )
818
+ c1 = cirq .Circuit (cirq .I (q0 ), cirq .X (q1 ))
819
+ simulator = cirq .DensityMatrixSimulator (dtype = dtype )
820
+ result = simulator .simulate_expectation_values (c1 , [psum1 , psum2 ])
821
+ assert cirq .approx_eq (result [0 ], - 2.2 , atol = 1e-6 )
822
+ assert cirq .approx_eq (result [1 ], 0 , atol = 1e-6 )
823
+
824
+ c2 = cirq .Circuit (cirq .H (q0 ), cirq .H (q1 ))
825
+ result = simulator .simulate_expectation_values (c2 , [psum1 , psum2 ])
826
+ assert cirq .approx_eq (result [0 ], 0 , atol = 1e-6 )
827
+ assert cirq .approx_eq (result [1 ], 1 , atol = 1e-6 )
828
+
829
+ psum3 = cirq .Z (q0 ) + cirq .X (q1 )
830
+ c3 = cirq .Circuit (cirq .I (q0 ), cirq .H (q1 ))
831
+ result = simulator .simulate_expectation_values (c3 , psum3 )
832
+ assert cirq .approx_eq (result [0 ], 2 , atol = 1e-6 )
833
+
834
+
835
+ @pytest .mark .parametrize ('dtype' , [np .complex64 , np .complex128 ])
836
+ def test_simulate_noisy_expectation_values (dtype ):
837
+ q0 = cirq .LineQubit (0 )
838
+ psums = [cirq .Z (q0 ), cirq .X (q0 )]
839
+ c1 = cirq .Circuit (
840
+ cirq .X (q0 ),
841
+ cirq .amplitude_damp (gamma = 0.1 ).on (q0 ),
842
+ )
843
+ simulator = cirq .DensityMatrixSimulator (dtype = dtype )
844
+ result = simulator .simulate_expectation_values (c1 , psums )
845
+ # <Z> = (gamma - 1) + gamma = -0.8
846
+ assert cirq .approx_eq (result [0 ], - 0.8 , atol = 1e-6 )
847
+ assert cirq .approx_eq (result [1 ], 0 , atol = 1e-6 )
848
+
849
+ c2 = cirq .Circuit (
850
+ cirq .H (q0 ),
851
+ cirq .depolarize (p = 0.3 ).on (q0 ),
852
+ )
853
+ result = simulator .simulate_expectation_values (c2 , psums )
854
+ assert cirq .approx_eq (result [0 ], 0 , atol = 1e-6 )
855
+ # <X> = (1 - p) + (-p / 3) = 0.6
856
+ assert cirq .approx_eq (result [1 ], 0.6 , atol = 1e-6 )
857
+
858
+
859
+ @pytest .mark .parametrize ('dtype' , [np .complex64 , np .complex128 ])
860
+ def test_simulate_expectation_values_terminal_measure (dtype ):
861
+ q0 = cirq .LineQubit (0 )
862
+ circuit = cirq .Circuit (cirq .H (q0 ), cirq .measure (q0 ))
863
+ obs = cirq .Z (q0 )
864
+ simulator = cirq .DensityMatrixSimulator (dtype = dtype )
865
+ with pytest .raises (ValueError ):
866
+ _ = simulator .simulate_expectation_values (circuit , obs )
867
+
868
+ results = {- 1 : 0 , 1 : 0 }
869
+ for _ in range (100 ):
870
+ result = simulator .simulate_expectation_values (
871
+ circuit , obs , permit_terminal_measurements = True
872
+ )
873
+ if cirq .approx_eq (result [0 ], - 1 , atol = 1e-6 ):
874
+ results [- 1 ] += 1
875
+ if cirq .approx_eq (result [0 ], 1 , atol = 1e-6 ):
876
+ results [1 ] += 1
877
+
878
+ # With a measurement after H, the Z-observable expects a specific state.
879
+ assert results [- 1 ] > 0
880
+ assert results [1 ] > 0
881
+ assert results [- 1 ] + results [1 ] == 100
882
+
883
+ circuit = cirq .Circuit (cirq .H (q0 ))
884
+ results = {0 : 0 }
885
+ for _ in range (100 ):
886
+ result = simulator .simulate_expectation_values (
887
+ circuit , obs , permit_terminal_measurements = True
888
+ )
889
+ if cirq .approx_eq (result [0 ], 0 , atol = 1e-6 ):
890
+ results [0 ] += 1
891
+
892
+ # Without measurement after H, the Z-observable is indeterminate.
893
+ assert results [0 ] == 100
894
+
895
+
896
+ @pytest .mark .parametrize ('dtype' , [np .complex64 , np .complex128 ])
897
+ def test_simulate_expectation_values_qubit_order (dtype ):
898
+ q0 , q1 , q2 = cirq .LineQubit .range (3 )
899
+ circuit = cirq .Circuit (cirq .H (q0 ), cirq .H (q1 ), cirq .X (q2 ))
900
+ obs = cirq .X (q0 ) + cirq .X (q1 ) - cirq .Z (q2 )
901
+ simulator = cirq .DensityMatrixSimulator (dtype = dtype )
902
+
903
+ result = simulator .simulate_expectation_values (circuit , obs )
904
+ assert cirq .approx_eq (result [0 ], 3 , atol = 1e-6 )
905
+
906
+ # Adjusting the qubit order has no effect on the observables.
907
+ result_flipped = simulator .simulate_expectation_values (circuit , obs , qubit_order = [q1 , q2 , q0 ])
908
+ assert cirq .approx_eq (result_flipped [0 ], 3 , atol = 1e-6 )
909
+
910
+
811
911
def test_density_matrix_simulator_state_eq ():
812
912
q0 , q1 = cirq .LineQubit .range (2 )
813
913
eq = cirq .testing .EqualsTester ()
0 commit comments