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 184 forks source link

Allow fixed parameters in GeneralEncoder #252

Open nikhilkhatri opened 3 months ago

nikhilkhatri commented 3 months ago

This PR adds the ability to fix parameters of some parameterised gates in a GeneralEncoder.

This allows, for example, a single parameterised gate to have a fixed parameter, shared across all items in the batch, while all other parameters can be dynamically provided. The change is fully backwards compatible, and no changes need to be made to existing encoder definitions.

This supports ansatze which have some fixed gates which aren't Paulis or other named operators. I expect this could already be achieved by subclassing existing operators, but I think this imposes less effort on the user.

Opening this to gauge interest. Shall update documentation and tests pending feedback.

>>> import torchquantum as tq
>>> import torch
>>> 
>>> 
>>> enc1 = [{'input_idx': [0], 'func': 'rx', 'wires': [0]},
...        {'input_idx': [1], 'func': 'rx', 'wires': [1]},
...        {'input_idx': [2], 'func': 'rx', 'wires': [2]},
...        {'input_idx': [3], 'func': 'rx', 'wires': [3]}]
>>> 
>>> # Same as above, but now with 0.3 provided to the first RX gate always
>>> enc2 = [{'params': [0.3], 'func': 'rx', 'wires': [0]},
...        {'input_idx': [0], 'func': 'rx', 'wires': [1]},
...        {'input_idx': [1], 'func': 'rx', 'wires': [2]},
...        {'input_idx': [2], 'func': 'rx', 'wires': [3]}]
>>> 
>>> 
>>> e1 = tq.GeneralEncoder(enc1)
>>> e2 = tq.GeneralEncoder(enc2)
>>> 
>>> qdev = tq.QuantumDevice(4)
>>> 
>>> 
>>> params1 = torch.tensor([[0.3, 0.4, 0.5, 0.6], [0.3, 0, 0, 0]])
>>> params2 = torch.tensor([[0.4, 0.5, 0.6], [0, 0, 0]])
>>> 
>>> qdev.reset_states(2)
>>> e1(qdev, params1)
>>> print(qdev.get_states_1d())
tensor([[ 0.8970+0.0000j,  0.0000-0.2775j,  0.0000-0.2290j, -0.0709+0.0000j,
          0.0000-0.1818j, -0.0562+0.0000j, -0.0464+0.0000j,  0.0000+0.0144j,
          0.0000-0.1356j, -0.0419+0.0000j, -0.0346+0.0000j,  0.0000+0.0107j,
         -0.0275+0.0000j,  0.0000+0.0085j,  0.0000+0.0070j,  0.0022+0.0000j],
        [ 0.9888+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,
          0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,
          0.0000-0.1494j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,
          0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j]])
>>> 
>>> qdev.reset_states(2)
>>> e2(qdev, params2)
>>> print(qdev.get_states_1d())
tensor([[ 0.8970+0.0000j,  0.0000-0.2775j,  0.0000-0.2290j, -0.0709+0.0000j,
          0.0000-0.1818j, -0.0562+0.0000j, -0.0464+0.0000j,  0.0000+0.0144j,
          0.0000-0.1356j, -0.0419+0.0000j, -0.0346+0.0000j,  0.0000+0.0107j,
         -0.0275+0.0000j,  0.0000+0.0085j,  0.0000+0.0070j,  0.0022+0.0000j],
        [ 0.9888+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,
          0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,
          0.0000-0.1494j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,
          0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j]])
nikhilkhatri commented 3 months ago

Hi @GenericP3rson, could I get a first-pass review on this please?

nikhilkhatri commented 3 months ago

I've added the tests now @GenericP3rson !