fig, axes = plt.subplots(1, 2, figsize=(11, 5))
# ---- Part (a) ----
ax = axes[0]
xs_a = np.array([5/2, 1])
v1a = np.array([1, 0]); v2a = np.array([-1, 1])
t_f = np.linspace(0, 3, 500); t_b = np.linspace(0, -1, 200)
ax.axhline(0, color='gray', lw=0.6); ax.axvline(0, color='gray', lw=0.6)
for c1v, c2v in [(2,0),(-2,0),(0,2),(0,-2),(1,1),(1,-1),(-1,1),(-1,-1),(3,1),(-3,1)]:
for tr in [t_f, t_b]:
xc = xs_a[0] + c1v*v1a[0]*np.exp(-2*tr) + c2v*v2a[0]*np.exp(-3*tr)
yc = xs_a[1] + c1v*v1a[1]*np.exp(-2*tr) + c2v*v2a[1]*np.exp(-3*tr)
mask = (np.abs(xc) < 6) & (np.abs(yc) < 5)
ax.plot(xc[mask], yc[mask], color='steelblue', lw=1.0, alpha=0.45)
ax.plot(*xs_a, 'ko', ms=7, zorder=5)
ax.annotate(r'$\mathbf{x}^*=(5/2,1)$', xy=xs_a, xytext=(3.2, 2.0), fontsize=8,
arrowprops=dict(arrowstyle='->', color='black', lw=0.8))
ax.set_xlim(-4, 6); ax.set_ylim(-4, 5)
ax.set_xlabel(r'$x$', fontsize=13); ax.set_ylabel(r'$y$', fontsize=13)
ax.set_title('Part (a): stable node at non-origin equilibrium', fontsize=10)
# ---- Part (b) ----
ax = axes[1]
xs_b = np.array([1, -1])
v1b = np.array([1, -3]); v2b = np.array([1, -1])
t_f2 = np.linspace(0, 1.2, 500)
t_b2 = np.linspace(0, -1.2, 500)
ax.axhline(0, color='gray', lw=0.6); ax.axvline(0, color='gray', lw=0.6)
# Stable manifold (c2=0)
for c1v in [1.5, -1.5]:
for tr in [t_f2, t_b2]:
xc = xs_b[0] + c1v*v1b[0]*np.exp(-tr)
yc = xs_b[1] + c1v*v1b[1]*np.exp(-tr)
mask = (np.abs(xc) < 7) & (np.abs(yc) < 7)
ax.plot(xc[mask], yc[mask], color='tomato', lw=2.0, alpha=0.85)
# Unstable manifold (c1=0)
for c2v in [0.8, -0.8]:
for tr in [t_f2, t_b2]:
xc = xs_b[0] + c2v*v2b[0]*np.exp(tr)
yc = xs_b[1] + c2v*v2b[1]*np.exp(tr)
mask = (np.abs(xc) < 7) & (np.abs(yc) < 7)
ax.plot(xc[mask], yc[mask], color='steelblue', lw=2.0, alpha=0.85)
# Generic orbits
for c1v, c2v in [(1,0.4),(1,-0.4),(-1,0.4),(-1,-0.4)]:
for tr in [t_f2, t_b2]:
xc = xs_b[0] + c1v*v1b[0]*np.exp(-tr) + c2v*v2b[0]*np.exp(tr)
yc = xs_b[1] + c1v*v1b[1]*np.exp(-tr) + c2v*v2b[1]*np.exp(tr)
mask = (np.abs(xc) < 7) & (np.abs(yc) < 7)
ax.plot(xc[mask], yc[mask], color='gray', lw=1.0, alpha=0.4)
ax.plot(*xs_b, 'ko', ms=7, zorder=5)
ax.annotate(r'$\mathbf{x}^*=(1,-1)$', xy=xs_b, xytext=(2.3, 0.5), fontsize=8,
arrowprops=dict(arrowstyle='->', color='black', lw=0.8))
ax.set_xlim(-5, 7); ax.set_ylim(-7, 5)
ax.set_xlabel(r'$x$', fontsize=13); ax.set_ylabel(r'$y$', fontsize=13)
ax.set_title('Part (b): saddle at non-origin equilibrium', fontsize=10)
from matplotlib.lines import Line2D
handles = [Line2D([0],[0], color='tomato', lw=2, label='Stable manifold ($c_2=0$)'),
Line2D([0],[0], color='steelblue', lw=2, label='Unstable manifold ($c_1=0$)'),
Line2D([0],[0], color='gray', lw=1, label='Other orbits')]
ax.legend(handles=handles, fontsize=8)
plt.tight_layout()
plt.show()