Hi @scichy,
as far as I am aware, there currently is no UI functionality to do this.
However, it is certainly doable, by manipulating the private _wires
of each factor in the Tensor
objects, for each term in the Hamiltonian
:
Start by defining the wires remapping as a dict
:
wires_map = {0: 1, 1: 0, 2: 2}
Then, iterate over all terms in H
, and over all observable factors in each term, and apply this remapping via qml.wires.Wires.map
:
new_ops = []
for op in H.ops:
new_obs = []
for ob in op.obs:
ob._wires = ob.wires.map(wires_map)
new_obs.append(ob)
new_ops.append(qml.operation.Tensor(*new_obs))
new_H = qml.Hamiltonian(H.coeffs, new_ops)
This works specifically for Hamiltonian
, but of course the inner loop could also just be applied to a single Tensor
object, or the map
approach without any loop to a single Observable
like qml.PauliX(3)
.
To make it a bit more convenient, here is a function that tackles all three cases:
def map_wires(H, wires_map):
"""Map the wires of an Observable according to a wires map.
Args:
H (Hamiltonian or Tensor or Observable): Hamiltonian to remap the wires of.
wires_map (dict): Wires map with `(origin, destination)` pairs as key-value pairs.
Returns:
Hamiltonian or Tensor or Observable: A copy of the original Hamiltonian with remapped wires.
"""
if isinstance(H, qml.Hamiltonian):
new_ops = [map_wires(op, wires_map) for op in H.ops]
new_H = qml.Hamiltonian(H.coeffs, new_ops)
elif isinstance(H, qml.operation.Tensor):
new_obs = [map_wires(ob, wires_map) for ob in H.obs]
new_H = qml.operation.Tensor(*new_obs)
elif isinstance(H, qml.operation.Observable):
new_H = copy.copy(H)
new_H._wires = new_H.wires.map(wires_map)
return new_H
Please note that this is untested custom code, so look out for bugs etc.
Also it is not optimized for performance…
It seems to be doing what we want, though
wires_map = {i: i+10 for i in range(5)}
Hs = [
qml.PauliX(4),
qml.operation.Tensor(qml.PauliX(0), qml.Hadamard(2), qml.PauliZ(4)),
qml.Hamiltonian(
[1,1],
[
qml.operation.Tensor(qml.PauliZ(0), qml.PauliX(1), qml.PauliZ(2)),
qml.operation.Tensor(qml.PauliX(0), qml.PauliZ(1), qml.PauliX(2)),
],
),
]
>>> for H in Hs:
>>> print(H)
>>> new_H = map_wires(H, wires_map)
>>> print(new_H)
PauliX(wires=[4])
PauliX(wires=[14])
PauliX(wires=[0]) @ Hadamard(wires=[2]) @ PauliZ(wires=[4])
PauliX(wires=[10]) @ Hadamard(wires=[12]) @ PauliZ(wires=[14])
(1) [Z0 X1 Z2]
+ (1) [X0 Z1 X2]
(1) [Z10 X11 Z12]
+ (1) [X10 Z11 X12]
Hope this helps! Let me know if you have any questions.
Side note: ExpvalCost
is deprecated, you may just use expval
on a Hamiltonian
object (see e.g. here)