codexfarkas-infeasible-halfplanes.py
farkas-infeasible-halfplanes.py
"""Show each half-plane and their incompatibility; save PNG to cwd (Python 3.14)."""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def main():
c = np.array([[-1, 0], [0, -1], [1, 1]])
d = np.array([-1, -1, 1])
multipliers = np.ones(3, dtype=int)
assert np.array_equal(c.T @ multipliers, [0, 0])
assert d @ multipliers == -1
pair_points = np.array([[1, 1], [1, 0], [0, 1]])
for point, rows in zip(pair_points, [(0, 1), (0, 2), (1, 2)]):
satisfied = c @ point <= d
assert np.all(satisfied[list(rows)]) and not np.all(satisfied)
assert np.array_equal(np.column_stack((c, -c, np.eye(3, dtype=int))).T
@ multipliers, [0, 0, 0, 0, 1, 1, 1])
upper_bound_multipliers = np.array([0, 0, 1])
bound_rhs = np.array([0, 0, 1])
assert np.array_equal(c.T @ upper_bound_multipliers, [1, 1])
assert bound_rhs @ upper_bound_multipliers == 1
assert np.all(c @ np.array([1, 0]) <= bound_rhs)
plt.rcParams.update({"font.size": 11, "axes.titlesize": 13})
fig, axes = plt.subplots(2, 2, figsize=(9, 8), dpi=120, facecolor="white")
lo, hi = -1, 3
grid = np.linspace(lo, hi, 401)
xx, yy = np.meshgrid(grid, grid)
masks = [xx >= 1, yy >= 1, xx + yy <= 1]
colors = ["#397ca5", "#458667", "#be633c"]
titles = [r"First requirement: $x\geq1$", r"Second requirement: $y\geq1$",
r"Third requirement: $x+y\leq1$", "All three: no common point"]
def shade(ax, mask, color):
ax.contourf(xx, yy, mask.astype(int), levels=[0.5, 1.5],
colors=[color], alpha=0.18, zorder=0)
for i, (ax, title) in enumerate(zip(axes.flat, titles)):
if i < 3:
shade(ax, masks[i], colors[i])
else:
first_two = masks[0] & masks[1]
assert not np.any(first_two & masks[2])
shade(ax, first_two, "#397ca5")
shade(ax, masks[2], colors[2])
if i in (0, 3):
ax.axvline(1, color=colors[0], lw=2)
if i in (1, 3):
ax.axhline(1, color=colors[1], lw=2)
if i in (2, 3):
ax.plot(grid, 1 - grid, color=colors[2], lw=2)
ax.axvline(0, color="#c2c7cc", lw=0.8, zorder=0)
ax.axhline(0, color="#c2c7cc", lw=0.8, zorder=0)
ax.set(xlim=(lo, hi), ylim=(lo, hi), aspect="equal", title=title,
xlabel="x", ylabel="y", xticks=[-1, 0, 1, 2, 3], yticks=[-1, 0, 1, 2, 3])
ax.spines[["top", "right"]].set_visible(False)
final = axes[1, 1]
final.text(1.22, 2.48, r"$x\geq1,\ y\geq1$" + "\n" + r"so $x+y\geq2$",
color=colors[0], fontsize=11)
final.text(-0.72, -0.72, r"$x+y\leq1$", color=colors[2], fontsize=11)
final.scatter(pair_points[:, 0], pair_points[:, 1], s=28, color="#343c42", zorder=4)
final.annotate("(1,1)", xy=(1, 1), xytext=(1.16, 1.28), fontsize=9)
final.annotate("(1,0)", xy=(1, 0), xytext=(1.24, 0.06), fontsize=9)
final.annotate("(0,1)", xy=(0, 1), xytext=(-0.77, 1.2), fontsize=9)
fig.suptitle("Each shaded half-plane is possible on its own", y=0.98, fontsize=16)
fig.text(0.5, 0.065, r"Multipliers $(1,1,1)$: $(-x)+(-y)+(x+y)\leq-1-1+1$",
ha="center", fontsize=13)
fig.text(0.5, 0.025, r"The variables cancel: $0\leq-1$ is impossible",
ha="center", fontsize=13, color="#9b3827")
fig.subplots_adjust(left=0.07, right=0.98, bottom=0.16, top=0.91, hspace=0.38, wspace=0.2)
fig.savefig(Path.cwd() / Path(__file__).with_suffix(".png").name,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()