\n", ">\n" ] } ], "source": [ "from mindquantum.core.circuit.channel_adder import ChannelAdderBase, SequentialAdder\n", "\n", "class CustomDepolarizingAdder(ChannelAdderBase):\n", " def __init__(self, q, p):\n", " self.q = q\n", " self.p = p\n", " super().__init__()\n", "\n", " def _accepter(self):\n", " return [lambda x: self.q in x.obj_qubits or self.q in x.ctrl_qubits]\n", "\n", " def _excluder(self):\n", " return [lambda x: isinstance(x, (G.Measure, G.NoiseGate))]\n", "\n", " def _handler(self, g):\n", " return Circuit([G.DepolarizingChannel(self.p).on(self.q)])\n", "\n", " def __repr__(self):\n", " return f\"CustomDepolarizingAdder\"\n", "\n", "seq_adder = SequentialAdder([\n", " MixerAdder([\n", " MeasureAccepter(),\n", " BitFlipAdder(flip_rate=0.01),\n", " ], add_after=False),\n", " CustomDepolarizingAdder(q=1, p=0.05),\n", "])\n", "print(seq_adder)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "" ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ = Circuit() + G.H(0) + G.RX('a').on(1) + G.Z(1, 0) + G.Measure().on(0)\n", "display_svg(circ.svg())\n", "new_circ = seq_adder(circ)\n", "new_circ.svg()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The custom quantum channel above can also be constructed using the predefined channels in MindQuantum." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SequentialAdder<\n", " MixerAdder<\n", " MeasureAccepter<>\n", " BitFlipAdder \n", " >\n", " MixerAdder<\n", " ReverseAdder<\n", " MeasureAccepter<>\n", " >\n", " NoiseExcluder<>\n", " NoiseChannelAdder \n", " >\n", ">\n" ] } ], "source": [ "from mindquantum.core.circuit import ReverseAdder, NoiseExcluder, NoiseChannelAdder\n", "seq_adder = SequentialAdder([\n", " MixerAdder([\n", " MeasureAccepter(),\n", " BitFlipAdder(flip_rate=0.01),\n", " ], add_after=False),\n", " MixerAdder([\n", " ReverseAdder(MeasureAccepter()),\n", " NoiseExcluder(),\n", " NoiseChannelAdder(G.DepolarizingChannel(0.05), focus_on=1),\n", " ])\n", "])\n", "print(seq_adder)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ " " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "seq_adder(circ).svg()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A more complex example\n", "\n", "We now build a more complex `ChannelAdder` example where the noise of single qubit gate operations on different bits of the chip can be ignored, while the two qubit gates have different depolarizing channels on different bits, and the measurement of the circuit has a bit flip error with a flip probability of 0.01.\n", "\n", "We assume that the depolarizing probability on different two bits are $p_{0, 1} = 0.01, p_{1, 2} = 0.02, p_{0, 2} = 0.03$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we define an `Adder` that meets the requirements:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "SequentialAdder<\n", " MixerAdder<\n", " NoiseExcluder<>\n", " ReverseAdder<\n", " MeasureAccepter<>\n", " >\n", " QubitNumberConstrain \n", " QubitIDConstrain<>\n", " DepolarizationChannelAdder \n", " >\n", " MixerAdder<\n", " NoiseExcluder<>\n", " ReverseAdder<\n", " MeasureAccepter<>\n", " >\n", " QubitNumberConstrain
\n", " QubitIDConstrain<>\n", " DepolarizationChannelAdder \n", " >\n", " MixerAdder<\n", " NoiseExcluder<>\n", " ReverseAdder<\n", " MeasureAccepter<>\n", " >\n", " QubitNumberConstrain
\n", " QubitIDConstrain<>\n", " DepolarizationChannelAdder \n", " >\n", " MixerAdder<\n", " NoiseExcluder<>\n", " MeasureAccepter<>\n", " BitFlipAdder
\n", " >\n", ">" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from mindquantum.core.circuit import QubitNumberConstrain, QubitIDConstrain, DepolarizingChannelAdder\n", "noise_adder = SequentialAdder([\n", " MixerAdder([\n", " NoiseExcluder(),\n", " ReverseAdder(MeasureAccepter()),\n", " QubitNumberConstrain(2),\n", " QubitIDConstrain([0, 1]),\n", " DepolarizingChannelAdder(0.01, 2)\n", " ]),\n", " MixerAdder([\n", " NoiseExcluder(),\n", " ReverseAdder(MeasureAccepter()),\n", " QubitNumberConstrain(2),\n", " QubitIDConstrain([1, 2]),\n", " DepolarizingChannelAdder(0.02, 2)\n", " ]),\n", " MixerAdder([\n", " NoiseExcluder(),\n", " ReverseAdder(MeasureAccepter()),\n", " QubitNumberConstrain(2),\n", " QubitIDConstrain([0, 2]),\n", " DepolarizingChannelAdder(0.03, 2)\n", " ]),\n", " MixerAdder([\n", " NoiseExcluder(),\n", " MeasureAccepter(),\n", " BitFlipAdder(0.01)\n", " ], add_after=False),\n", "])\n", "noise_adder" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Suppose the quantum circuit we want to process is the first-order Trotter approximation circuit of the time-evolving Hamiltonian\n", "\n", "$$H=a_{01} Z_0Z_1 + a_{12} Z_1Z_2 + b_0 X_0 + b_1 X_1 + b_2 X_2$$" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ " b_0 [X0] +\n", " b_1 [X1] +\n", " b_2 [X2] +\n", "a_01 [Z0 Z1] +\n", "a_12 [Z1 Z2]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from mindquantum.core.operators import TimeEvolution, QubitOperator\n", "\n", "ham = sum([\n", " QubitOperator('X0', 'b_0'),\n", " QubitOperator('X1', 'b_1'),\n", " QubitOperator('X2', 'b_2'),\n", " QubitOperator('Z0 Z1', 'a_01'),\n", " QubitOperator('Z1 Z2', 'a_12')\n", "])\n", "ham" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ " " ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ = TimeEvolution(ham).circuit\n", "circ.barrier()\n", "circ.measure_all()\n", "circ.svg()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is the processed quantum circuit after being processed by the ``noise_adder`` defined above:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ " " ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "noise_adder(circ).svg()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [ChannelAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/mindquantum.core.circuit.html#channel-adder) list\n", "\n", "Here are some of the existing [ChannelAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/mindquantum.core.circuit.html#channel-adder)s in MindQuantum and their specific meanings:\n", "\n", "|[ChannelAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/mindquantum.core.circuit.html#channel-adder)| Function|\n", "|--|--|\n", "|[ChannelAdderBase](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.ChannelAdderBase.html)|Add channels before or after quantum gates|\n", "|[NoiseChannelAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.NoiseChannelAdder.html)|Add a single-bit quantum channel|\n", "|[MeasureAccepter](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.MeasureAccepter.html)|Select measurement gates|\n", "|[ReverseAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.ReverseAdder.html)|Flip the accept and reject rules of the given channel adder|\n", "|[NoiseExcluder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.NoiseExcluder.html)|Exclude noise gates|\n", "|[BitFlipAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.BitFlipAdder.html)|Add a bit flip channel before or after the quantum gate|\n", "|[MixerAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.MixerAdder.html)|Execute all adders in sequence when the accept and reject sets of the sub-adders are met|\n", "|[SequentialAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.SequentialAdder.html)|Execute each adder in sequence|\n", "|[QubitNumberConstrain](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.QubitNumberConstrain.html)|Only apply noise channels to quantum gates with ``n_qubits`` bits|\n", "|[QubitIDConstrain](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.QubitIDConstrain.html)|Only apply noise channels to quantum gates with the given bit number|\n", "|[GateSelector](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.GateSelector.html)|Select gate to add noise channel|\n", "|[DepolarizingChannelAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/circuit/mindquantum.core.circuit.DepolarizingChannelAdder.html)|Add DepolarizingChannel|\n", "\n", "For API documentation of [ChannelAdder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/mindquantum.core.circuit.html#channel-adder) in MindQuantum, please refer to: [channel_adder](https://www.mindspore.cn/mindquantum/docs/en/r0.9/core/mindquantum.core.circuit.html#channel-adder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Noise simulator based on `ChannelAdder`\n", "\n", "We can combine the various `Adder` defined above with existing simulators to create a noisy simulator." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "" ], "text/plain": [ " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from mindquantum.simulator import Simulator\n", "from mindquantum.simulator.noise import NoiseBackend\n", "\n", "noiseless_sim = Simulator('mqvector', 2)\n", "noiseless_circ = Circuit().h(0).rx(1.0, 1).z(1, 0).measure(1)\n", "display_svg(noiseless_circ.svg())\n", "res1 = noiseless_sim.sampling(noiseless_circ, shots=10000)\n", "display(res1.svg())" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "" ], "text/plain": [ " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "noise_sim = Simulator(NoiseBackend('mqvector', 2, seq_adder))\n", "res2 = noise_sim.sampling(noiseless_circ, shots=10000)\n", "display(res2.svg())\n", "display(noise_sim.backend.transform_circ(noiseless_circ).svg())" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", "
\n" ], "text/plain": [ "\n", " \n", "Software \n", "Version \n", "\n", " mindquantum 0.9.0 \n", " scipy 1.10.1 \n", " numpy 1.24.4 \n", " \n", "System \n", "Info \n", "Python 3.8.17 OS Linux x86_64 Memory 16.62 GB CPU Max Thread 16 \n", " Date Tue Oct 31 14:52:29 2023 " ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from mindquantum.utils.show_info import InfoTable\n", "\n", "InfoTable('mindquantum', 'scipy', 'numpy')" ] } ], "metadata": { "kernelspec": { "display_name": "MindSpore", "language": "python", "name": "mindspore" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.17" } }, "nbformat": 4, "nbformat_minor": 2 }