Skip to content

QuadraticProgramToQubo

Bases: QuadraticProgramConverter

Convert a given optimization problem to a new problem that is a QUBO.

Examples:

>>> from qiskit_optimization.problems import QuadraticProgram
>>> from qiskit_optimization.converters import QuadraticProgramToQubo
>>> problem = QuadraticProgram()
>>> # define a problem
>>> conv = QuadraticProgramToQubo()
>>> problem2 = conv.convert(problem)
Source code in q3as/quadratic/converters/quadratic_program_to_qubo.py
class QuadraticProgramToQubo(QuadraticProgramConverter):
    """Convert a given optimization problem to a new problem that is a QUBO.

    Examples:
        >>> from qiskit_optimization.problems import QuadraticProgram
        >>> from qiskit_optimization.converters import QuadraticProgramToQubo
        >>> problem = QuadraticProgram()
        >>> # define a problem
        >>> conv = QuadraticProgramToQubo()
        >>> problem2 = conv.convert(problem)
    """

    def __init__(self, penalty: Optional[float] = None) -> None:
        """
        Args:
            penalty: Penalty factor to scale equality constraints that are added to objective.
                If None is passed, a penalty factor will be automatically calculated on every
                conversion.
        """
        self._penalize_lin_eq_constraints = LinearEqualityToPenalty(penalty=penalty)
        self._penalize_lin_ineq_constraints = LinearInequalityToPenalty(penalty=penalty)
        self._converters = [
            self._penalize_lin_ineq_constraints,
            InequalityToEquality(mode="integer"),
            IntegerToBinary(),
            self._penalize_lin_eq_constraints,
            MaximizeToMinimize(),
        ]

    def convert(self, problem: QuadraticProgram) -> QuadraticProgram:
        """Convert a problem with linear constraints into new one with a QUBO form.

        Args:
            problem: The problem with linear constraints to be solved.

        Returns:
            The problem converted in QUBO format as minimization problem.

        Raises:
            QiskitOptimizationError: In case of an incompatible problem.
        """

        # analyze compatibility of problem
        msg = self.get_compatibility_msg(problem)
        if len(msg) > 0:
            raise QiskitOptimizationError(f"Incompatible problem: {msg}")

        for conv in self._converters:
            problem = conv.convert(problem)
        return problem

    def interpret(self, x: Union[np.ndarray, List[float]]) -> np.ndarray:
        """Convert a result of a converted problem into that of the original problem.

        Args:
            x: The result of the converted problem.

        Returns:
            The result of the original problem.
        """
        for conv in self._converters[::-1]:
            x = conv.interpret(x)
        return cast(np.ndarray, x)

    @staticmethod
    def get_compatibility_msg(problem: QuadraticProgram) -> str:
        """Checks whether a given problem can be solved with this optimizer.

        Checks whether the given problem is compatible, i.e., whether the problem can be converted
        to a QUBO, and otherwise, returns a message explaining the incompatibility.

        Args:
            problem: The optimization problem to check compatibility.

        Returns:
            A message describing the incompatibility.
        """

        # initialize message
        msg = ""
        # check whether there are incompatible variable types
        if problem.get_num_continuous_vars() > 0:
            msg += "Continuous variables are not supported! "

        # check whether there are incompatible constraint types
        if len(problem.quadratic_constraints) > 0:
            msg += "Quadratic constraints are not supported. "
        # check whether there are float coefficients in constraints
        compatible_with_integer_slack = True
        for l_constraint in problem.linear_constraints:
            linear = l_constraint.linear.to_dict()
            if any(
                isinstance(coef, float) and not coef.is_integer()
                for coef in linear.values()
            ):
                compatible_with_integer_slack = False
        for q_constraint in problem.quadratic_constraints:
            linear = q_constraint.linear.to_dict()
            quadratic = q_constraint.quadratic.to_dict()
            if any(
                isinstance(coef, float) and not coef.is_integer()
                for coef in quadratic.values()
            ) or any(
                isinstance(coef, float) and not coef.is_integer()
                for coef in linear.values()
            ):
                compatible_with_integer_slack = False
        if not compatible_with_integer_slack:
            msg += (
                "Can not convert inequality constraints to equality constraint because \
                    float coefficients are in constraints. "
            )

        # if an error occurred, return error message, otherwise, return the empty string
        return msg

    def is_compatible(self, problem: QuadraticProgram) -> bool:
        """Checks whether a given problem can be solved with the optimizer implementing this method.

        Args:
            problem: The optimization problem to check compatibility.

        Returns:
            Returns True if the problem is compatible, False otherwise.
        """
        return len(self.get_compatibility_msg(problem)) == 0

    @property
    def penalty(self) -> Optional[float]:
        """Returns the penalty factor used in conversion.

        Returns:
            The penalty factor used in conversion.
        """
        return self._penalize_lin_eq_constraints.penalty

    @penalty.setter
    def penalty(self, penalty: Optional[float]) -> None:
        """Set a new penalty factor.

        Args:
            penalty: The new penalty factor.
                     If None is passed, a penalty factor will be automatically calculated on every
                     conversion.
        """
        self._penalize_lin_ineq_constraints.penalty = penalty
        self._penalize_lin_eq_constraints.penalty = penalty

penalty: Optional[float] property writable

Returns the penalty factor used in conversion.

Returns:

Type Description
Optional[float]

The penalty factor used in conversion.

__init__(penalty=None)

Parameters:

Name Type Description Default
penalty Optional[float]

Penalty factor to scale equality constraints that are added to objective. If None is passed, a penalty factor will be automatically calculated on every conversion.

None
Source code in q3as/quadratic/converters/quadratic_program_to_qubo.py
def __init__(self, penalty: Optional[float] = None) -> None:
    """
    Args:
        penalty: Penalty factor to scale equality constraints that are added to objective.
            If None is passed, a penalty factor will be automatically calculated on every
            conversion.
    """
    self._penalize_lin_eq_constraints = LinearEqualityToPenalty(penalty=penalty)
    self._penalize_lin_ineq_constraints = LinearInequalityToPenalty(penalty=penalty)
    self._converters = [
        self._penalize_lin_ineq_constraints,
        InequalityToEquality(mode="integer"),
        IntegerToBinary(),
        self._penalize_lin_eq_constraints,
        MaximizeToMinimize(),
    ]

convert(problem)

Convert a problem with linear constraints into new one with a QUBO form.

Parameters:

Name Type Description Default
problem QuadraticProgram

The problem with linear constraints to be solved.

required

Returns:

Type Description
QuadraticProgram

The problem converted in QUBO format as minimization problem.

Raises:

Type Description
QiskitOptimizationError

In case of an incompatible problem.

Source code in q3as/quadratic/converters/quadratic_program_to_qubo.py
def convert(self, problem: QuadraticProgram) -> QuadraticProgram:
    """Convert a problem with linear constraints into new one with a QUBO form.

    Args:
        problem: The problem with linear constraints to be solved.

    Returns:
        The problem converted in QUBO format as minimization problem.

    Raises:
        QiskitOptimizationError: In case of an incompatible problem.
    """

    # analyze compatibility of problem
    msg = self.get_compatibility_msg(problem)
    if len(msg) > 0:
        raise QiskitOptimizationError(f"Incompatible problem: {msg}")

    for conv in self._converters:
        problem = conv.convert(problem)
    return problem

get_compatibility_msg(problem) staticmethod

Checks whether a given problem can be solved with this optimizer.

Checks whether the given problem is compatible, i.e., whether the problem can be converted to a QUBO, and otherwise, returns a message explaining the incompatibility.

Parameters:

Name Type Description Default
problem QuadraticProgram

The optimization problem to check compatibility.

required

Returns:

Type Description
str

A message describing the incompatibility.

Source code in q3as/quadratic/converters/quadratic_program_to_qubo.py
@staticmethod
def get_compatibility_msg(problem: QuadraticProgram) -> str:
    """Checks whether a given problem can be solved with this optimizer.

    Checks whether the given problem is compatible, i.e., whether the problem can be converted
    to a QUBO, and otherwise, returns a message explaining the incompatibility.

    Args:
        problem: The optimization problem to check compatibility.

    Returns:
        A message describing the incompatibility.
    """

    # initialize message
    msg = ""
    # check whether there are incompatible variable types
    if problem.get_num_continuous_vars() > 0:
        msg += "Continuous variables are not supported! "

    # check whether there are incompatible constraint types
    if len(problem.quadratic_constraints) > 0:
        msg += "Quadratic constraints are not supported. "
    # check whether there are float coefficients in constraints
    compatible_with_integer_slack = True
    for l_constraint in problem.linear_constraints:
        linear = l_constraint.linear.to_dict()
        if any(
            isinstance(coef, float) and not coef.is_integer()
            for coef in linear.values()
        ):
            compatible_with_integer_slack = False
    for q_constraint in problem.quadratic_constraints:
        linear = q_constraint.linear.to_dict()
        quadratic = q_constraint.quadratic.to_dict()
        if any(
            isinstance(coef, float) and not coef.is_integer()
            for coef in quadratic.values()
        ) or any(
            isinstance(coef, float) and not coef.is_integer()
            for coef in linear.values()
        ):
            compatible_with_integer_slack = False
    if not compatible_with_integer_slack:
        msg += (
            "Can not convert inequality constraints to equality constraint because \
                float coefficients are in constraints. "
        )

    # if an error occurred, return error message, otherwise, return the empty string
    return msg

interpret(x)

Convert a result of a converted problem into that of the original problem.

Parameters:

Name Type Description Default
x Union[ndarray, List[float]]

The result of the converted problem.

required

Returns:

Type Description
ndarray

The result of the original problem.

Source code in q3as/quadratic/converters/quadratic_program_to_qubo.py
def interpret(self, x: Union[np.ndarray, List[float]]) -> np.ndarray:
    """Convert a result of a converted problem into that of the original problem.

    Args:
        x: The result of the converted problem.

    Returns:
        The result of the original problem.
    """
    for conv in self._converters[::-1]:
        x = conv.interpret(x)
    return cast(np.ndarray, x)

is_compatible(problem)

Checks whether a given problem can be solved with the optimizer implementing this method.

Parameters:

Name Type Description Default
problem QuadraticProgram

The optimization problem to check compatibility.

required

Returns:

Type Description
bool

Returns True if the problem is compatible, False otherwise.

Source code in q3as/quadratic/converters/quadratic_program_to_qubo.py
def is_compatible(self, problem: QuadraticProgram) -> bool:
    """Checks whether a given problem can be solved with the optimizer implementing this method.

    Args:
        problem: The optimization problem to check compatibility.

    Returns:
        Returns True if the problem is compatible, False otherwise.
    """
    return len(self.get_compatibility_msg(problem)) == 0