# This code is part of a Qiskit project.
#
# (C) Copyright IBM 2019, 2025.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""Abstract Constraint."""
from __future__ import annotations
from abc import abstractmethod
from enum import Enum
from typing import Any
from numpy import ndarray
from .quadratic_program_element import QuadraticProgramElement
from ..exceptions import QiskitOptimizationError
class ConstraintSense(Enum):
"""Constraint Sense Type."""
# pylint: disable=invalid-name
LE = 0
GE = 1
EQ = 2
@staticmethod
def convert(sense: str | ConstraintSense) -> ConstraintSense:
"""Convert a string into a corresponding sense of constraints
Args:
sense: A string or sense of constraints
Returns:
The sense of constraints
Raises:
QiskitOptimizationError: if the input string is invalid.
"""
if isinstance(sense, ConstraintSense):
return sense
sense = sense.upper()
if sense not in [
"E",
"L",
"G",
"EQ",
"LE",
"GE",
"=",
"==",
"<=",
"<",
">=",
">",
]:
raise QiskitOptimizationError(f"Invalid sense: {sense}")
if sense in ["E", "EQ", "=", "=="]:
return ConstraintSense.EQ
elif sense in ["L", "LE", "<=", "<"]:
return ConstraintSense.LE
else:
return ConstraintSense.GE
@property
def label(self) -> str:
"""Label of the constraint sense
Returns:
The label of the constraint sense ('<=', '>=', or '==')
"""
if self is ConstraintSense.LE:
return "<="
elif self is ConstraintSense.GE:
return ">="
else:
return "=="
[docs]
class Constraint(QuadraticProgramElement):
"""Abstract Constraint Class."""
Sense = ConstraintSense
def __init__(
self, quadratic_program: Any, name: str, sense: ConstraintSense, rhs: float
) -> None:
"""Initializes the constraint.
Args:
quadratic_program: The parent QuadraticProgram.
name: The name of the constraint.
sense: The sense of the constraint.
rhs: The right-hand-side of the constraint.
"""
super().__init__(quadratic_program)
self._name = name
self._sense = sense
self._rhs = rhs
@property
def name(self) -> str:
"""Returns the name of the constraint.
Returns:
The name of the constraint.
"""
return self._name
@property
def sense(self) -> ConstraintSense:
"""Returns the sense of the constraint.
Returns:
The sense of the constraint.
"""
return self._sense
@sense.setter
def sense(self, sense: ConstraintSense) -> None:
"""Sets the sense of the constraint.
Args:
sense: The sense of the constraint.
"""
self._sense = sense
@property
def rhs(self) -> float:
"""Returns the right-hand-side of the constraint.
Returns:
The right-hand-side of the constraint.
"""
return self._rhs
@rhs.setter
def rhs(self, rhs: float) -> None:
"""Sets the right-hand-side of the constraint.
Args:
rhs: The right-hand-side of the constraint.
"""
self._rhs = rhs
[docs]
@abstractmethod
def evaluate(self, x: ndarray | list | dict[int | str, float]) -> float:
"""Evaluate left-hand-side of constraint for given values of variables.
Args:
x: The values to be used for the variables.
Returns:
The left-hand-side of the constraint.
"""
raise NotImplementedError()