TheAlgorithms/Python · error · ValueError

RHS must be > 0

Error message

RHS must be > 0

What it means

Raised by the simplex solver when the RHS column (last column of the tableau) contains any negative value. Phase-II simplex pivoting requires a feasible starting basis (non-negative RHS); negative right-hand sides mean the origin is infeasible and a two-phase/big-M preprocessing step is needed.

Source

Thrown at linear_programming/simplex.py:51

    >>> Tableau(np.array([[-1,-1,0,0,1],[1,3,1,0,4],[3,1,0,1,4.]]), -2, 2)
    Traceback (most recent call last):
    ...
    ValueError: number of (artificial) variables must be a natural number
    """

    # Max iteration number to prevent cycling
    maxiter = 100

    def __init__(
        self, tableau: np.ndarray, n_vars: int, n_artificial_vars: int
    ) -> None:
        if tableau.dtype != "float64":
            raise TypeError("Tableau must have type float64")

        # Check if RHS is negative
        if not (tableau[:, -1] >= 0).all():
            raise ValueError("RHS must be > 0")

        if n_vars < 2 or n_artificial_vars < 0:
            raise ValueError(
                "number of (artificial) variables must be a natural number"
            )

        self.tableau = tableau
        self.n_rows, n_cols = tableau.shape

        # Number of decision variables x1, x2, x3...
        self.n_vars, self.n_artificial_vars = n_vars, n_artificial_vars

        # 2 if there are >= or == constraints (nonstandard), 1 otherwise (std)
        self.n_stages = (self.n_artificial_vars > 0) + 1

        # Number of slack variables added to make inequalities into equalities
        self.n_slack = n_cols - self.n_vars - self.n_artificial_vars - 1

View on GitHub (pinned to f5988cc097)

Solutions

  1. Rewrite '>=' constraints as '<=' by negating both sides so the RHS is non-negative, then add surplus/artificial variables as required.
  2. If the negative RHS is a modeling error, fix the constraint data.
  3. Verify feasibility before constructing: assert (tableau[:, -1] >= 0).all().

Example fix

# before: row for -2x - y >= -10 kept with RHS -10 after negation mismatch
tableau = np.array([[-2.0, -1.0, 10.0]])  # last col negative elsewhere

# after: ensure last column non-negative
row = np.array([[-2.0, -1.0, 10.0]])
tableau = np.vstack([tableau, row]) if (tableau[:, -1] >= 0).all() else fix_constraints(tableau)
Defensive patterns

Strategy: validation

Validate before calling

if not (tableau[:, -1] >= 0).all():
    raise ValueError("RHS has negative entries; convert '>=' rows and add artificials")
solver = Simplex(tableau, n_vars, n_artificial_vars)

Type guard

def has_nonneg_rhs(t: np.ndarray) -> bool:
    return bool((t[:, -1] >= 0).all())

Try / catch

try:
    Simplex(tableau, n_vars, n_artificial_vars)
except ValueError as e:
    if "RHS" in str(e):
        raise ValueError("LP is not in canonical form; negate '>=' rows first") from e
    raise

Prevention

When it happens

Trigger: Passing a tableau whose last column has a negative entry, typically from a constraint like 2x + y <= -10, or from multiplying a '>=' constraint row by -1 without then adding artificial variables and going through phase 1.

Common situations: Converting '>=' constraints to '<=' by negating the row, modeling negative demand/requirement values, or hand-building the tableau without running the standard two-phase preprocessing.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/e68cf2cdf70654a9. Report an issue: GitHub.