ValueError: cannot reshape array of size 16 into shape (2,2,2,2,2,2)

Hello! I am trying to implement an encoding circuit for an image using pennylane. Below is the code I used to create the circuit.

# Put code here
dev = qml.device("default.qubit", wires = 8)

# Define the coefficients of the state
coefficient_0 = 1/np.sqrt(2)
coefficient_1 = 1/np.sqrt(2)

# Define the state vector as a numpy array
state_vector = np.array([coefficient_0, coefficient_1])


@qml.qnode(dev)
def encoding_circ(pixel_val):
    qml.Hadamard(wires=0)
    qml.Hadamard(wires=1)
    qml.ArbitraryStatePreparation(state_vector, wires = [2])
    ## Band 1
    qml.RY(pixel_val[0], wires = 3)
    qml.CRY(pixel_val[1], wires = [0,3])
    qml.CRY(pixel_val[2], wires = [1,3])
    qml.CRY(pixel_val[3], wires = [(0,1),3])
    qml.Barrier()

    ## Band 2
    qml.RY(pixel_val[4], wires = 3)
    qml.CRY(pixel_val[5], wires = [0,3])
    qml.CRY(pixel_val[6], wires = [1,3])
    qml.CRY(pixel_val[7], wires = [(0,1),3])
    qml.Barrier()
    
    ## Band 3
    qml.RY(pixel_val[8], wires = 3)
    qml.CRY(pixel_val[9], wires = [0,3])
    qml.CRY(pixel_val[10], wires = [1,3])
    qml.CRY(pixel_val[11], wires = [(0,1),3])

    return qml.expval(qml.PauliZ(3))

print(qml.draw_mpl(encoding_circ)([0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.2,0.3,0.4,0.5,0.6]))

I convert the circuit into a pytorch layer and try to encode the image using a 2x2 patch.

## Creating Pytorch layers for the Encoding and Convolution Circuits
class QuantumEncodingLayer(nn.Module):
    def __init__(self):
        super(QuantumEncodingLayer, self).__init__()
        self.encoded_img = []

    def forward(self, x):
        for j in range(0, 128, 2):
            for k in range(0, 128, 2):
                pixel_val = [x[j, k, 0],x[j, k+1, 0],x[j+1, k, 0],x[j+1, k+1, 0],x[j, k, 1],x[j, k+1, 1],x[j+1, k, 1],x[j+1, k+1, 1],x[j, k, 2],x[j, k+1, 2],x[j+1, k, 2],x[j+1, k+1, 2]]
                print(len(pixel_val))
                pixel_enc = encoding_circ(pixel_val)

                self.encoded_img.append(pixel_enc)

        self.encoded_img = np.array(self.encoded_img)
        encoded_img_reshaped = self.encoded_img.reshape(4,4)
        return torch.tensor(encoded_img_reshaped)
encode_layer = QuantumEncodingLayer()

op = encode_layer(temp_im)

However, when I try to pass the image through the layer, I get the below error and not sure where it is originating from. Any help would be appreciated.

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[41], line 3
      1 encode_layer = QuantumEncodingLayer()
----> 3 op = encode_layer(temp_im)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\torch\nn\modules\module.py:1532, in Module._wrapped_call_impl(self, *args, **kwargs)
   1530     return self._compiled_call_impl(*args, **kwargs)  # type: ignore[misc]
   1531 else:
-> 1532     return self._call_impl(*args, **kwargs)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\torch\nn\modules\module.py:1541, in Module._call_impl(self, *args, **kwargs)
   1536 # If we don't have any hooks, we want to skip the rest of the logic in
   1537 # this function, and just call forward.
   1538 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks
   1539         or _global_backward_pre_hooks or _global_backward_hooks
   1540         or _global_forward_hooks or _global_forward_pre_hooks):
-> 1541     return forward_call(*args, **kwargs)
   1543 try:
   1544     result = None

Cell In[40], line 12
     10         pixel_val = [x[j, k, 0],x[j, k+1, 0],x[j+1, k, 0],x[j+1, k+1, 0],x[j, k, 1],x[j, k+1, 1],x[j+1, k, 1],x[j+1, k+1, 1],x[j, k, 2],x[j, k+1, 2],x[j+1, k, 2],x[j+1, k+1, 2]]
     11         print(len(pixel_val))
---> 12         pixel_enc = encoding_circ(pixel_val)
     14         self.encoded_img.append(pixel_enc)
     16 self.encoded_img = np.array(self.encoded_img)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\workflow\qnode.py:1098, in QNode.__call__(self, *args, **kwargs)
   1095 self._update_gradient_fn(shots=override_shots, tape=self._tape)
   1097 try:
-> 1098     res = self._execution_component(args, kwargs, override_shots=override_shots)
   1099 finally:
   1100     if old_interface == "auto":

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\workflow\qnode.py:1052, in QNode._execution_component(self, args, kwargs, override_shots)
   1049 full_transform_program.prune_dynamic_transform()
   1051 # pylint: disable=unexpected-keyword-arg
-> 1052 res = qml.execute(
   1053     (self._tape,),
   1054     device=self.device,
   1055     gradient_fn=self.gradient_fn,
   1056     interface=self.interface,
   1057     transform_program=full_transform_program,
   1058     config=config,
   1059     gradient_kwargs=self.gradient_kwargs,
   1060     override_shots=override_shots,
   1061     **self.execute_kwargs,
   1062 )
   1063 res = res[0]
   1065 # convert result to the interface in case the qfunc has no parameters

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\workflow\execution.py:616, in execute(tapes, device, gradient_fn, interface, transform_program, config, grad_on_execution, gradient_kwargs, cache, cachesize, max_diff, override_shots, expand_fn, max_expansion, device_batch_transform, device_vjp)
    614 # Exiting early if we do not need to deal with an interface boundary
    615 if no_interface_boundary_required:
--> 616     results = inner_execute(tapes)
    617     return post_processing(results)
    619 _grad_on_execution = False

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\workflow\execution.py:297, in _make_inner_execute.<locals>.inner_execute(tapes, **_)
    294 transformed_tapes, transform_post_processing = transform_program(tapes)
    296 if transformed_tapes:
--> 297     results = device_execution(transformed_tapes)
    298 else:
    299     results = ()

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\modifiers\simulator_tracking.py:30, in _track_execute.<locals>.execute(self, circuits, execution_config)
     28 @wraps(untracked_execute)
     29 def execute(self, circuits, execution_config=DefaultExecutionConfig):
---> 30     results = untracked_execute(self, circuits, execution_config)
     31     if isinstance(circuits, QuantumScript):
     32         batch = (circuits,)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\modifiers\single_tape_support.py:32, in _make_execute.<locals>.execute(self, circuits, execution_config)
     30     is_single_circuit = True
     31     circuits = (circuits,)
---> 32 results = batch_execute(self, circuits, execution_config)
     33 return results[0] if is_single_circuit else results

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\default_qubit.py:593, in DefaultQubit.execute(self, circuits, execution_config)
    590 prng_keys = [self.get_prng_keys()[0] for _ in range(len(circuits))]
    592 if max_workers is None:
--> 593     return tuple(
    594         _simulate_wrapper(
    595             c,
    596             {
    597                 "rng": self._rng,
    598                 "debugger": self._debugger,
    599                 "interface": interface,
    600                 "state_cache": self._state_cache,
    601                 "prng_key": _key,
    602             },
    603         )
    604         for c, _key in zip(circuits, prng_keys)
    605     )
    607 vanilla_circuits = [convert_to_numpy_parameters(c) for c in circuits]
    608 seeds = self._rng.integers(2**31 - 1, size=len(vanilla_circuits))

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\default_qubit.py:594, in <genexpr>(.0)
    590 prng_keys = [self.get_prng_keys()[0] for _ in range(len(circuits))]
    592 if max_workers is None:
    593     return tuple(
--> 594         _simulate_wrapper(
    595             c,
    596             {
    597                 "rng": self._rng,
    598                 "debugger": self._debugger,
    599                 "interface": interface,
    600                 "state_cache": self._state_cache,
    601                 "prng_key": _key,
    602             },
    603         )
    604         for c, _key in zip(circuits, prng_keys)
    605     )
    607 vanilla_circuits = [convert_to_numpy_parameters(c) for c in circuits]
    608 seeds = self._rng.integers(2**31 - 1, size=len(vanilla_circuits))

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\default_qubit.py:841, in _simulate_wrapper(circuit, kwargs)
    840 def _simulate_wrapper(circuit, kwargs):
--> 841     return simulate(circuit, **kwargs)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\qubit\simulate.py:287, in simulate(circuit, debugger, state_cache, **execution_kwargs)
    282     return simulate_one_shot_native_mcm(
    283         circuit, debugger=debugger, rng=rng, prng_key=prng_key, interface=interface
    284     )
    286 ops_key, meas_key = jax_random_split(prng_key)
--> 287 state, is_state_batched = get_final_state(
    288     circuit, debugger=debugger, rng=rng, prng_key=ops_key, interface=interface
    289 )
    290 if state_cache is not None:
    291     state_cache[circuit.hash] = state

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\qubit\simulate.py:150, in get_final_state(circuit, debugger, **execution_kwargs)
    148 if isinstance(op, MidMeasureMP):
    149     prng_key, key = jax_random_split(prng_key)
--> 150 state = apply_operation(
    151     op,
    152     state,
    153     is_state_batched=is_state_batched,
    154     debugger=debugger,
    155     mid_measurements=mid_measurements,
    156     rng=rng,
    157     prng_key=key,
    158 )
    159 # Handle postselection on mid-circuit measurements
    160 if isinstance(op, qml.Projector):

File ~\AppData\Local\Programs\Python\Python312\Lib\functools.py:909, in singledispatch.<locals>.wrapper(*args, **kw)
    905 if not args:
    906     raise TypeError(f'{funcname} requires at least '
    907                     '1 positional argument')
--> 909 return dispatch(args[0].__class__)(*args, **kw)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\qubit\apply_operation.py:206, in apply_operation(op, state, is_state_batched, debugger, **_)
    152 @singledispatch
    153 def apply_operation(
    154     op: qml.operation.Operator,
   (...)
    158     **_,
    159 ):
    160     """Apply and operator to a given state.
    161 
    162     Args:
   (...)
    204 
    205     """
--> 206     return _apply_operation_default(op, state, is_state_batched, debugger)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\qubit\apply_operation.py:217, in _apply_operation_default(op, state, is_state_batched, debugger)
    212 if (
    213     len(op.wires) < EINSUM_OP_WIRECOUNT_PERF_THRESHOLD
    214     and math.ndim(state) < EINSUM_STATE_WIRECOUNT_PERF_THRESHOLD
    215 ) or (op.batch_size and is_state_batched):
    216     return apply_operation_einsum(op, state, is_state_batched=is_state_batched)
--> 217 return apply_operation_tensordot(op, state, is_state_batched=is_state_batched)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\pennylane\devices\qubit\apply_operation.py:129, in apply_operation_tensordot(op, state, is_state_batched)
    127     if op.batch_size is None:
    128         op._batch_size = batch_size  # pylint:disable=protected-access
--> 129 reshaped_mat = math.reshape(mat, new_mat_shape)
    131 mat_axes = list(range(-num_indices, 0))
    132 state_axes = [i + is_state_batched for i in op.wires]

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\autoray\autoray.py:81, in do(fn, like, *args, **kwargs)
     79 backend = _choose_backend(fn, args, kwargs, like=like)
     80 func = get_lib_fn(backend, fn)
---> 81 return func(*args, **kwargs)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\numpy\core\fromnumeric.py:285, in reshape(a, newshape, order)
    200 @array_function_dispatch(_reshape_dispatcher)
    201 def reshape(a, newshape, order='C'):
    202     """
    203     Gives a new shape to an array without changing its data.
    204 
   (...)
    283            [5, 6]])
    284     """
--> 285     return _wrapfunc(a, 'reshape', newshape, order=order)

File c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages\numpy\core\fromnumeric.py:59, in _wrapfunc(obj, method, *args, **kwds)
     56     return _wrapit(obj, method, *args, **kwds)
     58 try:
---> 59     return bound(*args, **kwds)
     60 except TypeError:
     61     # A TypeError occurs if the object does have such a method in its
     62     # class, but its signature is not identical to that of NumPy's. This
   (...)
     66     # Call _wrapit from within the except clause to ensure a potential
     67     # exception has a traceback chain.
     68     return _wrapit(obj, method, *args, **kwds)

ValueError: cannot reshape array of size 16 into shape (2,2,2,2,2,2)

Below is the output of qml.about()

Name: PennyLane
Version: 0.36.0
Summary: PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Home-page: https://github.com/PennyLaneAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: c:\Personal_Projects\Quantum_ML\Quantum_ML\QML-venv\Lib\site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane_Lightning

Platform info:           Windows-11-10.0.22631-SP0
Python version:          3.12.0
Numpy version:           1.26.4
Scipy version:           1.13.1
Installed devices:
- default.clifford (PennyLane-0.36.0)
- default.gaussian (PennyLane-0.36.0)
- default.mixed (PennyLane-0.36.0)
- default.qubit (PennyLane-0.36.0)
- default.qubit.autograd (PennyLane-0.36.0)
- default.qubit.jax (PennyLane-0.36.0)
- default.qubit.legacy (PennyLane-0.36.0)
- default.qubit.tf (PennyLane-0.36.0)
- default.qubit.torch (PennyLane-0.36.0)
- default.qutrit (PennyLane-0.36.0)
- default.qutrit.mixed (PennyLane-0.36.0)
- null.qubit (PennyLane-0.36.0)
- lightning.qubit (PennyLane_Lightning-0.36.0)

Hi @Hrithik_Kumar , welcome to the forum!

What is temp_im? Sharing a self-contained version of your code can help us help you.

From the error it looks like there’s a dimension mismatch somewhere. Try not to only print the length of pixel_val but the whole pixel_val. It looks to me like you’re inputting something with more than one dimension into the quantum circuit and then the circuit is struggling to do batching on that data.

If you’re interested in working with images maybe this demo on quanvolutional neural networks will be interesting to you.

I hope this helps you!

Hi @CatalinaAlbornoz , temp_im is an image of shape (128,128,3). Even if I try to pass a list of 12 values to the circuit, it throws the same error.

Hi @Hrithik_Kumar ,

The issue here is with how you’re using CRY. Note that this takes only one control, not two. Three times in the circuit you’re adding two control wires which makes the code fail.

If you really need a CCRY then you should use qml.ctrl, adding first the first control wire as part of qml.ctrl, and then applying the arguments for your gate, which in this case is CRY.

So use this code

qml.ctrl(qml.CRY,0)(pixel_val[7], wires = [1,3])

Instead of this one

qml.CRY(pixel_val[7], wires = [(0,1),3])

If this was a mistake and you just needed a single control wire then feel free to adapt the line to remove it.

I hope this helps you.

1 Like