def _two_body_mapping(h2_ijkm_a_ijkm, threshold): """ Subroutine for two body mapping. We use the chemists notation for the two-body term, h2(i,j,k,m) adag_i adag_k a_m a_j. Args: h2_ijkm_aijkm (tuple): value of h2 at index (i,j,k,m), pauli at index i, pauli at index j, pauli at index k, pauli at index m threshold: (float): threshold to remove a pauli Returns: WeightedPauliOperator: Operator for those paulis """ h2_ijkm, a_i, a_j, a_k, a_m = h2_ijkm_a_ijkm pauli_list = [] for alpha in range(2): for beta in range(2): for gamma in range(2): for delta in range(2): pauli_prod_1 = Pauli.sgn_prod(a_i[alpha], a_k[beta]) pauli_prod_2 = Pauli.sgn_prod(pauli_prod_1[0], a_m[gamma]) pauli_prod_3 = Pauli.sgn_prod(pauli_prod_2[0], a_j[delta]) phase1 = pauli_prod_1[1] * pauli_prod_2[1] * pauli_prod_3[1] phase2 = np.power(-1j, alpha + beta) * np.power(1j, gamma + delta) pauli_term = [h2_ijkm / 16 * phase1 * phase2, pauli_prod_3[0]] if np.absolute(pauli_term[0]) > threshold: pauli_list.append(pauli_term) return WeightedPauliOperator(paulis=pauli_list)
def test_sgn_prod(self): """Test sgn prod.""" p1 = Pauli(np.array([False]), np.array([True])) p2 = Pauli(np.array([True]), np.array([True])) self.log.info("sign product:") p3, sgn = Pauli.sgn_prod(p1, p2) self.log.info("p1: %s", p1.to_label()) self.log.info("p2: %s", p2.to_label()) self.log.info("p3: %s", p3.to_label()) self.log.info("sgn_prod(p1, p2): %s", str(sgn)) self.assertEqual(p1.to_label(), 'X') self.assertEqual(p2.to_label(), 'Y') self.assertEqual(p3.to_label(), 'Z') self.assertEqual(sgn, 1j) self.log.info("sign product reverse:") p3, sgn = Pauli.sgn_prod(p2, p1) self.log.info("p2: %s", p2.to_label()) self.log.info("p1: %s", p1.to_label()) self.log.info("p3: %s", p3.to_label()) self.log.info("sgn_prod(p2, p1): %s", str(sgn)) self.assertEqual(p1.to_label(), 'X') self.assertEqual(p2.to_label(), 'Y') self.assertEqual(p3.to_label(), 'Z') self.assertEqual(sgn, -1j)
def compose(self, other: OperatorBase, permutation: Optional[List[int]] = None, front: bool = False) -> OperatorBase: new_self, other = self._expand_shorter_operator_and_permute( other, permutation) new_self = cast(PauliOp, new_self) if front: return other.compose(new_self) # If self is identity, just return other. if not any(new_self.primitive.x + new_self.primitive.z): # type: ignore return other * new_self.coeff # type: ignore # Both Paulis if isinstance(other, PauliOp): product, phase = Pauli.sgn_prod(new_self.primitive, other.primitive) return PrimitiveOp(product, coeff=new_self.coeff * other.coeff * phase) # pylint: disable=cyclic-import,import-outside-toplevel from .circuit_op import CircuitOp from ..state_fns.circuit_state_fn import CircuitStateFn if isinstance(other, (CircuitOp, CircuitStateFn)): return new_self.to_circuit_op().compose(other) return super(PauliOp, new_self).compose(other)
def _three_body_mapping(h3_ijkmpq_a_ijkmpq, threshold): """ Subroutine for three body mapping. We use the chemists notation for the two-body term, h2(i,j,k,m,p,q) adag_i adag_k adag_p a_q a_m a_j . Args: h2_ijkmpq_a_ijkmpq (tuple): value of h3 at index (i,j,k,m,p,q), pauli at index i, pauli at index j, pauli at index k, pauli at index m, pauli at index p, pauli at index q threshold (float): threshold to remove a pauli Returns: WeightedPauliOperator: Operator for those paulis """ h3_ijkmpq, a_i, a_j, a_k, a_m, a_p, a_q = h3_ijkmpq_a_ijkmpq pauli_list = [] for alpha in range(2): for beta in range(2): for gamma in range(2): for delta in range(2): for theta in range(2): for phi in range(2): pauli_prod_1 = Pauli.sgn_prod( a_i[alpha], a_k[beta]) pauli_prod_2 = Pauli.sgn_prod( pauli_prod_1[0], a_p[gamma]) pauli_prod_3 = Pauli.sgn_prod( pauli_prod_2[0], a_q[delta]) pauli_prod_4 = Pauli.sgn_prod( pauli_prod_3[0], a_m[theta]) pauli_prod_5 = Pauli.sgn_prod( pauli_prod_4[0], a_j[phi]) phase1 = pauli_prod_1[1] * pauli_prod_2[1] * pauli_prod_3[1] * \ pauli_prod_4[1] * pauli_prod_5[1] phase2 = np.power(-1j, alpha + beta + gamma) * \ np.power(1j, delta + theta + phi) pauli_term = [ h3_ijkmpq / 64 * phase1 * phase2, pauli_prod_5[0] ] if np.absolute(pauli_term[0]) > threshold: pauli_list.append(pauli_term) return WeightedPauliOperator(paulis=pauli_list)
def _two_body_mapping(h2_ijkm, a_i, a_j, a_k, a_m, threshold): """ Subroutine for two body mapping. Args: h1_ijkm (complex): value of h2 at index (i,j,k,m) a_i (Pauli): pauli at index i a_j (Pauli): pauli at index j a_k (Pauli): pauli at index k a_m (Pauli): pauli at index m threshold: (float): threshold to remove a pauli Returns: Operator: Operator for those paulis """ pauli_list = [] for alpha in range(2): for beta in range(2): for gamma in range(2): for delta in range(2): pauli_prod_1 = Pauli.sgn_prod(a_i[alpha], a_k[beta]) pauli_prod_2 = Pauli.sgn_prod(pauli_prod_1[0], a_m[gamma]) pauli_prod_3 = Pauli.sgn_prod(pauli_prod_2[0], a_j[delta]) phase1 = pauli_prod_1[1] * pauli_prod_2[ 1] * pauli_prod_3[1] phase2 = np.power(-1j, alpha + beta) * np.power( 1j, gamma + delta) pauli_term = [ h2_ijkm / 16 * phase1 * phase2, pauli_prod_3[0] ] if np.absolute(pauli_term[0]) > threshold: pauli_list.append(pauli_term) return Operator(paulis=pauli_list)
def multiply(self, other): """ Perform self * other, and the phases are tracked. Args: other (WeightedPauliOperator): an operator Returns: WeightedPauliOperator: the multiplied operator """ ret_op = WeightedPauliOperator(paulis=[]) for existed_weight, existed_pauli in self.paulis: for weight, pauli in other.paulis: new_pauli, sign = Pauli.sgn_prod(existed_pauli, pauli) new_weight = existed_weight * weight * sign pauli_term = [new_weight, new_pauli] ret_op += WeightedPauliOperator(paulis=[pauli_term]) return ret_op
def compose(self, other: OperatorBase) -> OperatorBase: other = self._check_zero_for_composition_and_expand(other) # If self is identity, just return other. if not any(self.primitive.x + self.primitive.z): # type: ignore return other * self.coeff # type: ignore # Both Paulis if isinstance(other, PauliOp): product, phase = Pauli.sgn_prod(self.primitive, other.primitive) return PrimitiveOp(product, coeff=self.coeff * other.coeff * phase) # pylint: disable=cyclic-import,import-outside-toplevel from .circuit_op import CircuitOp from ..state_fns.circuit_state_fn import CircuitStateFn if isinstance(other, (CircuitOp, CircuitStateFn)): return self.to_circuit_op().compose(other) return ComposedOp([self, other])
def _one_body_mapping(a_i, a_j, threshold=0.000001): """ Subroutine for one body mapping. Args: a_i (Pauli): pauli at index i a_j (Pauli): pauli at index j threshold: (float): threshold to remove a pauli Returns: Operator: Operator for those paulis """ pauli_list = [] for alpha in range(2): for beta in range(2): pauli_prod = Pauli.sgn_prod(a_i[alpha], a_j[beta]) coeff = 1.0/4 * pauli_prod[1] * np.power(-1j, alpha) * np.power(1j, beta) pauli_term = [coeff, pauli_prod[0]] if np.absolute(pauli_term[0]) > threshold: pauli_list.append(pauli_term) return Operator(paulis=pauli_list)
def _one_body_mapping(h1_ij_aij, threshold): """ Subroutine for one body mapping. Args: h1_ij_aij (tuple): value of h1 at index (i,j), pauli at index i, pauli at index j threshold: (float): threshold to remove a pauli Returns: WeightedPauliOperator: Operator for those paulis """ h1_ij, a_i, a_j = h1_ij_aij pauli_list = [] for alpha in range(2): for beta in range(2): pauli_prod = Pauli.sgn_prod(a_i[alpha], a_j[beta]) coeff = h1_ij / 4 * pauli_prod[1] * np.power(-1j, alpha) * np.power(1j, beta) pauli_term = [coeff, pauli_prod[0]] if np.absolute(pauli_term[0]) > threshold: pauli_list.append(pauli_term) return WeightedPauliOperator(paulis=pauli_list)
def _one_body_mapping(self, h1_ij_aij: Tuple[float, Pauli, Pauli]) -> PauliSumOp: """ Subroutine for one body mapping. Args: h1_ij_aij: value of h1 at index (i,j), pauli at index i, pauli at index j Returns: Operator for those paulis """ h1_ij, a_i, a_j = h1_ij_aij pauli_list = [] for alpha in range(2): for beta in range(2): pauli_prod = Pauli.sgn_prod(a_i[alpha], a_j[beta]) coeff = h1_ij / 4 * pauli_prod[1] * np.power( -1j, alpha) * np.power(1j, beta) pauli_term = [coeff, pauli_prod[0]] pauli_list.append(pauli_term) op = PauliSumOp.from_list([(pauli[1].to_label(), pauli[0]) for pauli in pauli_list]) return op