From 024be60950fbb8996afcfaf960094ec1404a76a5 Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Thu, 1 Aug 2024 18:19:14 +0800 Subject: [PATCH 1/9] Make the warning message clearer for uninstalled MindSpore --- mindquantum/__init__.py | 8 ++++++ mindquantum/framework/__init__.py | 41 ++++++++++++++++++------------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/mindquantum/__init__.py b/mindquantum/__init__.py index 6e0aeed6c..a88c0448e 100644 --- a/mindquantum/__init__.py +++ b/mindquantum/__init__.py @@ -70,3 +70,11 @@ __all__.extend(config.__all__) __all__.extend(device.__all__) __all__.extend(dtype.__all__) __all__.sort() + +from .framework import framework_modules + +def __getattr__(name): + if name in framework_modules: + if name not in framework.__all__: + raise ImportError(f"MindSpore not install, cannot import '{name}' from 'mindquantum'.") + raise ImportError(f"cannot import '{name}' from 'mindquantum'") diff --git a/mindquantum/framework/__init__.py b/mindquantum/framework/__init__.py index dc42c5cfe..a81bdd0b6 100644 --- a/mindquantum/framework/__init__.py +++ b/mindquantum/framework/__init__.py @@ -15,6 +15,21 @@ """Quantum neural networks operators and cells.""" import warnings +framework_modules = [ + "MQAnsatzOnlyLayer", + "MQN2AnsatzOnlyLayer", + "MQLayer", + "MQN2Layer", + "MQOps", + "MQN2Ops", + "MQAnsatzOnlyOps", + "MQN2AnsatzOnlyOps", + "MQEncoderOnlyOps", + "MQN2EncoderOnlyOps", + "QRamVecOps", + "QRamVecLayer", +] + __all__ = [] try: import mindspore @@ -36,22 +51,7 @@ try: QRamVecOps, ) - __all__.extend( - [ - "MQAnsatzOnlyLayer", - "MQN2AnsatzOnlyLayer", - "MQLayer", - "MQN2Layer", - "MQOps", - "MQN2Ops", - "MQAnsatzOnlyOps", - "MQN2AnsatzOnlyOps", - "MQEncoderOnlyOps", - "MQN2EncoderOnlyOps", - "QRamVecOps", - "QRamVecLayer", - ] - ) + __all__.extend(framework_modules) import packaging.version ms_version = mindspore.__version__ @@ -70,8 +70,15 @@ try: except ImportError: warnings.warn( - "MindSpore not installed, you may not be able to use hybrid quantum classical neural network.", + "MindSpore not installed. 'mindquantum.framework' modules (for hybrid quantum-classical neural network) are disabled.", stacklevel=2, ) __all__.sort() + + +def __getattr__(name): + if name in framework_modules: + if name not in __all__: + raise ImportError(f"MindSpore not install, cannot import '{name}' from 'mindquantum'.") + raise ImportError(f"cannot import '{name}' from 'mindquantum'") -- Gitee From 5665738f1b8e7739c8d8928a34dc3d46bf08f27c Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Thu, 1 Aug 2024 18:51:49 +0800 Subject: [PATCH 2/9] add 'to_json' for MeasureResult --- mindquantum/core/gates/measurement.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/mindquantum/core/gates/measurement.py b/mindquantum/core/gates/measurement.py index 93e94c13e..86ab35c86 100644 --- a/mindquantum/core/gates/measurement.py +++ b/mindquantum/core/gates/measurement.py @@ -20,6 +20,7 @@ from collections.abc import Iterable import numpy as np +import json from rich.console import Console from mindquantum import mqbackend as mb @@ -361,3 +362,26 @@ class MeasureResult: raise ValueError(f"Style not found, currently we support {list(supported_style.keys())}") style = supported_style[style] return SVGMeasure(self, style) + + def to_json(self, filename=None): + """ + Convert the measure result to JSON format and optionally save to a file. + + Args: + filename (str): save the JSON to this file. If None, return the JSON string. Default: ``None``. + + Returns: + str: JSON representation of the object if filename is None, + otherwise None (file is saved instead). + """ + data = { + "keys": self.keys, + "data": self.data, + "shots": self.shots, + } + + if filename: + with open(filename, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=4) + else: + return json.dumps(data, ensure_ascii=False, indent=4) -- Gitee From 0aaa25f53ec05efcaa011616f1f8fc1fb67a6725 Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Thu, 1 Aug 2024 19:17:00 +0800 Subject: [PATCH 3/9] fix is_measure_end bug --- mindquantum/core/circuit/circuit.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mindquantum/core/circuit/circuit.py b/mindquantum/core/circuit/circuit.py index 0612cef40..82f9711f9 100644 --- a/mindquantum/core/circuit/circuit.py +++ b/mindquantum/core/circuit/circuit.py @@ -830,14 +830,16 @@ class Circuit(list): # pylint: disable=too-many-instance-attributes,too-many-pu """ circ = self.remove_barrier() high = [0 for i in range(self.n_qubits)] + measure_num = [0 for i in range(self.n_qubits)] for gate in circ: for idx in set(gate.obj_qubits + gate.ctrl_qubits): high[idx] += 1 if isinstance(gate, mq_gates.Measure): m_idx = gate.obj_qubits[0] + measure_num[m_idx] += 1 if high[m_idx] != circ.all_qubits.map[m_idx]: return False - return True + return all(x == 1 for x in measure_num) def matrix(self, pr=None, big_end=False, backend='mqvector', seed=None, dtype=None): """ -- Gitee From 191ac2a85f66f2a8c526b401c93022d691011400 Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Thu, 1 Aug 2024 20:57:49 +0800 Subject: [PATCH 4/9] Unified endianness for keys, samples, and data in MeasureResult; added reverse_endian. --- mindquantum/core/circuit/circuit.py | 4 +++ mindquantum/core/gates/measurement.py | 25 ++++++++++++++++--- mindquantum/io/display/measure_res_drawer.py | 2 +- .../io/display/measure_res_svg_drawer.py | 2 +- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/mindquantum/core/circuit/circuit.py b/mindquantum/core/circuit/circuit.py index 82f9711f9..76ffbbed0 100644 --- a/mindquantum/core/circuit/circuit.py +++ b/mindquantum/core/circuit/circuit.py @@ -1463,6 +1463,10 @@ class Circuit(list): # pylint: disable=too-many-instance-attributes,too-many-pu """ Flip the circuit to big endian. + Note: + This operation also changes the qubits that measurement gates act on, + which may cause the measurement keys to no longer correspond to the actual measured qubits. + Examples: >>> from mindquantum.core.circuit import Circuit >>> circ = Circuit().h(0).x(2, 0).y(3).x(3, 2) diff --git a/mindquantum/core/gates/measurement.py b/mindquantum/core/gates/measurement.py index 86ab35c86..429be4ef6 100644 --- a/mindquantum/core/gates/measurement.py +++ b/mindquantum/core/gates/measurement.py @@ -214,7 +214,7 @@ class MeasureResult: for meas in measure: if not isinstance(meas, Measure): raise ValueError("Measurement gates need to be objects of class 'Measurement' ") - for meas in measure: + for meas in reversed(measure): if meas.key in self.keys: raise ValueError(f"Measure key {meas.key} already defined.") self.measures.append(meas) @@ -234,11 +234,10 @@ class MeasureResult: the sampling bit string in 0 or 1, where N represents the number of shot times, and M represents the number of keys in this measurement container """ - self.samples = samples out = {} - res = np.fliplr(self.samples) + self.samples = np.fliplr(samples) self.shots = len(self.samples) - for string in res: + for string in self.samples: string = ''.join([str(i) for i in string]) if string in out: out[string] += 1 @@ -385,3 +384,21 @@ class MeasureResult: json.dump(data, f, ensure_ascii=False, indent=4) else: return json.dumps(data, ensure_ascii=False, indent=4) + + def reverse_endian(self): + """ + Reverse the endianness of the measurement result. + + This function reverses the order of bits in each bit string of the measurement result, + and also reverses the order of keys. + + Returns: + MeasureResult: A new MeasureResult object with reversed endian. + """ + new_result = MeasureResult() + new_result.keys = self.keys[::-1] + new_result.measures = self.measures[::-1] + new_result.bit_string_data = {bit_string[::-1]: count for bit_string, count in self.bit_string_data.items()} + new_result.samples = np.fliplr(self.samples) + new_result.shots = self.shots + return new_result diff --git a/mindquantum/io/display/measure_res_drawer.py b/mindquantum/io/display/measure_res_drawer.py index a134512de..0fdb4c521 100644 --- a/mindquantum/io/display/measure_res_drawer.py +++ b/mindquantum/io/display/measure_res_drawer.py @@ -50,7 +50,7 @@ def measure_text_drawer(res): # pylint: disable=too-many-locals else: max_prop /= 0.8 ket_exp = 'Keys: ' - ket_exp += ' '.join(keys[::-1]) + ket_exp += ' '.join(keys) string = [f'shots: {res.shots}'] string.append(ket_exp + vline) axis_num = '' diff --git a/mindquantum/io/display/measure_res_svg_drawer.py b/mindquantum/io/display/measure_res_svg_drawer.py index bbd8d4cf8..8fe844d3d 100644 --- a/mindquantum/io/display/measure_res_svg_drawer.py +++ b/mindquantum/io/display/measure_res_svg_drawer.py @@ -121,7 +121,7 @@ class SVGMeasure(SVGContainer): shots_text = Text(0, 0, f"Shots:\n {str(self.res.shots)}") shots_text.text_anchor("start") shots_text.shift(0, (shots_text.bottom - shots_text.top) / 2) - keys_text = Text(0, 0, f"Keys: {' '.join(self.res.keys[::-1])}") + keys_text = Text(0, 0, f"Keys: {' '.join(self.res.keys)}") keys_text.text_anchor("start") keys_text.shift(0, (shots_text.bottom - shots_text.top) / 2 + shots_text.bottom) text = SVGContainer() -- Gitee From 4e4936af8fb64b3150f3476a4f0bf3a776cbe371 Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Mon, 12 Aug 2024 17:22:49 +0800 Subject: [PATCH 5/9] fix pylint --- mindquantum/__init__.py | 3 ++- mindquantum/core/gates/measurement.py | 10 ++++------ mindquantum/framework/__init__.py | 4 +++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mindquantum/__init__.py b/mindquantum/__init__.py index a88c0448e..d9c1bd2a8 100644 --- a/mindquantum/__init__.py +++ b/mindquantum/__init__.py @@ -21,6 +21,7 @@ import warnings import numpy as np from .mqbackend import logging +from .framework import framework_modules # isort: split @@ -71,8 +72,8 @@ __all__.extend(device.__all__) __all__.extend(dtype.__all__) __all__.sort() -from .framework import framework_modules +# pylint: disable=invalid-name def __getattr__(name): if name in framework_modules: if name not in framework.__all__: diff --git a/mindquantum/core/gates/measurement.py b/mindquantum/core/gates/measurement.py index 429be4ef6..9df066c7f 100644 --- a/mindquantum/core/gates/measurement.py +++ b/mindquantum/core/gates/measurement.py @@ -19,8 +19,8 @@ from collections.abc import Iterable -import numpy as np import json +import numpy as np from rich.console import Console from mindquantum import mqbackend as mb @@ -367,11 +367,10 @@ class MeasureResult: Convert the measure result to JSON format and optionally save to a file. Args: - filename (str): save the JSON to this file. If None, return the JSON string. Default: ``None``. + filename (str): The name of the file to save the JSON. Default: ``None``. Returns: - str: JSON representation of the object if filename is None, - otherwise None (file is saved instead). + str: JSON representation of the object. """ data = { "keys": self.keys, @@ -382,8 +381,7 @@ class MeasureResult: if filename: with open(filename, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=4) - else: - return json.dumps(data, ensure_ascii=False, indent=4) + return json.dumps(data, ensure_ascii=False, indent=4) def reverse_endian(self): """ diff --git a/mindquantum/framework/__init__.py b/mindquantum/framework/__init__.py index a81bdd0b6..26a253ca0 100644 --- a/mindquantum/framework/__init__.py +++ b/mindquantum/framework/__init__.py @@ -70,13 +70,15 @@ try: except ImportError: warnings.warn( - "MindSpore not installed. 'mindquantum.framework' modules (for hybrid quantum-classical neural network) are disabled.", + "MindSpore not installed." + "'mindquantum.framework' modules (for hybrid quantum-classical neural network) are disabled.", stacklevel=2, ) __all__.sort() +# pylint: disable=invalid-name def __getattr__(name): if name in framework_modules: if name not in __all__: -- Gitee From 6564bb9630fa9bfb92edc0ffe9d800452856e761 Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Fri, 23 Aug 2024 11:56:54 +0800 Subject: [PATCH 6/9] fix two qubit gates order bug --- ccsrc/lib/simulator/utils.cpp | 4 +- .../test_basic_gate_with_simulator.py | 61 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/ccsrc/lib/simulator/utils.cpp b/ccsrc/lib/simulator/utils.cpp index 78ac9c15e..77b2b54a0 100644 --- a/ccsrc/lib/simulator/utils.cpp +++ b/ccsrc/lib/simulator/utils.cpp @@ -59,8 +59,8 @@ DoubleQubitGateMask::DoubleQubitGateMask(const qbits_t &obj_qubits, const qbits_ q_max = obj_qubits[0]; } this->ctrl_qubits = ctrl_qubits; - obj_min_mask = (static_cast(1) << q_min); - obj_max_mask = (static_cast(1) << q_max); + obj_min_mask = (static_cast(1) << obj_qubits[0]); + obj_max_mask = (static_cast(1) << obj_qubits[1]); obj_mask = obj_min_mask + obj_max_mask; ctrl_mask = QIndexToMask(ctrl_qubits); for (qbit_t i = 0; i < q_min; i++) { diff --git a/tests/st/test_simulator/test_basic_gate_with_simulator.py b/tests/st/test_simulator/test_basic_gate_with_simulator.py index a28090fe5..10cefa8a3 100644 --- a/tests/st/test_simulator/test_basic_gate_with_simulator.py +++ b/tests/st/test_simulator/test_basic_gate_with_simulator.py @@ -748,3 +748,64 @@ def test_rot_pauli_string_gate_gradient(config): # pylint: disable=too-many-loc atol = 1e-8 assert np.allclose(f1, f2, atol=atol) assert np.allclose(g1, g2, atol=atol) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_x86_cpu +@pytest.mark.env_onecard +@pytest.mark.parametrize("config", list(filter(lambda x: x != 'stabilizer', SUPPORTED_SIMULATOR))) +def test_custom_gate_order(config): # pylint: disable=too-many-locals + """ + Description: test object qubits order of custom gate + Expectation: success. + """ + virtual_qc, dtype = config + for n in (2, 3, 4): + circ = mq.random_circuit(n, 100, 1.0, 0.0) + g = G.UnivMathGate('random', circ.matrix()).on(list(reversed(range(n)))) + dim = 2**g.n_qubits + init_state = np.random.rand(dim) + np.random.rand(dim) * 1j + sim = Simulator(virtual_qc, g.n_qubits, dtype=dtype) + sim.set_qs(init_state) + sim.apply_gate(g) + ref_sim = Simulator("mqvector", g.n_qubits, dtype=dtype) + ref_sim.set_qs(init_state) + ref_sim.apply_circuit(circ.reverse_qubits()) + ref_qs = ref_sim.get_qs() + if virtual_qc.startswith("mqmatrix"): + assert np.allclose(sim.get_qs(), np.outer(ref_qs, ref_qs.conj()), atol=1e-6) + else: + assert np.allclose(sim.get_qs(), ref_qs, atol=1e-6) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_x86_cpu +@pytest.mark.env_onecard +@pytest.mark.parametrize("config", list(filter(lambda x: x != 'stabilizer', SUPPORTED_SIMULATOR))) +@pytest.mark.parametrize("gate", single_parameter_gate + multi_parameter_gate) +def test_two_qubit_gate_order(config, gate): # pylint: disable=too-many-locals + """ + Description: test object qubits order of two qubit gates + Expectation: success. + """ + virtual_qc, dtype = config + n_pr = len(signature(gate).parameters) + pr = np.random.rand(n_pr) * 2 * np.pi + g = gate(*pr) + dim = 2**g.n_qubits + g = g.on(list(reversed(range(g.n_qubits)))) + init_state = np.random.rand(dim) + np.random.rand(dim) * 1j + sim = Simulator(virtual_qc, g.n_qubits, dtype=dtype) + sim.set_qs(init_state) + sim.apply_gate(g) + ref_g = G.UnivMathGate('ref', g.matrix()).on(list(reversed(range(g.n_qubits)))) + ref_sim = Simulator("mqvector", g.n_qubits, dtype=dtype) + ref_sim.set_qs(init_state) + ref_sim.apply_gate(ref_g) + ref_qs = ref_sim.get_qs() + if virtual_qc.startswith("mqmatrix"): + assert np.allclose(sim.get_qs(), np.outer(ref_qs, ref_qs.conj()), atol=1e-6) + else: + assert np.allclose(sim.get_qs(), ref_qs, atol=1e-6) -- Gitee From 258ced6fa5019409e429178bdb3269f67ebbbfa7 Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Wed, 11 Sep 2024 11:59:16 +0800 Subject: [PATCH 7/9] fix endian bug --- ccsrc/include/simulator/vector/vector_state.tpp | 9 +++++++-- mindquantum/core/gates/measurement.py | 2 +- mindquantum/framework/__init__.py | 2 +- mindquantum/io/qasm/openqasm.py | 3 +++ tests/st/test_core/test_circuit/test_circuit.py | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ccsrc/include/simulator/vector/vector_state.tpp b/ccsrc/include/simulator/vector/vector_state.tpp index 11ca716ef..fee8cf4e4 100644 --- a/ccsrc/include/simulator/vector/vector_state.tpp +++ b/ccsrc/include/simulator/vector/vector_state.tpp @@ -1304,6 +1304,7 @@ VT VectorState::SamplingMeasurementEndingWithoutNoise(co VT already_measured(this->n_qubits, 0); VT m_qids; + std::map qid_maps; circuit_t other_circ; for (auto& g : circ) { if (g->GetID() == GateID::M) { @@ -1313,6 +1314,7 @@ VT VectorState::SamplingMeasurementEndingWithoutNoise(co } already_measured[m_qid] = 1; m_qids.push_back(m_qid); + qid_maps[m_qid] = static_cast(g.get())->Name(); } else { other_circ.push_back(g); } @@ -1326,12 +1328,15 @@ VT VectorState::SamplingMeasurementEndingWithoutNoise(co } std::sort(sampled_probs.begin(), sampled_probs.end()); auto res = qs_policy_t_::LowerBound(cum_prob, sampled_probs); - VT out; + auto key_size = key_map.size(); + VT out(shots * key_size); + size_t count = 0; // Measure all qubits and filter actually measurement qubit. for (auto r : res) { for (auto i : m_qids) { - out.push_back((r >> i) & 1); + out[count * key_size + key_map.at(qid_maps[i])] = ((r >> i) & 1); } + count++; } return out; } diff --git a/mindquantum/core/gates/measurement.py b/mindquantum/core/gates/measurement.py index 9df066c7f..0d513c54d 100644 --- a/mindquantum/core/gates/measurement.py +++ b/mindquantum/core/gates/measurement.py @@ -235,7 +235,7 @@ class MeasureResult: times, and M represents the number of keys in this measurement container """ out = {} - self.samples = np.fliplr(samples) + self.samples = samples self.shots = len(self.samples) for string in self.samples: string = ''.join([str(i) for i in string]) diff --git a/mindquantum/framework/__init__.py b/mindquantum/framework/__init__.py index 26a253ca0..cc5e41e79 100644 --- a/mindquantum/framework/__init__.py +++ b/mindquantum/framework/__init__.py @@ -70,7 +70,7 @@ try: except ImportError: warnings.warn( - "MindSpore not installed." + "MindSpore not installed. " "'mindquantum.framework' modules (for hybrid quantum-classical neural network) are disabled.", stacklevel=2, ) diff --git a/mindquantum/io/qasm/openqasm.py b/mindquantum/io/qasm/openqasm.py index 4e20152e8..65f83ec1a 100644 --- a/mindquantum/io/qasm/openqasm.py +++ b/mindquantum/io/qasm/openqasm.py @@ -585,6 +585,9 @@ class OpenQASM: 'x': lambda prs, qids: G.X.on(qids), 'y': lambda prs, qids: G.Y.on(qids), 'z': lambda prs, qids: G.Z.on(qids), + 'c3sqrtx': lambda prs, qids: G.SX.on(qids[-1], qids[:-1]), + 'c3x': lambda prs, qids: G.X.on(qids[-1], qids[:-1]), + 'c4x': lambda prs, qids: G.X.on(qids[-1], qids[:-1]), } self.gate_map_mq_openqasm = { diff --git a/tests/st/test_core/test_circuit/test_circuit.py b/tests/st/test_core/test_circuit/test_circuit.py index 480059906..2e3f0a60d 100644 --- a/tests/st/test_core/test_circuit/test_circuit.py +++ b/tests/st/test_core/test_circuit/test_circuit.py @@ -127,7 +127,7 @@ def test_is_measure_end(): Expectation: """ circ1 = Circuit().x(0) - assert circ1.is_measure_end + assert not circ1.is_measure_end circ1 += G.Measure().on(0) circ1 += G.BARRIER assert circ1.is_measure_end -- Gitee From c84f39a603416ea798c219df767dd08718a1cca1 Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Thu, 12 Sep 2024 16:30:21 +0800 Subject: [PATCH 8/9] fix dm SWAP bug --- .../cpu_common/cpu_densitymatrix_core_swap_like.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ccsrc/lib/simulator/densitymatrix/detail/cpu_common/cpu_densitymatrix_core_swap_like.cpp b/ccsrc/lib/simulator/densitymatrix/detail/cpu_common/cpu_densitymatrix_core_swap_like.cpp index ea16e6fb0..5c36dedc4 100644 --- a/ccsrc/lib/simulator/densitymatrix/detail/cpu_common/cpu_densitymatrix_core_swap_like.cpp +++ b/ccsrc/lib/simulator/densitymatrix/detail/cpu_common/cpu_densitymatrix_core_swap_like.cpp @@ -72,7 +72,7 @@ void CPUDensityMatrixPolicyBase::ApplySWAP(qs_data_p_t* qs qs[IdxMap(r1, r1)] = qs[IdxMap(r2, r2)]; qs[IdxMap(r2, r2)] = tmp; - qs[IdxMap(r2, r1)] = std::conj(qs[IdxMap(r2, r1)]); + SetValue(qs, r2, r1, std::conj(GetValue(qs, r2, r1))); }) } else { THRESHOLD_OMP_FOR( @@ -130,7 +130,7 @@ void CPUDensityMatrixPolicyBase::ApplySWAP(qs_data_p_t* qs qs[IdxMap(r1, r1)] = qs[IdxMap(r2, r2)]; qs[IdxMap(r2, r2)] = tmp; - qs[IdxMap(r2, r1)] = std::conj(qs[IdxMap(r2, r1)]); + SetValue(qs, r2, r1, std::conj(GetValue(qs, r2, r1))); } }) } @@ -195,7 +195,7 @@ void CPUDensityMatrixPolicyBase::ApplyISWAPNoCtrl(qs_data_ qs[IdxMap(r1, r1)] = qs[IdxMap(r2, r2)]; qs[IdxMap(r2, r2)] = tmp; - qs[IdxMap(r2, r1)] = std::conj(qs[IdxMap(r2, r1)]); + SetValue(qs, r2, r1, std::conj(GetValue(qs, r2, r1))); }) } @@ -266,7 +266,7 @@ void CPUDensityMatrixPolicyBase::ApplyISWAPCtrl(qs_data_p_ qs[IdxMap(r1, r1)] = qs[IdxMap(r2, r2)]; qs[IdxMap(r2, r2)] = tmp; - qs[IdxMap(r2, r1)] = std::conj(qs[IdxMap(r2, r1)]); + SetValue(qs, r2, r1, std::conj(GetValue(qs, r2, r1))); } }) } -- Gitee From c64ed4057266f81e51ef3a02da64e81a866014c0 Mon Sep 17 00:00:00 2001 From: dsdsdshe Date: Thu, 12 Sep 2024 19:37:35 +0800 Subject: [PATCH 9/9] add warning of ham having imag coefficient --- mindquantum/core/operators/hamiltonian.py | 9 +++++++++ .../test_simulator/test_basic_gate_with_simulator.py | 11 +++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/mindquantum/core/operators/hamiltonian.py b/mindquantum/core/operators/hamiltonian.py index b2204bef8..83d8f5a4b 100644 --- a/mindquantum/core/operators/hamiltonian.py +++ b/mindquantum/core/operators/hamiltonian.py @@ -15,6 +15,7 @@ """Hamiltonian module.""" # pylint: disable=too-many-instance-attributes,no-member from enum import Enum +import warnings import numpy as np import scipy.sparse as sp @@ -85,9 +86,17 @@ class Hamiltonian: self.how_to = HowTo.ORIGIN self.n_qubits = count_qubits(hamiltonian) self.ham_termlist = [] + has_warned = False for i, j in self.hamiltonian.terms.items(): if not j.is_const(): raise ValueError("Hamiltonian cannot be parameterized.") + if abs(j.const.imag) > 1e-8 and not has_warned: + warnings.warn( + f"Hamiltonian coefficients must be real numbers. Imaginary part will be discarded.", + UserWarning, + stacklevel=2, + ) + has_warned = True self.ham_termlist.append((i, j.const.real)) self.ham_cpp = None diff --git a/tests/st/test_simulator/test_basic_gate_with_simulator.py b/tests/st/test_simulator/test_basic_gate_with_simulator.py index 10cefa8a3..5389009c0 100644 --- a/tests/st/test_simulator/test_basic_gate_with_simulator.py +++ b/tests/st/test_simulator/test_basic_gate_with_simulator.py @@ -784,16 +784,19 @@ def test_custom_gate_order(config): # pylint: disable=too-many-locals @pytest.mark.platform_x86_cpu @pytest.mark.env_onecard @pytest.mark.parametrize("config", list(filter(lambda x: x != 'stabilizer', SUPPORTED_SIMULATOR))) -@pytest.mark.parametrize("gate", single_parameter_gate + multi_parameter_gate) +@pytest.mark.parametrize("gate", none_parameter_gate + single_parameter_gate + multi_parameter_gate) def test_two_qubit_gate_order(config, gate): # pylint: disable=too-many-locals """ Description: test object qubits order of two qubit gates Expectation: success. """ virtual_qc, dtype = config - n_pr = len(signature(gate).parameters) - pr = np.random.rand(n_pr) * 2 * np.pi - g = gate(*pr) + if isinstance(gate, mq.NoneParameterGate): + g = gate() + else: + n_pr = len(signature(gate).parameters) + pr = np.random.rand(n_pr) * 2 * np.pi + g = gate(*pr) dim = 2**g.n_qubits g = g.on(list(reversed(range(g.n_qubits)))) init_state = np.random.rand(dim) + np.random.rand(dim) * 1j -- Gitee