#set document(title: "5.2 Hunting the Eigenline", author: "XYZ Homework") #set page(width: 8.5in, height: auto, margin: 1in) #import "@preview/cetz:0.5.2" #set text(font: ("STIX Two Text", "Libertinus Serif", "New Computer Modern"), size: 10.5pt, lang: "en") #show math.equation: set text(font: ("STIX Two Math", "New Computer Modern Math")) #set par(justify: true, leading: 0.62em, spacing: 0.9em) #set enum(spacing: 1.1em) // room between list items so tall inline fractions don't collide #set list(spacing: 1.1em) #set table(stroke: 0.5pt + rgb("#c7ccd3")) #let BLUE = rgb("#183B6F") // brand navy — section bars + example/solution labels (white on navy 11.09:1) #let ORANGE = rgb("#A94509") // brand primary-700 — AA-safe deep orange for TEXT (5.93:1 on white; raw brand #F37021 is 2.94:1 and must never carry text) #let RED = rgb("#DC2626") // brand error-600 #let GREEN = rgb("#059669") // brand success-600 (decoration only; small green text uses green-text #007942) #show heading.where(level: 1): it => block(width: 100%, above: 0pt, below: 16pt, fill: gradient.linear(BLUE, rgb("#2C5AA0")), inset: (x: 14pt, y: 12pt), radius: 3pt, text(fill: white, weight: "bold", size: 19pt, it.body)) #show heading.where(level: 2): it => block(width: 100%, above: 18pt, below: 10pt, fill: BLUE, inset: (x: 10pt, y: 6pt), radius: 2pt, text(fill: white, weight: "bold", size: 12pt, it.body)) #show heading.where(level: 3): it => text(fill: ORANGE, weight: "bold", size: 12.5pt, it.body) #show heading.where(level: 4): it => text(fill: BLUE, weight: "bold", size: 10.5pt, it.body) #let examplebox(label, title, body) = block(width: 100%, breakable: true, fill: rgb("#EFF1F5"), stroke: 0.5pt + rgb("#CFDDF0"), radius: 4pt, inset: 10pt, above: 12pt, below: 12pt)[ #block(below: 6pt)[#box(fill: BLUE, inset: (x: 6pt, y: 2pt), radius: 2pt, text(fill: white, weight: "bold", size: 8.5pt, label)) #h(0.4em) #strong[#title]] #body] // rail = decorative left rule (raw brand token); labelcolor = AA-safe label text shade #let notebox(label, rail, labelcolor, tint, body) = block(width: 100%, breakable: true, fill: tint, stroke: (left: 3pt + rail), inset: (left: 10pt, rest: 8pt), radius: (right: 4pt), above: 11pt, below: 11pt)[ #text(fill: labelcolor, weight: "bold", size: 7.5pt, tracking: 0.5pt)[#upper(label)] #linebreak() #body] #let solutionbox(body) = block(above: 4pt, below: 8pt)[ #text(fill: BLUE, weight: "bold", size: 8.5pt)[Solution] #linebreak() #body] #let figph(msg) = block(width: 100%, height: 60pt, fill: rgb("#f6f7f9"), stroke: (paint: rgb("#c7ccd3"), dash: "dashed"), radius: 4pt, inset: 10pt)[ #align(center + horizon, text(fill: rgb("#889"), style: "italic", size: 9pt, msg))] // Standardize inlined figure sizes: measure the natural CeTZ canvas, then scale to a // consistent envelope (aspect-aware; see build_typst.py FIG_* constants). Unlike the // print preamble, dimensions are FLOORED: in an editor a user can trim a figure to a // degenerate 1-D shape (a bare line), and w/h or tw/w would then divide by zero. #let _STD_W = 3.5 #let _WIDE_W = 5.6 #let _MAX_H = 3.4 #let _ASPECT_WIDE = 2.2 #let _UPSCALE_MAX = 1.15 #let stdfig(body) = context { let m = measure(body) let w = calc.max(m.width / 1in, 0.01) let h = calc.max(m.height / 1in, 0.01) let tw = if w / h > _ASPECT_WIDE { _WIDE_W } else { _STD_W } let s = calc.min(tw / w, _MAX_H / h, _UPSCALE_MAX) align(center, box(scale(x: s * 100%, y: s * 100%, reflow: true, body))) } #show figure: set block(breakable: false) #set figure(gap: 8pt) #show figure.caption: set text(size: 8.5pt, fill: rgb("#555")) == 5.2#h(0.6em)Hunting the Eigenline #notebox("Note", rgb("#8a94a6"), rgb("#556666"), rgb("#f7f8fa"))[ #emph[Objectives] - Search for eigen-directions continuously, by rotating a test line through a field. - Derive an alignment condition in the angle of the test line and solve it exactly. - Explain why eigen-directions are isolated: a continuum of candidates, finitely many winners. ] The last section was a rigged hunt: four candidate lines were drawn in advance, and you merely had to judge them. Suppose nobody marks the candidates. The honest search is continuous — sweep a line through every direction and watch for the moment the field stops crossing it. The figure below stages that search in the horizontal plane #math.equation(block: false, alt: "z equals 0")[$z = 0$], where our matrix from the last section acts by #math.equation(block: false, alt: "open parenthesis x , y close parenthesis ↦ open parenthesis 2 x plus y , x plus 2 y close parenthesis")[$( x , y ) ↦ ( 2 x + y , #h(0.278em) x + 2 y )$]. A thick amber test line runs through the origin at angle #math.equation(block: false, alt: "a")[$a$], controlled by a slider that rotates it from #math.equation(block: false, alt: "0")[$0$] to #math.equation(block: false, alt: "3.14")[$3.14$] — nearly a half-turn, which is all a line needs, since a line at angle #math.equation(block: false, alt: "a plus π")[$a + π$] is the same line. Two dashed answer lines are hidden in the scene; leave them hidden until step 4. {"camera":{"fov":50,"position":\[5,3.5,5.5\],"projection":"perspective","target":\[0,0,0\]},"grid":{"axisColors":{"x":"\#ef4444","y":"\#22c55e","z":"\#3b82f6"},"divisions":10,"gridColor":"\#e5e7eb","showAxes":true,"showLabels":true,"size":10,"visible":true},"id":"90ce543e-73a1-467f-ad36-965f2608f369","metadata":{"alt\_text":"A cube of small arrows for the vector field F(x) = Ax, colored by length, with a thick amber test line through the origin in the horizontal plane. A slider named a rotates the test line from angle 0 to about pi; at exactly two angles the arrows sitting on the line point along it instead of across it. Two dashed answer lines are hidden until revealed.","created\_at":"2026-08-01T00:00:00.000Z","description":"Book scene: eigenline hunt by rotation. The field F(x, y, z) = (2x + y, x + 2y, -z) for A = \[\[2,1,0\],\[1,2,0\],\[0,0,-1\]\] plus a rotating test line (t cos a, t sin a, 0). The field aligns with the line only at a = pi/4 and a = 3pi/4; hidden dashed lines mark the answers.","tags":\["book","linear-algebra","eigenvectors","vector-field","slider"\],"updated\_at":"2026-08-01T00:00:00.000Z"},"objects":\[{"id":"0586205a-46c1-4dee-807b-83c26bd84233","kind":"parameter","label":{"text":"a (angle of the test line, radians)","visible":true},"max":3.14,"min":0,"name":"a","step":0.01,"value":0.3,"visible":true},{"density":5,"id":"7eb81484-ec87-4da4-a769-212693d015a4","kind":"vector-field","label":{"text":"F(x) = Ax","visible":true},"pExpr":"2\*x + y","qExpr":"x + 2\*y","rExpr":"-z","style":{"arrowScale":0.25,"colorByMagnitude":true,"colormap":"viridis","fixedColor":"\#ffffff"},"visible":true,"xDomain":\[-2,2\],"yDomain":\[-2,2\],"zDomain":\[-2,2\]},{"id":"e503f70d-13c4-4516-80ed-18a3c950b086","kind":"parametric-curve","label":{"text":"test line at angle a","visible":true},"samples":100,"style":{"color":"\#f59e0b","dash":\[\],"lineWidth":4},"tDomain":\[-2.5,2.5\],"visible":true,"xExpr":"t\*cos(a)","yExpr":"t\*sin(a)","zExpr":"0"},{"id":"51162a91-fb59-42d0-a15a-7ec9713b2138","kind":"parametric-curve","label":{"text":"answer: (t, t, 0)","visible":true},"samples":100,"style":{"color":"\#ef4444","dash":\[5,5\],"lineWidth":2},"tDomain":\[-2.5,2.5\],"visible":false,"xExpr":"t","yExpr":"t","zExpr":"0"},{"id":"751eb618-607a-408e-b144-35e8e00f6cd6","kind":"parametric-curve","label":{"text":"answer: (t, -t, 0)","visible":true},"samples":100,"style":{"color":"\#3b82f6","dash":\[5,5\],"lineWidth":2},"tDomain":\[-2.5,2.5\],"visible":false,"xExpr":"t","yExpr":"-t","zExpr":"0"}\],"title":"Hunting the eigenline","version":1} The field #math.equation(block: false, alt: "F open parenthesis 𝐱 close parenthesis equals A 𝐱")[$F ( 𝐱 ) = A 𝐱$] with an amber test line #math.equation(block: false, alt: "open parenthesis t cos a , t sin a , 0 close parenthesis")[$( t cos a , #h(0.278em) t sin a , #h(0.278em) 0 )$] through the origin, rotated by the slider #math.equation(block: false, alt: "a")[$a$]. At exactly two angles in the sweep, the arrows sitting on the line point along it instead of across it; dashed answer lines are hidden until you reveal them. === Explore the figure + Start at the default #math.equation(block: false, alt: "a equals 0.3")[$a = 0.3$] and zoom toward the arrows sitting on the amber line. They cross it at a visible angle — this direction is being turned, so it is no eigenline. Notice that #math.equation(block: false, alt: "a equals 0")[$a = 0$] would be the #math.equation(block: false, alt: "x")[$x$]-axis: the dashed decoy from last section, now just one more failed angle. + Sweep #math.equation(block: false, alt: "a")[$a$] slowly upward and watch only the arrows on the line. Somewhere near #math.equation(block: false, alt: "a approximately equals 0.79")[$a ≈ 0.79$] they swing into perfect alignment, pointing outward along the line and noticeably long. Park there. + Keep sweeping. Alignment breaks, then returns near #math.equation(block: false, alt: "a approximately equals 2.36")[$a ≈ 2.36$] — but differently: the arrows again lie along the line, yet they are shorter, matching the position vectors in length. Two alignments in the whole sweep, with two different strengths. + Reveal the two hidden dashed lines, #emph[answer: #math.equation(block: false, alt: "open parenthesis t , t , 0 close parenthesis")[$( t , t , 0 )$]] and #emph[answer: #math.equation(block: false, alt: "open parenthesis t , minus t , 0 close parenthesis")[$( t , − t , 0 )$]]. Drive the slider to each and confirm your parked angles were #math.equation(block: false, alt: "π / 4")[$π / 4$] and #math.equation(block: false, alt: "3 π / 4")[$3 π / 4$]. Every other angle in the continuum — infinitely many candidates — lost the audition. === The alignment condition The test direction at angle #math.equation(block: false, alt: "a")[$a$] is #math.equation(block: false, alt: "𝐝 equals open parenthesis cos a , sin a close parenthesis")[$𝐝 = ( cos a , #h(0.278em) sin a )$], and the field there is #math.equation(block: false, alt: "A 𝐝 equals open parenthesis 2 cos a plus sin a , cos a plus 2 sin a close parenthesis")[$A 𝐝 = ( 2 cos a + sin a , #h(0.278em) cos a + 2 sin a )$]. Alignment means #math.equation(block: false, alt: "A 𝐝")[$A 𝐝$] is parallel to #math.equation(block: false, alt: "𝐝")[$𝐝$], and two plane vectors are parallel exactly when their cross-term vanishes: #math.equation(block: true, alt: "cos a open parenthesis cos a plus 2 sin a close parenthesis minus sin a open parenthesis 2 cos a plus sin a close parenthesis equals cos squared a minus sin squared a equals cos 2 a")[$cos a ( cos a + 2 sin a ) − sin a ( 2 cos a + sin a ) = cos^(2) a − sin^(2) a = cos 2 a$] The mixed products cancel, and the entire misalignment of this field collapses to the function #math.equation(block: false, alt: "cos 2 a")[$cos 2 a$]. On the slider's range, #math.equation(block: false, alt: "cos 2 a equals 0")[$cos 2 a = 0$] exactly at #math.equation(block: false, alt: "a equals π / 4 approximately equals 0.79")[$a = π / 4 ≈ 0.79$] and #math.equation(block: false, alt: "a equals 3 π / 4 approximately equals 2.36")[$a = 3 π / 4 ≈ 2.36$] — the two places your sweep caught. Eigen-hunting is #emph[root-finding]: a smooth misalignment function of the candidate direction, whose isolated roots are the eigenlines. That is why the winners are so rare, and it is the same rarity you met when a span collapsed at a single slider value in Chapter 2: special directions are knife-edge events, not neighborhoods. #examplebox("Example 1")[The eigenvalues at the two winning angles][ Find the eigenvalue of #math.equation(block: false, alt: "A")[$A$] along each of the two alignment directions found above. At #math.equation(block: false, alt: "a equals π / 4")[$a = π / 4$] the direction has equal components, #math.equation(block: false, alt: "cos a equals sin a")[$cos a = sin a$], so #math.equation(block: false, alt: "A 𝐝 equals open parenthesis 2 cos a plus cos a , cos a plus 2 cos a close parenthesis equals 3 open parenthesis cos a , cos a close parenthesis equals 3 𝐝")[$A 𝐝 = ( 2 cos a + cos a , #h(0.278em) cos a + 2 cos a ) = 3 ( cos a , #h(0.278em) cos a ) = 3 𝐝$]: eigenvalue #math.equation(block: false, alt: "3")[$3$], matching the long outward arrows of step 2. At #math.equation(block: false, alt: "a equals 3 π / 4")[$a = 3 π / 4$] the components are opposite, #math.equation(block: false, alt: "cos a equals minus sin a")[$cos a = − sin a$], so #math.equation(block: false, alt: "A 𝐝 equals open parenthesis 2 cos a minus cos a , cos a minus 2 cos a close parenthesis equals open parenthesis cos a , minus cos a close parenthesis equals 𝐝")[$A 𝐝 = ( 2 cos a − cos a , #h(0.278em) cos a − 2 cos a ) = ( cos a , #h(0.278em) − cos a ) = 𝐝$]: eigenvalue #math.equation(block: false, alt: "1")[$1$], matching the modest arrows of step 3. These are the red and blue lines of the previous section, recovered by search instead of by gift — and they agree with the roots #math.equation(block: false, alt: "3")[$3$] and #math.equation(block: false, alt: "1")[$1$] of the in-plane block of the characteristic polynomial. ] #notebox("Note", rgb("#8a94a6"), rgb("#556666"), rgb("#f7f8fa"))[ A continuum of directions, two winners: the eigenline hunt is the geometric face of solving #math.equation(block: false, alt: "det open parenthesis A minus λ I close parenthesis equals 0")[$det ( A − λ I ) = 0$], trading a picture's sweep for a polynomial's roots. But the sweep raises a sharper question — what if the misalignment function #emph[never] crosses zero, and no direction in the plane survives unturned? Matrices like that exist, and they are next. ]