summaryrefslogtreecommitdiff
path: root/posts
diff options
context:
space:
mode:
Diffstat (limited to 'posts')
-rw-r--r--posts/linear_system_solver.html102
-rw-r--r--posts/linear_system_solver.html~77
-rw-r--r--posts/linear_system_solver.js172
-rw-r--r--posts/linear_system_solver.js~106
4 files changed, 457 insertions, 0 deletions
diff --git a/posts/linear_system_solver.html b/posts/linear_system_solver.html
new file mode 100644
index 0000000..a8b17e5
--- /dev/null
+++ b/posts/linear_system_solver.html
@@ -0,0 +1,102 @@
+
+<h2>Linear Systems Solver</h2>
+<h3>2021-08-01 by Matthew Kosarek</h3>
+<p>
+ I wanted to write a little algorithm to visually solve linear systems of equations for fun. I am only going to deal with 3x3 matrices for now, but I'll make it so that I can easily extend it to more matrices in the future if I think that would be cool.
+
+ <br/><br/>
+
+ <div id='equation_container'>
+ <div id='matrix_lhs'></div>
+ <label>&times;</label>
+ <div id='unknown_variables'></div>
+ <label>=</label>
+ <div id='matrix_rhs'></div>
+ </div>
+
+ <div id='solution_container'>
+ </div>
+
+ <div id='actions_container'>
+ <button class='action_button'id='reset_button'>
+ Reset
+ </button>
+ <button class='action_button' id='solve_button'>
+ Solve
+ </button>
+ </div>
+
+ <script src='/posts/linear_system_solver.js'></script>
+
+ <style>
+ #equation_container {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ width: 100%;
+ justify-content: center;
+ }
+
+ #equation_container input {
+ width: 128px;
+ }
+
+ #equation_container > label {
+ padding: 1rem;
+ }
+
+ #matrix_lhs {
+ display: grid;
+ grid-gap: 1rem;
+ grid-template-columns: repeat(3, 1fr);
+ }
+
+ #unknown_variables {
+ display: grid;
+ grid-gap: 1rem;
+ }
+
+ #unknown_variables > input {
+ text-align: center;
+ }
+
+ #matrix_rhs {
+ display: grid;
+ grid-gap: 1rem;
+ }
+
+ #actions_container {
+ padding: 1rem;
+ text-align: center;
+ }
+
+ #solve_button {
+ background-color: lightgreen;
+ }
+
+ .augmented_matrix_container {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+ padding: 1rem;
+ }
+
+ .augmented_matrix_container input {
+ width: 128px;
+ }
+
+ .augmented_matrix_container > div:first-child {
+ display: grid;
+ grid-gap: 1rem;
+ grid-template-columns: repeat(3, 1fr);
+ padding-right: 0.5rem;
+ border-right: 1px dashed white;
+ }
+
+ .augmented_matrix_container > div:last-child {
+ display: grid;
+ grid-gap: 1rem;
+ padding-left: 0.5rem;
+ }
+ </style>
+</p>
diff --git a/posts/linear_system_solver.html~ b/posts/linear_system_solver.html~
new file mode 100644
index 0000000..a280a8b
--- /dev/null
+++ b/posts/linear_system_solver.html~
@@ -0,0 +1,77 @@
+
+<h2>Linear Systems Solver</h2>
+<h3>2021-08-01 by Matthew Kosarek</h3>
+<p>
+ I wanted to write a little algorithm to visually solve linear systems of equations for fun. I am only going to deal with 3x3 matrices for now, but I'll make it so that I can easily extend it to more matrices in the future if I think that would be cool.
+
+ <br/><br/>
+
+ <div id='equation_container'>
+ <div id='matrix_lhs'></div>
+ <label>&times;</label>
+ <div id='unknown_variables'></div>
+ <label>=</label>
+ <div id='matrix_rhs'></div>
+ </div>
+
+ <div id='solution_container'>
+ </div>
+
+ <div id='actions_container'>
+ <button class='action_button'id='reset_button'>
+ Reset
+ </button>
+ <button class='action_button' id='solve_button'>
+ Solve
+ </button>
+ </div>
+
+ <script src='/posts/linear_system_solver.js'></script>
+
+ <style>
+ #equation_container {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ width: 100%;
+ justify-content: center;
+ }
+
+ #equation_container input {
+ width: 128px;
+ }
+
+ #equation_container > label {
+ padding: 1rem;
+ }
+
+ #matrix_lhs {
+ display: grid;
+ grid-gap: 1rem;
+ grid-template-columns: repeat(3, 1fr);
+ }
+
+ #unknown_variables {
+ display: grid;
+ grid-gap: 1rem;
+ }
+
+ #unknown_variables > input {
+ text-align: center;
+ }
+
+ #matrix_rhs {
+ display: grid;
+ grid-gap: 1rem;
+ }
+
+ #actions_container {
+ padding: 1rem;
+ text-align: center;
+ }
+
+ #solve_button {
+ background-color: lightgreen;
+ }
+ </style>
+</p>
diff --git a/posts/linear_system_solver.js b/posts/linear_system_solver.js
new file mode 100644
index 0000000..9eb901f
--- /dev/null
+++ b/posts/linear_system_solver.js
@@ -0,0 +1,172 @@
+var $ = window.$,
+ rows = 3,
+ columns = 3,
+ currentLhs = [], // rows x columns matrix
+ currentRhs = []; // rows x 1 matrix
+ solutionContainer = $('#solution_container');
+
+function main() {
+ $('#reset_button').on('click', onResetClicked);
+ $('#solve_button').on('click', onSolveClicked);
+ resetView();
+}
+
+function resetView() {
+ renderLHS();
+ renderUnknowns();
+ renderRHS();
+
+ currentLhs = [];
+ currentRhs = [];
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ currentLhs.push(0);
+ }
+ }
+
+ for (var otherR = 0; otherR < rows; otherR++) {
+ currentRhs.push(0);
+ }
+
+ solutionContainer.empty();
+}
+
+// Renders for the input container.
+function renderLHS() {
+ var lhs = $('#matrix_lhs').empty(),
+ addCell = function(index) {
+ $('<input>').type('number').val(0).on('change', function(event) {
+ currentLhs[index] = Number(event.target.value);
+ }).appendTo(lhs);
+ };
+
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ addCell((r * rows) + c);
+ }
+ }
+}
+
+function renderUnknowns() {
+ var unknownsContainer = $('#unknown_variables').empty();
+
+ for (var r = 0; r < columns; r++) {
+ var cell = $('<input>').disabled(true).val(String.fromCharCode('x'.charCodeAt(0) + r).toUpperCase());
+ unknownsContainer.append(cell);
+ }
+}
+
+function renderRHS() {
+ var rhs = $('#matrix_rhs').empty(),
+ addCell = function(index) {
+ $('<input>').type('number').val(0).on('change', function(event) {
+ currentRhs[index] = Number(event.target.value);
+ }).appendTo(rhs);
+ };
+
+ for (var r = 0; r < rows; r++) {
+ addCell(r);
+ }
+}
+
+// Renders for the augmented matrix container
+function renderAugmentedMatrix(lhs, rhs) {
+ var container = $('<div>').addClass('augmented_matrix_container'),
+ lhsContainer = $('<div>').appendTo(container),
+ rhsContainer = $('<div>').appendTo(container),
+ addLhsCell = function(index) {
+ $('<input>').type('number').val(lhs[index]).disabled(true).appendTo(lhsContainer);
+ },
+ addRhsCell = function(index) {
+ $('<input>').type('number').val(rhs[index]).disabled(true).appendTo(rhsContainer);
+ };
+
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ addLhsCell(r * rows + c);
+ }
+ }
+
+ for (var otherR = 0; otherR < rows; otherR++) {
+ addRhsCell(otherR);
+ }
+
+ return container;
+}
+
+// Solver helper functions
+function findLargestValue(c, rowStart) {
+ var largestValue = 0,
+ largestRow = -1;
+ for (var r = rowStart; r < rows; r++) {
+ var currValue = Math.abs(currentLhs[r * rows + c]);
+ if (currValue > largestValue) {
+ largestValue = currValue;
+ largestRow = r;
+ }
+ }
+ return {
+ row: largestRow,
+ value: largestValue
+ };
+}
+
+function swapRows(r1, r2) {
+ if (r1 === r2) {
+ return;
+ }
+
+ for (var c = 0; c < columns; c++) {
+ var temp = currentLhs[r1 * row + c];
+ currentLhs[r1 * rows + c] = currentLhs[r2 * row + c];
+ currentLhs[r2 * rows + c] = temp;
+ }
+
+ var rhsTmp = currentRhs[r1];
+ currentRhs[r1] = currentRhs[r2];
+ currentRhs[r2] = rhsTmp;
+}
+
+function multiplyRow(r, scale) {
+ for (var c = 0; c < columns; c++) {
+ currentLhs[r * rows + c] *= scale;
+ }
+
+ currentRhs[r] *= scale;
+}
+
+function addRow(r, a) {
+ for (var c = 0; c < columns; c++) {
+ currentLhs[r * rows + c] += a;
+ }
+
+ currentRhs[r] += a;
+}
+
+// Callbacks for actions
+function onResetClicked() {
+ resetView();
+}
+
+function onSolveClicked() {
+ var rowStart = 0;
+ for (var c = 0; c < columns; c++) {
+ var largestForColumn = findLargestValue(c, rowStart);
+ if (largestForColumn.row >= 0) {
+ swapRows(rowStart, largestForColumn.row);
+ multiplyRow(rowStart, 1.0 / largestForColumn.value);
+
+ for (var r = 0; r < rows; r++) {
+ if (r === rowStart) continue;
+
+ }
+ }
+
+ rowStart++;
+ }
+
+ solutionContainer.append(renderAugmentedMatrix(currentLhs, currentRhs));
+ solutionContainer.append(renderAugmentedMatrix(currentLhs, currentRhs));
+}
+
+main();
diff --git a/posts/linear_system_solver.js~ b/posts/linear_system_solver.js~
new file mode 100644
index 0000000..33fc026
--- /dev/null
+++ b/posts/linear_system_solver.js~
@@ -0,0 +1,106 @@
+var $ = window.$,
+ rows = 3,
+ columns = 3,
+ currentLhs = [], // rows x columns matrix
+ currentRhs = []; // rows x 1 matrix
+ solutionContainer = $('#solution_container');
+
+function main() {
+ $('#reset_button').on('click', onResetClicked);
+ $('#solve_button').on('click', onSolveClicked);
+ resetView();
+}
+
+function resetView() {
+ renderLHS();
+ renderUnknowns();
+ renderRHS();
+
+ currentLhs = [];
+ currentRhs = [];
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ currentLhs.push(0);
+ }
+ }
+
+ for (var otherR = 0; otherR < rows; otherR++) {
+ currentRhs.push(0);
+ }
+
+ solutionContainer.empty();
+}
+
+// Renders for the input container.
+function renderLHS() {
+ var lhs = $('#matrix_lhs').empty(),
+ addCell = function(index) {
+ $('<input>').type('number').val(0).on('change', function(event) {
+ currentLhs[index] = Number(event.target.value);
+ }).appendTo(lhs);
+ };
+
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ addCell((r * rows) + c);
+ }
+ }
+}
+
+function renderUnknowns() {
+ var unknownsContainer = $('#unknown_variables').empty();
+
+ for (var r = 0; r < columns; r++) {
+ var cell = $('<input>').disabled(true).val(String.fromCharCode('x'.charCodeAt(0) + r).toUpperCase());
+ unknownsContainer.append(cell);
+ }
+}
+
+function renderRHS() {
+ var rhs = $('#matrix_rhs').empty(),
+ addCell = function(index) {
+ $('<input>').type('number').val(0).on('change', function(event) {
+ currentRhs[index] = Number(event.target.value);
+ }).appendTo(rhs);
+ };
+
+ for (var r = 0; r < rows; r++) {
+ addCell(r);
+ }
+}
+
+// Renders for the solution container
+function renderAugmentedMatrix(lhs, rhs) {
+ var container = $('<div>').addClass('augmented_matrix_container'),
+ lhsContainer = $('<div>').appendTo(container),
+ rhsContainer = $('<div>').appendTo(container),
+ addLhsCell = function(index) {
+ $('<input>').type('number').val(lhs[index]).disabled(true).appendTo(lhsContainer);
+ },
+ addRhsCell = function(index) {
+ $('<input>').type('number').val(rhs[index]).disabled(true).appendTo(rhsContainer);
+ };
+
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ addLhsCell(r * rows + c);
+ }
+ }
+
+ for (var otherR = 0; otherR < rows; otherR++) {
+ addRhsCell(otherR);
+ }
+
+ return container;
+}
+
+// Callbacks for actions
+function onResetClicked() {
+ resetView();
+}
+
+function onSolveClicked() {
+ solutionContainer.append(renderAugmentedMatrix(currentLhs, currentRhs));
+}
+
+main();