Source code for quantum_launcher.hampy.object

  1from typing import Union, overload
  2from qiskit.quantum_info import SparsePauliOp
  3
  4
[docs] 5class Equation: 6 @overload 7 def __init__(self, size: int): ... 8 @overload 9 def __init__(self, hamiltonian: SparsePauliOp): ... 10 @overload 11 def __init__(self, sparse_list: list[tuple], size: int): ... 12 13 def __init__(self, argument, *args): 14 if isinstance(argument, int): 15 self.size = argument 16 self._hamiltonian = SparsePauliOp.from_sparse_list([('I', [], 0)], argument) 17 elif isinstance(argument, SparsePauliOp): 18 self.size = argument.num_qubits 19 self._hamiltonian = argument 20 elif isinstance(argument, list) and len(args) > 0 and isinstance(args[0], int): 21 self.size = args[0] 22 self._hamiltonian = SparsePauliOp.from_sparse_list(argument, args[0]) 23 else: 24 raise TypeError('Wrong arguments!') 25
[docs] 26 def get_variable(self, index: int) -> "Variable": 27 assert isinstance(index, int), "Index needs to be an integer" 28 obj = Variable(index, self) 29 return obj
30 31 @property 32 def hamiltonian(self) -> SparsePauliOp: 33 return self._hamiltonian.simplify() 34 35 @hamiltonian.setter 36 def hamiltonian(self, new_hamiltonian: SparsePauliOp): 37 self._hamiltonian = new_hamiltonian 38
[docs] 39 def to_sparse_pauli_op(self) -> SparsePauliOp: 40 return self.hamiltonian
41
[docs] 42 def get_order(self) -> int: 43 equation_order = 0 44 for Z_term in self.hamiltonian.paulis: 45 equation_order = max(equation_order, str(Z_term).count('Z')) 46 return equation_order
47
[docs] 48 def is_quadratic(self) -> bool: 49 return all(term.z.sum() <= 2 for term in self.hamiltonian.paulis)
50 51 def __or__(self, other: Union["Variable", "Equation"], /) -> "Equation": 52 if isinstance(other, Variable): 53 other = other.to_equation() 54 55 return Equation(self.hamiltonian + other.hamiltonian - self.hamiltonian.compose(other.hamiltonian)) 56 57 def __and__(self, other: Union["Variable", "Equation"], /) -> "Equation": 58 if isinstance(other, Variable): 59 other = other.to_equation() 60 61 return Equation(self.hamiltonian.compose(other.hamiltonian)) 62 63 def __xor__(self, other: Union["Variable", "Equation"], /) -> "Equation": 64 if isinstance(other, Variable): 65 other = other.to_equation() 66 67 return Equation(self.hamiltonian + other.hamiltonian - (2 * self.hamiltonian.compose(other.hamiltonian))) 68 69 def __invert__(self) -> "Equation": 70 I = ('I', [], 1) 71 identity = SparsePauliOp.from_sparse_list([I], self.size) 72 return Equation(identity - self.hamiltonian) 73 74 def __getitem__(self, variable_number: int): 75 return self.get_variable(variable_number) 76 77 def __eq__(self, other: "Equation") -> bool: 78 if isinstance(other, Variable): 79 other = other.to_equation() 80 81 return self.hamiltonian == other.hamiltonian 82 83 def __add__(self, other: Union["Equation", "Variable"]) -> "Equation": 84 if isinstance(other, Variable): 85 other = other.to_equation() 86 87 return Equation(self.hamiltonian + other.hamiltonian) 88 89 def __radd__(self, other: "Equation") -> "Equation": 90 if isinstance(other, Variable): 91 other = other.to_equation() 92 93 return Equation(self.hamiltonian + other.hamiltonian) 94 95 def __mul__(self, other: Union["Equation", float]) -> "Equation": 96 if isinstance(other, Variable): 97 other = other.to_equation() 98 if isinstance(other, float) or isinstance(other, int): 99 return Equation(float(other) * self.hamiltonian) 100 return Equation(self.hamiltonian.compose(other.hamiltonian)) 101 102 def __rmul__(self, other: Union["Equation", float]) -> "Equation": 103 if isinstance(other, Variable): 104 other = other.to_equation() 105 if isinstance(other, float) or isinstance(other, int): 106 return Equation(float(other) * self.hamiltonian) 107 return Equation(self.hamiltonian.compose(other.hamiltonian))
108 109
[docs] 110class Variable: 111 def __init__(self, index: int, parent: Equation): 112 self.index = index 113 self.size = parent.size 114 115 def __xor__(self, other: Union["Variable", Equation], /) -> Equation: 116 if isinstance(other, Equation): 117 return self.to_equation() ^ other 118 119 I = ('I', [], 0.5) 120 Z_term = ('ZZ', [self.index, other.index], -0.5) 121 eq = Equation(SparsePauliOp.from_sparse_list([I, Z_term], self.size)) 122 return eq 123 124 def __or__(self, other: Union["Variable", Equation], /) -> Equation: 125 if isinstance(other, Equation): 126 return self.to_equation() | other 127 128 I_term = ('I', [], 0.75) 129 Z1_term = ('Z', [self.index], -0.25) 130 Z2_term = ('Z', [other.index], -0.25) 131 ZZ_term = ('ZZ', [self.index, other.index], -0.25) 132 eq = Equation([I_term, Z1_term, Z2_term, ZZ_term], self.size) 133 return eq 134 135 def __and__(self, other: Union["Variable", Equation], /) -> Equation: 136 137 if isinstance(other, Equation): 138 return self.to_equation() & other 139 140 I_term = ('I', [], 0.25) 141 Z1_term = ('Z', [self.index], -0.25) 142 Z2_term = ('Z', [other.index], -0.25) 143 ZZ_term = ('ZZ', [self.index, other.index], 0.25) 144 eq = Equation([I_term, Z1_term, Z2_term, ZZ_term], self.size) 145 return eq 146 147 def __invert__(self) -> Equation: 148 I_term = ('I', [], 0.5) 149 Z_term = ('Z', [self.index], 0.5) 150 return Equation([I_term, Z_term], self.size) 151
[docs] 152 def to_equation(self) -> Equation: 153 I_term = ('I', [], 0.5) 154 Z_term = ('Z', [self.index], -0.5) 155 return Equation([I_term, Z_term], self.size)