Inequalities and Constraint Regions
Equations name exact spots; inequalities name whole territories. Budgets, error tolerances and feasible regions are all inequalities deciding what counts as allowed.
Why Does This Exist?
Almost nothing in practice wants an exact value. A model must use at most 14 GB. Error must stay below 5%. Weights must keep norm under the budget. Each requirement is an inequality, and the set of points satisfying all of them is the feasible region where the answer is allowed to live.
Inequalities solve like equations with one extra rule and one new habit: shade the allowed side and test a point in it. Optimization lives inside such regions, which is why convex sets and functions and the KKT conditions both assume this page.
The one idea you need first. The symbols: under, over, under-or-equal, over-or-equal. A filled boundary circle includes the endpoint; an open one excludes it. Everything below is deciding which side of a boundary counts.
Think of It Like This
A speed limit with a checkpoint
A 60 km/h limit does not ask for exactly 60. It allows everything up to and including 60, a whole territory of legal speeds with one boundary. The checkpoint tests membership: 52 passes, 60 passes, 61 fails.
Solving an inequality draws the limit and shades the legal territory. Testing a point is driving through the checkpoint. And the boundary question, open or filled circle, is whether exactly-60 gets waved through.
Where it stops: speed limits have one boundary and one side, while real feasible regions have many intersecting constraints. The analogy shows one inequality; pages on convexity intersect them.
How It Actually Works
Solve exactly like an equation, with one extra rule: multiplying or dividing by a negative flips the direction. gives , so . But divides by and flips: . Adding or subtracting never flips; only negative scaling reverses the order, because it mirrors the number line.
Graph the answer by shading. For : an open circle at 4, shading to the left. For : a filled circle, shading left. Compound inequalities chain: shades between, open at 1, filled at 5.
Worked example: solve, test the inside and the edge
Solve . Subtract 3: . Divide by 2 (positive, no flip): .
Test inside with : , and holds. Test the boundary with : , and fails, confirming the circle stays open. Test outside with : fails. Inside passes, edge and outside fail: the shading is correct.
Code
def satisfies(x: float) -> bool: # True exactly on the allowed side of 2x + 3 < 11. return 2 * x + 3 < 11
print([satisfies(v) for v in [3.0, 4.0, 5.0]]) # -> [True, False, False]print(all(satisfies(v) for v in [0.0, 1.0, 2.0, 3.0])) # -> TrueConstraints in code are predicates, not values: a function returning True or False per point. The second line sweeps the allowed side asserting every interior sample passes, the executable version of shading.
Watch Out For
Forgetting the flip on negative division
solved as is wrong; dividing by flips it to . The check exposes it instantly: satisfies the "solution" () yet fails the original ( is false). The symptom is a feasible region mirrored to the wrong side, admitting exactly what was banned.
Test a point from the claimed region in the original inequality every time a negative scaling appears. The flip is the most failed algebra step in constraint code.
Squaring both sides of an inequality
squared is not in both directions: satisfies ... no, it fails, while fails the original too, but passes the original and passes as well, hiding that squaring merged and . The squared form admits imposters and the direction can reverse on negatives.
Never square an inequality with mixed-sign sides. Isolate and test points instead; keep squaring for equations with checks.
The Quick Version
- Solve like an equation, except negative multiply or divide flips the direction.
- Shade the allowed side; open circle excludes the boundary, filled includes it.
- gives : inside passes, boundary fails.
- Test inside, boundary and outside points in the original inequality, all three.
- Constraints in code are True/False predicates swept over samples, not solved values.