diff options
Diffstat (limited to 'posts')
-rw-r--r-- | posts/linear_system_solver.html | 102 | ||||
-rw-r--r-- | posts/linear_system_solver.html~ | 77 | ||||
-rw-r--r-- | posts/linear_system_solver.js | 172 | ||||
-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>×</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>×</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(); |