Linear Algebra Solver (Ax = b)
A =
x =
b =
Results will appear here.
Error: Please enter valid numbers in all fields.
'; return null; } return { matrixA, vectorB }; } // Solve the system Ax = b using Gaussian elimination function solveLinearSystem(matrixA, vectorB) { const n = matrixA.length; const augmentedMatrix = []; // Create augmented matrix [A|b] for (let i = 0; i < n; i++) { augmentedMatrix[i] = [...matrixA[i], vectorB[i]]; } // --- Gaussian Elimination (Forward Elimination) --- for (let i = 0; i < n; i++) { // Find pivot (largest element in current column below current row) let maxRow = i; for (let k = i + 1; k < n; k++) { if (Math.abs(augmentedMatrix[k][i]) > Math.abs(augmentedMatrix[maxRow][i])) { maxRow = k; } } // Swap rows if necessary [augmentedMatrix[i], augmentedMatrix[maxRow]] = [augmentedMatrix[maxRow], augmentedMatrix[i]]; // Check for singularity or near-singularity (pivot close to zero) const pivot = augmentedMatrix[i][i]; if (Math.abs(pivot) < 1e-10) { // Threshold for zero // Check for inconsistency (e.g., 0 0 | c where c != 0) if (i < n) { for(let k = i; k < n; k++) { if (Math.abs(augmentedMatrix[k][n]) > 1e-10 && Math.abs(augmentedMatrix[k][i]) < 1e-10) { // It *might* be inconsistent, but could also be infinite solutions. // Let's check further down. A full zero row [0 0 | 0] means infinite. } } } // For simplicity, we'll report potential issues. A more robust solver // would fully analyze rank to distinguish no vs. infinite solutions. continue; // Skip this column if pivot is zero } // Normalize the pivot row for (let j = i; j <= n; j++) { augmentedMatrix[i][j] /= pivot; } // Eliminate other rows for (let k = 0; k < n; k++) { if (k !== i) { const factor = augmentedMatrix[k][i]; for (let j = i; j <= n; j++) { augmentedMatrix[k][j] -= factor * augmentedMatrix[i][j]; } } } } // End forward elimination // --- Check for No Solution or Infinite Solutions --- for (let i = 0; i < n; i++) { let allZerosInRow = true; for (let j = 0; j < n; j++) { if (Math.abs(augmentedMatrix[i][j]) > 1e-10) { allZerosInRow = false; break; } } if (allZerosInRow && Math.abs(augmentedMatrix[i][n]) > 1e-10) { return { status: 'no_solution', message: "The system has no solution (inconsistent)." }; } if (allZerosInRow && Math.abs(augmentedMatrix[i][n]) < 1e-10) { // This indicates dependent equations (potentially infinite solutions) // A more advanced solver would parameterize the solution. // For now, report it as not uniquely solvable. return { status: 'infinite_solutions', message: "The system has infinitely many solutions (dependent equations)." }; } } // Check if diagonal elements became zero after elimination steps (another indicator of issues) for(let i=0; i'); resultsDiv.innerHTML += `
${solutionVector}
`; downloadBtn.style.display = 'inline-block'; // Show download button } else { resultsDiv.innerHTML = `${resultData.message}
`; downloadBtn.style.display = 'none'; // Hide download button } } // Generate and download PDF function downloadPDF() { if (!solutionData) return; const doc = new jsPDF(); const { matrixA, vectorB, result } = solutionData; const n = matrixA.length; // --- Get Colors from CSS Variables --- const styles = getComputedStyle(document.querySelector('.las-solver-container')); const primaryColor = styles.getPropertyValue('--las-primary-color').trim(); const textColor = styles.getPropertyValue('--las-text-color').trim(); const resultsBg = styles.getPropertyValue('--las-results-bg').trim(); const errorColor = styles.getPropertyValue('--las-error-color').trim(); // --- PDF Content --- const lineHeight = 7; const margin = 15; let currentY = 20; // Title doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text("Linear Algebra Solver Results (Ax = b)", doc.internal.pageSize.getWidth() / 2, currentY, { align: 'center' }); currentY += lineHeight * 2; // Input System doc.setFontSize(14); doc.setTextColor(textColor); doc.text("Input System:", margin, currentY); currentY += lineHeight * 1.5; doc.setFontSize(12); // Matrix A let matrixString = ""; for (let i = 0; i < n; i++) { matrixString += (i === 0 ? "A = [" : " [") + matrixA[i].map(val => val.toString().padStart(6)).join(' ') + "]\n"; } doc.setFont("courier", "normal"); // Use monospace for alignment doc.text(matrixString, margin + 5, currentY); currentY += n * lineHeight + 5; // Adjust spacing based on matrix size // Vector b let vectorString = ""; for (let i = 0; i < n; i++) { vectorString += (i === 0 ? "b = [" : " [") + vectorB[i].toString() + "]\n"; } doc.text(vectorString, margin + 5, currentY); currentY += n * lineHeight + lineHeight; // Adjust spacing doc.setFont("helvetica", "normal"); // Switch back to normal font // Result Section doc.setFillColor(resultsBg); // Use results background color doc.rect(margin - 5, currentY - 5, doc.internal.pageSize.getWidth() - 2 * (margin - 5), (result.status === 'unique_solution' ? n + 2 : 3) * lineHeight + 5, 'F'); // Draw background rectangle doc.setFontSize(14); doc.setTextColor(textColor); doc.text("Result:", margin, currentY); currentY += lineHeight * 1.5; doc.setFontSize(12); if (result.status === 'unique_solution') { doc.setTextColor(primaryColor); // Solution color doc.text("Unique Solution Found (x):", margin + 5, currentY); currentY += lineHeight; let solutionString = ""; result.solution.forEach((val, index) => { solutionString += ` x${index + 1} = ${val}\n`; }); doc.setFont("courier", "normal"); doc.text(solutionString, margin + 5, currentY); doc.setFont("helvetica", "normal"); } else { doc.setTextColor(errorColor); // Error color doc.text(result.message, margin + 5, currentY); } // --- Save PDF --- doc.save('linear_system_solution.pdf'); } // --- Event Listeners --- sizeSelector.addEventListener('change', (e) => { generateInputs(e.target.value); }); solveBtn.addEventListener('click', () => { const inputs = getInputs(); if (inputs) { const { matrixA, vectorB } = inputs; const result = solveLinearSystem(matrixA, vectorB); displayResults(result); // Store data for PDF, regardless of unique solution or not solutionData = { matrixA, vectorB, result }; // Only show download button if there's a unique solution downloadBtn.style.display = (result.status === 'unique_solution') ? 'inline-block' : 'none'; } else { // Input validation failed, hide button and clear stored data downloadBtn.style.display = 'none'; solutionData = null; } }); downloadBtn.addEventListener('click', downloadPDF); // --- Initial Setup --- generateInputs(sizeSelector.value); // Initialize with the default size (2x2) })(); // IIFE to avoid polluting global scope