Create a quadratic program from a qubit operator and a shift value.
Variables are mapped to qubits in the same order, i.e.,
i-th variable is mapped to i-th qubit.
See https://github.com/Qiskit/qiskit-terra/issues/1148 for details.
Parameters:
    
      
        
          | Name | Type | Description | Default | 
      
      
          
            | qubit_op | BaseOperator | 
                The qubit operator of the problem. | required | 
          
            | offset | float | 
                The constant term in the Ising Hamiltonian. | 0.0 | 
          
            | linear | bool | 
                If linear is True, :math:x^2is treated as a linear term
since :math:x^2 = xfor :math:x \in \{0,1\}.
Otherwise, :math:x^2is treat as a quadratic term.
The default value is False. | False | 
      
    
    Returns:
    
      
        
          | Type | Description | 
      
      
          
            | QuadraticProgram | 
                The quadratic program corresponding to the qubit operator. | 
      
    
Raises:
    
      
        
          | Type | Description | 
      
      
          
            | QiskitOptimizationError | 
                if there are Pauli Xs or Ys in any Pauli term | 
          
            | QiskitOptimizationError | 
                if there are more than 2 Pauli Zs in any Pauli term | 
          
            | QiskitOptimizationError | 
                if any Pauli term has an imaginary coefficient | 
      
    
            
              Source code in q3as/quadratic/translators/ising.py
              |  | def from_ising(
    qubit_op: BaseOperator,
    offset: float = 0.0,
    linear: bool = False,
) -> QuadraticProgram:
    r"""Create a quadratic program from a qubit operator and a shift value.
    Variables are mapped to qubits in the same order, i.e.,
    i-th variable is mapped to i-th qubit.
    See https://github.com/Qiskit/qiskit-terra/issues/1148 for details.
    Args:
        qubit_op: The qubit operator of the problem.
        offset: The constant term in the Ising Hamiltonian.
        linear: If linear is True, :math:`x^2` is treated as a linear term
            since :math:`x^2 = x` for :math:`x \in \{0,1\}`.
            Otherwise, :math:`x^2` is treat as a quadratic term.
            The default value is False.
    Returns:
        The quadratic program corresponding to the qubit operator.
    Raises:
        QiskitOptimizationError: if there are Pauli Xs or Ys in any Pauli term
        QiskitOptimizationError: if there are more than 2 Pauli Zs in any Pauli term
        QiskitOptimizationError: if any Pauli term has an imaginary coefficient
    """
    # quantum_info
    if isinstance(qubit_op, BaseOperator):
        if not isinstance(qubit_op, SparsePauliOp):
            qubit_op = SparsePauliOp.from_operator(Operator(qubit_op))
    quad_prog = QuadraticProgram()
    quad_prog.binary_var_list(qubit_op.num_qubits)
    # prepare a matrix of coefficients of Pauli terms
    # `pauli_coeffs_diag` is the diagonal part
    # `pauli_coeffs_triu` is the upper triangular part
    pauli_coeffs_diag = [0.0] * qubit_op.num_qubits
    pauli_coeffs_triu = {}
    for pauli_op in qubit_op:
        pauli = pauli_op.paulis[0]
        coeff = pauli_op.coeffs[0]
        if not math.isclose(coeff.imag, 0.0, abs_tol=1e-10):
            raise QiskitOptimizationError(f"Imaginary coefficient exists: {pauli_op}")
        if np.any(pauli.x):
            raise QiskitOptimizationError(
                f"Pauli X or Y exists in the Pauli term: {pauli}"
            )
        # indices of Pauli Zs in the Pauli term
        z_index = np.where(pauli.z)[0]
        num_z = len(z_index)
        if num_z == 0:
            offset += coeff.real
        elif num_z == 1:
            pauli_coeffs_diag[z_index[0]] = coeff.real
        elif num_z == 2:
            pauli_coeffs_triu[z_index[0], z_index[1]] = coeff.real
        else:
            raise QiskitOptimizationError(
                f"There are more than 2 Pauli Zs in the Pauli term: {pauli}"
            )
    linear_terms = {}
    quadratic_terms = {}
    # For quadratic pauli terms of operator
    # x_i * x_j = (1 - Z_i - Z_j + Z_i * Z_j)/4
    for (i, j), weight in pauli_coeffs_triu.items():
        # Add a quadratic term to the objective function of `QuadraticProgram`
        # The coefficient of the quadratic term in `QuadraticProgram` is
        # 4 * weight of the pauli
        quadratic_terms[i, j] = 4 * weight
        pauli_coeffs_diag[i] += weight
        pauli_coeffs_diag[j] += weight
        offset -= weight
    # After processing quadratic pauli terms, only linear paulis are left
    # x_i = (1 - Z_i)/2
    for i, weight in enumerate(pauli_coeffs_diag):
        # Add a linear term to the objective function of `QuadraticProgram`
        # The coefficient of the linear term in `QuadraticProgram` is
        # 2 * weight of the pauli
        if linear:
            linear_terms[i] = -2 * weight
        else:
            quadratic_terms[i, i] = -2 * weight
        offset += weight
    quad_prog.minimize(constant=offset, linear=linear_terms, quadratic=quadratic_terms)
    return quad_prog
 |