viewof a11 = Inputs. range ([0.5 , 3 ], {
step : 0.1 ,
value : 2 ,
label : tex `a_{11}` ,
width : 150
})
viewof a12 = Inputs. range ([- 1 , 1 ], {
step : 0.1 ,
value : 0.5 ,
label : tex `a_{12}` ,
width : 150
})
viewof a21 = Inputs. range ([- 1 , 1 ], {
step : 0.1 ,
value : 0.5 ,
label : tex `a_{21}` ,
width : 150
})
viewof a22 = Inputs. range ([0.5 , 3 ], {
step : 0.1 ,
value : 1.5 ,
label : tex `a_{22}` ,
width : 150
})
// Calculate eigenvalues and eigenvectors
eigenData = {
const trace = a11 + a22;
const det = a11 * a22 - a12 * a21;
const discriminant = trace * trace - 4 * det;
// Calculate eigenvalues
const lambda1 = (trace + Math . sqrt (Math . abs (discriminant))) / 2 ;
const lambda2 = (trace - Math . sqrt (Math . abs (discriminant))) / 2 ;
// Calculate eigenvectors
let v1, v2;
// For λ₁
if (Math . abs (a12) > 1e-10 ) {
v1 = [1 , - (a11 - lambda1) / a12];
} else if (Math . abs (a21) > 1e-10 ) {
v1 = [- (a22 - lambda1) / a21, 1 ];
} else {
v1 = [1 , 0 ];
}
// For λ₂
if (Math . abs (a12) > 1e-10 ) {
v2 = [1 , - (a11 - lambda2) / a12];
} else if (Math . abs (a21) > 1e-10 ) {
v2 = [- (a22 - lambda2) / a21, 1 ];
} else {
v2 = [0 , 1 ];
}
// Normalize to unit vectors
const norm1 = Math . sqrt (v1[0 ] * v1[0 ] + v1[1 ] * v1[1 ]);
const norm2 = Math . sqrt (v2[0 ] * v2[0 ] + v2[1 ] * v2[1 ]);
v1 = [v1[0 ] / norm1, v1[1 ] / norm1];
v2 = [v2[0 ] / norm2, v2[1 ] / norm2];
return { lambda1, lambda2, v1, v2 };
}
// Display matrix and eigenvalue information
html `<div style="text-align: center; font-size: 1.2em; margin: 1.5em 0;">
<p>
${ tex ` \m athbf{A} = \b egin{bmatrix} ${ a11. toFixed (1 )} & ${ a12. toFixed (1 )} \\ ${ a21. toFixed (1 )} & ${ a22. toFixed (1 )} \e nd{bmatrix}` }
</p>
<p style="margin-top: 1em;">
${ tex ` \l ambda_1 = ${ eigenData. lambda1 . toFixed (3 )} , \q uad \l ambda_2 = ${ eigenData. lambda2 . toFixed (3 )} ` }
</p>
<p style="margin-top: 0.5em; font-size: 0.9em;">
${ tex ` \m athbf{v}_1 = \b egin{bmatrix} ${ eigenData. v1 [0 ]. toFixed (3 )} \\ ${ eigenData. v1 [1 ]. toFixed (3 )} \e nd{bmatrix}, \q uad \m athbf{v}_2 = \b egin{bmatrix} ${ eigenData. v2 [0 ]. toFixed (3 )} \\ ${ eigenData. v2 [1 ]. toFixed (3 )} \e nd{bmatrix}` }
</p>
</div>`
Plot. plot ({
style : "overflow: visible; display: block; margin: 0 auto;" ,
width : 600 ,
height : 600 ,
grid : true ,
x : {label : "x₁" , domain : [- 4 , 4 ]},
y : {label : "x₂" , domain : [- 4 , 4 ]},
marks : [
// Grid axes
Plot. ruleY ([0 ], {stroke : "#ddd" , strokeWidth : 1 }),
Plot. ruleX ([0 ], {stroke : "#ddd" , strokeWidth : 1 }),
// First eigenvector (red solid)
Plot. arrow ([{x1 : 0 , y1 : 0 , x2 : eigenData. v1 [0 ] * 2 , y2 : eigenData. v1 [1 ] * 2 }], {
x1 : "x1" , y1 : "y1" , x2 : "x2" , y2 : "y2" ,
stroke : "#d73027" , strokeWidth : 4 , fill : "#d73027"
}),
// First eigenvector scaled by eigenvalue (red dotted)
Plot. arrow ([{x1 : 0 , y1 : 0 , x2 : eigenData. v1 [0 ] * 2 * eigenData. lambda1 , y2 : eigenData. v1 [1 ] * 2 * eigenData. lambda1 }], {
x1 : "x1" , y1 : "y1" , x2 : "x2" , y2 : "y2" ,
stroke : "#d73027" , strokeWidth : 4 , fill : "#d73027" ,
strokeDasharray : "8,4"
}),
// Second eigenvector (green solid)
Plot. arrow ([{x1 : 0 , y1 : 0 , x2 : eigenData. v2 [0 ] * 2 , y2 : eigenData. v2 [1 ] * 2 }], {
x1 : "x1" , y1 : "y1" , x2 : "x2" , y2 : "y2" ,
stroke : "#1a9850" , strokeWidth : 4 , fill : "#1a9850"
}),
// Second eigenvector scaled by eigenvalue (green dotted)
Plot. arrow ([{x1 : 0 , y1 : 0 , x2 : eigenData. v2 [0 ] * 2 * eigenData. lambda2 , y2 : eigenData. v2 [1 ] * 2 * eigenData. lambda2 }], {
x1 : "x1" , y1 : "y1" , x2 : "x2" , y2 : "y2" ,
stroke : "#1a9850" , strokeWidth : 4 , fill : "#1a9850" ,
strokeDasharray : "8,4"
}),
// Origin point
Plot. dot ([{x : 0 , y : 0 }], {
x : "x" , y : "y" ,
r : 5 ,
fill : "black" ,
stroke : "white" , strokeWidth : 2
}),
// Eigenvector labels
Plot. text ([
{x : eigenData. v1 [0 ] * 2.3 , y : eigenData. v1 [1 ] * 2.3 , text : `v₁` },
{x : eigenData. v2 [0 ] * 2.3 , y : eigenData. v2 [1 ] * 2.3 , text : `v₂` }
], {
x : "x" , y : "y" , text : "text" ,
fontSize : 14 , fontWeight : "bold" ,
fill : d => d. text . includes ("₁" ) ? "#d73027" : "#1a9850"
}),
// Eigenvalue scaling labels
Plot. text ([
{x : eigenData. v1 [0 ] * 2.3 * eigenData. lambda1 + 0.2 , y : eigenData. v1 [1 ] * 2.3 * eigenData. lambda1 + 0.2 , text : `λ₁v₁` },
{x : eigenData. v2 [0 ] * 2.3 * eigenData. lambda2 + 0.2 , y : eigenData. v2 [1 ] * 2.3 * eigenData. lambda2 + 0.2 , text : `λ₂v₂` }
], {
x : "x" , y : "y" , text : "text" ,
fontSize : 12 , fontWeight : "bold" ,
fill : d => d. text . includes ("₁" ) ? "#d73027" : "#1a9850"
})
]
})