ValueError: p > 1 when playing with the numbers of shots


#1

Hello,

I’ve implemented a pytorch model which takes a device when created.
I’m defining the qnode in the forward.

class mymodel(nn.Module):
    def __init__(self,device, n_wires, n_features):
        super(mymodel, self).__init__()
        self.device = device
        self.n_wires =n_wires
        self.n_features= n_features
        self.CE = torch.nn.Tanh()
        self.wires_to_encode = list(range(0,n_wires))
        self.QC_optvar = torch.nn.Parameter(torch.randn((1, 3, n_wires), requires_grad =True))
        
    def forward(self, x):

        x = self.CE(x)
        @qml.qnode(self.device, interface='torch')
        def circuit(x,QC_optvar):
            embedding.AmplitudeEmbedding(x, self.wires_to_encode)
            QC_layparam = QC_optvar[0,:,:]
            stronglayer(QC_layparam,r=1, n_wires = self.n_wires)
            return qml.expval.PauliZ(0)

        out = 0.5*(1+(circuit(x,self.QC_optvar)))
        out = out.unsqueeze(0)
        return torch.cat((out,1-out,))#0.5*(1+(circuit(x,QE_param,self.QC_optvar)))

    def num_flat_features(self, x):
        size = x.size()[1:]  # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        print('numflat',num_features)
        return num_features

When the device is simply the dev = qml.device('default.qubit', wires=2) it is working just fine.
When I’m changing it to dev = qml.device('default.qubit', wires=2, shots = 10) I get the following error :

ValueError                                Traceback (most recent call last)
<ipython-input-57-35e78050c922> in <module>
     11 sample = train_dataset[j]
     12 X, label = sample['X'], sample['label']
---> 13 output = model(X)

~\.conda\envs\penny\lib\site-packages\torch\nn\modules\module.py in __call__(self, *input, **kwargs)
    487             result = self._slow_forward(*input, **kwargs)
    488         else:
--> 489             result = self.forward(*input, **kwargs)
    490         for hook in self._forward_hooks.values():
    491             hook_result = hook(self, input, result)

<ipython-input-55-cce0fb3f986b> in forward(self, x)
     36 
     37         #QC
---> 38         out = 0.5*(1+(circuit(x,self.QC_optvar)))
     39         out = out.unsqueeze(0)
     40 #         print(type(out),out,out.shape)

~\.conda\envs\penny\lib\site-packages\pennylane\interfaces\torch.py in custom_apply(*args, **kwargs)
    388         # [keyword_values[k] for k in sorted(keyword_positions, key=keyword_positions.get)]
    389 
--> 390         return _TorchQNode.apply(keyword_values, *args)
    391 
    392     return custom_apply

~\.conda\envs\penny\lib\site-packages\pennylane\interfaces\torch.py in forward(ctx, input_kwargs, *input_)
    305 
    306             # evaluate the QNode
--> 307             res = qnode(*ctx.args, **ctx.kwargs)
    308 
    309             if not isinstance(res, np.ndarray):

~\.conda\envs\penny\lib\site-packages\pennylane\qnode.py in __call__(self, *args, **kwargs)
    511         # pylint: disable=no-member
    512         args = autograd.builtins.tuple(args)  # prevents autograd boxed arguments from going through to evaluate
--> 513         return self.evaluate(args, **kwargs)  # args as one tuple
    514 
    515     @ae.primitive

~\.conda\envs\penny\lib\site-packages\autograd\tracer.py in f_wrapped(*args, **kwargs)
     46             return new_box(ans, trace, node)
     47         else:
---> 48             return f_raw(*args, **kwargs)
     49     f_wrapped.fun = f_raw
     50     f_wrapped._is_autograd_primitive = True

~\.conda\envs\penny\lib\site-packages\pennylane\qnode.py in evaluate(self, args, **kwargs)
    584             check_op(op)
    585 
--> 586         ret = self.device.execute(self.queue, self.ev)
    587         return self.output_type(ret)
    588 

~\.conda\envs\penny\lib\site-packages\pennylane\_device.py in execute(self, queue, observables)
    214             for obs in observables:
    215                 if obs.return_type == "expectation":
--> 216                     results.append(self.expval(obs.name, obs.wires, obs.parameters))
    217                 elif obs.return_type == "variance":
    218                     results.append(self.var(obs.name, obs.wires, obs.parameters))

~\.conda\envs\penny\lib\site-packages\pennylane\plugins\default_qubit.py in expval(self, observable, wires, par)
    366             a, P = spectral_decomposition_qubit(A)
    367             p0 = self.ev(P[0], wires)  # probability of measuring a[0]
--> 368             n0 = np.random.binomial(self.shots, p0)
    369             ev = (n0*a[0] +(self.shots-n0)*a[1]) / self.shots
    370 

mtrand.pyx in mtrand.RandomState.binomial()

ValueError: p > 1

It looks like a bug, or maybe I have done something wrong…


#2

Hi @barthelemymp,

This looks like a numerical bug. If you check out the numpy docs, you’ll see that the function np.random.binomial which is causing the error takes a second argument p, which should be a probability (between 0 and 1). Obviously the variable p0 that gets passed to it in your example doesn’t fit these conditions.

However, I just inspected the other parts of the code that lead to p0, and they should result in a valid probability. My guess is that there is probably some tiny overflow (i.e., p0=1.0001 or something). In order to confirm (or refute) this guess, would you be able to drop a debug/print statement which shows the value of p0 in between lines 367 and 368 of the file located at ~\.conda\envs\penny\lib\site-packages\pennylane\plugins\default_qubit.py and rerun your code?


#3

Thank you @nathan,

However the overflow is not tiny. I made the test 3 time and got 1.1, 2.3, and 0.7 (the last case did not create the error message).

Thank you again for your help,

b


#4

Hi @barthelemymp,

That definitely sounds like a bug then. I’ll make an issue on github and we’ll look into it deeper.

(bug reported here)


#5

Hey @nathan

After playing a bit with my code, it seems that the error is (at least partly) coming from the function AmplitudeEmbedding. Indeed by encoding differently my data, I’m not having this issue anymore.

I hope it will help,

regards

Barthélémy


#6

Good to hear there was a workaround. We’ll still try to track down what caused it though :thinking:


#7

Hi @barthelemymp, I just skimmed through the code of AmplitudeEncoding(features, wires). In the docstring it says

The absolute square of all elements in ``features`` has to add up to one.

Is this the case in your code? I can imagine that this might cause the problems at a later stage.


#8

Hi @barthelemymp,

We have now enhanced the amplitude embedding template function to take care of normalisation and padding automatically (see https://pennylane.readthedocs.io/en/latest/code/templates/embeddings.html#pennylane.templates.embeddings.AmplitudeEmbedding). You can update your PennyLane version from the master branch on github.

Thank you for your feedback.