mit-han-lab / torchquantum

A PyTorch-based framework for Quantum Classical Simulation, Quantum Machine Learning, Quantum Neural Networks, Parameterized Quantum Circuits with support for easy deployments on real quantum computers.
https://torchquantum.org
MIT License
1.24k stars 185 forks source link

One question about noise in quantumnat.py #104

Open caitaozhan opened 1 year ago

caitaozhan commented 1 year ago

Hi Hanrui,

Code below from examples/quantumnat.py loads the noise model from IBM's ibmq_quito machine

    noise_model_tq = tq.NoiseModelTQ(
        noise_model_name="ibmq_quito",
        n_epochs=n_epochs,
        noise_total_prob=0.5,
        factor=0.1,
        add_thermal=True,
    )

Then I print the _parseddict from _noise_modeldict, however, I find that there is no noise for u3 gate and cu3 gate. See below:

print(self.parsed_dict.keys())
--> dict_keys(['id', 'sx', 'x', 'cx', 'reset', 'measure'])

I also tried all other free available IBM quantum machines, such as ibm_perth, ibm_lagos, etc. (9 free in total), and I find out that none has a noise model for u3, and cu3 gate.

Question: Is it true these free available IBM quantum machines don't have a noise model for u3 and cu3 gate? My parameterized quantum circuit has u3 and cu3 gates, and I need a noise model for these two. Did I miss anything here?

Thanks in advance! Caitao

Hanrui-Wang commented 1 year ago

Hi Caitao,

Yes, the IBM quantum machine doesn't provide the noise modeling for u3 and cu3 gates, they only have noise models for their native gates, which are 'id', 'sx', 'x', 'cx', 'reset', 'measure'. If you would like to add noise to u3 and cu3 gates, I suggest to transpile them to native gates then add noise to them.

caitaozhan commented 1 year ago

Hi Hanrui,

I see. I have a question about an expected thing happening. I ran the quantumnat.py and did some profiling (adding self.counter_x, self.counter_y, self.counter_z) in the _NoiseModelTQ.sample_noiseop() function and observed a strange thing: only see PauliZ error is occurring. I am expecting that PauliX, PauliY, and PauliZ are all happening somewhat evenly, but only the PauliZ is happening. Is it normal, or did I do something wrong?

        ops = []
        for instruction in instructions:
            v_wires = [
                self.p_v_reg_mapping["p2v"][qubit] for qubit in instruction["qubits"]
            ]
            if instruction["name"] == "x":
                op = tq.PauliX(wires=v_wires)
                self.counter_x += 1
                print(f'{op_name} # x = {self.counter_x} ')     <--print when PauliX error happens
            elif instruction["name"] == "y":
                op = tq.PauliY(wires=v_wires)
                self.counter_y += 1
                print(f'{op_name} # y = {self.counter_y} ')     <--print when PauliY error happens
            elif instruction["name"] == "z":
                op = tq.PauliZ(wires=v_wires)
                self.counter_z += 1
                print(f'{op_name} # z = {self.counter_z} ')     <--print when PauliZ error happens
            elif instruction["name"] == "reset":
                op = tq.Reset(wires=v_wires)
            else:
                # ignore operations specified by self.ignored_ops
                logger.warning(f"skip noise operation {instruction['name']}")
                continue
            ops.append(op)

        return ops

Also, I need to increase the factor to 100 (factor is a parameter to construct a NoiseModelTQ object) to observe some obvious noise. So it seems that the effect of noise is minimal when using factor=1, or is the example model in quantumnat.py too small (only 57 gates before transpile), so not affected by the noise a lot? I am curious during your experiments, do you need to increase the factor parameter?

Thanks for your time! Caitao

Hanrui-Wang commented 1 year ago

Hi Caitao,

I have merged the PR. I think for single qubit operations, the probability for x y z are not the same. we can see the third entry [{'name': 'id', 'qubits': [0]}, {'name': 'z', 'qubits': [0]}] has pretty large probability compared with others. The second large is the y error. x error is pretty small.

for the 'sx' operation below

we have: {'type': 'qerror', 'id': '3b46c51e30804c209684bb7925e81dab', 'operations': ['sx'], 'instructions': [[{'name': 'id', 'qubits': [0]}, {'name': 'id', 'qubits': [0]}], [{'name': 'id', 'qubits': [0]}, {'name': 'z', 'qubits': [0]}], [{'name': 'id', 'qubits': [0]}, {'name': 'reset', 'qubits': [0]}], [{'name': 'x', 'qubits': [0]}, {'name': 'id', 'qubits': [0]}], [{'name': 'x', 'qubits': [0]}, {'name': 'z', 'qubits': [0]}], [{'name': 'x', 'qubits': [0]}, {'name': 'reset', 'qubits': [0]}], [{'name': 'y', 'qubits': [0]}, {'name': 'id', 'qubits': [0]}], [{'name': 'y', 'qubits': [0]}, {'name': 'z', 'qubits': [0]}], [{'name': 'y', 'qubits': [0]}, {'name': 'reset', 'qubits': [0]}], [{'name': 'z', 'qubits': [0]}, {'name': 'id', 'qubits': [0]}], [{'name': 'z', 'qubits': [0]}, {'name': 'z', 'qubits': [0]}], [{'name': 'z', 'qubits': [0]}, {'name': 'reset', 'qubits': [0]}]], 'probabilities': [ 0.9993659966232363, 3.579606708404507e-05, 0.0003028957754461616, 9.840382835998485e-05, 3.5247047159929088e-09, 2.9825013056958735e-08, 9.840382835998485e-05, 3.5247047159929088e-09, 2.9825013056958735e-08, 9.840382835998485e-05, 3.5247047159929088e-09, 2.9825013056958735e-08], 'gate_qubits': [(1,)]}

for your PR, the number of pauliX and pauliY is increase, i guess that is mainly because the twoqubit paulis?