Calculadora de escritorio para sistemas de ecuaciones lineales. Resuelve por eliminación de Gauss y Gauss-Jordan, muestra cada transformación de fila y comprueba la solución por sustitución.
PrettyCalc está pensada para estudiantes de álgebra lineal que necesitan ver cómo se obtiene el resultado, no solo el vector final. Abre una matriz aumentada + y recorre el procedimiento paso a paso con el pivote y las filas involucradas resaltados. El motor matemático (prettycalc.core) usa fractions.Fraction y no depende de NumPy, SciPy ni SymPy: la aritmética es exacta y el mismo código se puede probar o reutilizar fuera de la interfaz.
Requisitos previos
- Python 3.10 o superior
- pip
- Entorno gráfico de escritorio (la interfaz usa PySide6 / Qt 6)
Clonar e instalar
git clone https://github.com/robertofabiot/PrettyCalc.git
cd PrettyCalc
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
pip install -r requirements.txtpip install -e . instala la aplicación y PySide6. requirements.txt añade pytest, pytest-qt y pytest-cov para las pruebas.
Levantar el proyecto
python run.pyTras la instalación editable también puedes usar:
prettycalcComprobar que las pruebas pasan
pytestEn un entorno sin pantalla (CI o SSH):
QT_QPA_PLATFORM=offscreen pytest- La ventana abre en
$2 \times 2$ con la columna$b$ visible: transcribe el sistema como matriz aumentada. - Pulsa
+para añadir filas o variables. Clic derecho en una celda para eliminar fila o columna (el mínimo es$1 \times 1$ ). - Se admiten enteros, fracciones (
3/4) y decimales. Una celda inválida se marca en el momento. - Resolver sistema ejecuta Gauss-Jordan, llena el carrusel de pasos y el panel de Resultados.
- En Procedimiento, avanza con Anterior / Siguiente. La fórmula del paso se ve en notación de libro (F₁, A⁻¹, ‖v‖²), no como código LaTeX. Fracciones es un interruptor entre vista racional y decimal.
-
Resultados clasifica el sistema (solución única, infinitas soluciones o inconsistente) y, si hay solución única, muestra la comprobación por sustitución. Si el sistema es indeterminado, el panel escribe la forma vectorial paramétrica
$x = p + t_1 v_1 + \dots$ con el vector particular y una base del núcleo. - En Álgebra Matricial, el modo A⁻¹ (Inversa) reduce
$[A \mid I_n]$ por Gauss-Jordan, muestra$A^{-1}$ y comprueba$A \cdot A^{-1} = I_n$ . Si$A$ no es cuadrada, el cálculo queda deshabilitado. Si$A$ es singular, el panel explica que no existe inversa. - En Determinantes, el orden n va de 1 a 8. Se puede calcular por triangulación, por Sarrus (solo 3×3), por cofactores de Laplace o pedir la matriz de cofactores, la adjunta y la inversa (A^{-1} = \frac{1}{\det A}\operatorname{adj}(A)).
- En Sistemas Lineales, el selector de método incluye la Regla de Cramer para sistemas n×n con determinante distinto de cero. El panel muestra det(A), cada matriz columna reemplazada y (x_i = \det(A_i(b)) / \det(A)).
- En Vectores, Norma y producto exterior calcula (|u|), (|v|), la distancia (d(u, v)) y la matriz (u v^T). La norma se muestra como cuadrado racional y como radical simplificado.
- En Álgebra Matricial, TMI revisa las caracterizaciones de invertibilidad (*c, *e, *h y (\det(A) \neq 0)). Identidades A⁻¹ contrasta ((A^{-1})^{-1} = A), ((AB)^{-1} = B^{-1}A^{-1}) y ((A^T)^{-1} = (A^{-1})^T).
- En Determinantes, Propiedades contrasta (\det(AB) = \det(A)\det(B)), (\det(A^T) = \det(A)), (\det(A^{-1}) = 1/\det(A)) y (\det(kA) = k^n \det(A)).
- En Factorización LU, Descomponer A = LU calcula (PA = LU). Si no hubo intercambio, (P = I) y se comprueba (L \cdot U = A). Si un pivote es cero, se muestra la matriz de permutación (P) y Resolver hace (Ly = Pb) y después (Ux = y). Si cambia (b), se reutilizan los mismos factores.
- En Sistemas Lineales, V · Aplicaciones abre el asistente de la sesión 8. No hace falta armar la matriz aumentada a mano:
-
Química escribe reactivos y productos (
C3H8 + O2yCO2 + H2O) y devuelve los enteros mínimos, con esos coeficientes resaltados. - Leontief lee la matriz de consumo (C) y resuelve ((I - C)p = 0). El ejemplo de carbón, electricidad y acero normaliza el precio del acero en 1.
- Dieta carga la tabla Cambridge y muestra las unidades exactas y los gramos.
- Tráfico carga la red de Baltimore y las cotas (x_i \ge 0).
-
Química escribe reactivos y productos (
Hay casos de prueba en la columna izquierda: solución única, infinitas soluciones, sin solución, Cramer y el asistente de aplicaciones.
Atajos y ayudas comunes a todos los módulos (F1 abre la hoja completa):
| Acción | Atajo |
|---|---|
| Calcular / Resolver / Verificar desde cualquier celda | Ctrl+Intro |
| Deshacer / rehacer un cambio de la cuadrícula (pegar, reiniciar, ejemplo) | Ctrl+Z / Ctrl+Y |
| Eliminar la fila / la columna de la celda activa | Ctrl+Supr / Ctrl+Mayús+Supr |
| Copiar / pegar la matriz completa (TSV, Excel, LaTeX) | Ctrl+C / Ctrl+V |
| Ir al módulo 1 … 6 | Ctrl+1 … Ctrl+6 |
| Apariencia (tema oscuro, alto contraste o claro; escala) | Ctrl+, |
| Navegar el procedimiento | ← / → dentro del carrusel |
Los errores se explican en línea («A, fila 2, columna 3: divide entre cero»), los cambios masivos muestran un aviso con Deshacer y la app se ve igual en Windows y en Linux porque trae sus propias fuentes (Inter, Fira Code y DejaVu Sans).
El núcleo no necesita Qt. Ejemplo con el caso de solución única
from prettycalc.core import (
Matrix,
gauss_jordan_elimination,
classify_system,
SolutionVerifier,
)
aumentada = Matrix([
[1, 1, 1, 4],
[2, -1, 1, 4],
[1, 2, -1, 3],
])
rref, tracer = gauss_jordan_elimination(aumentada, split_col=3)
analisis = classify_system(aumentada, split_col=3)
print(analisis.system_type.value)
# Consistente Determinado
print(analisis.unique_solution)
# [Fraction(2, 1), Fraction(1, 1), Fraction(1, 1)]
for paso in tracer:
print(paso.step_number, paso.heuristic_text)
comprobacion = SolutionVerifier.verify(
aumentada, analisis.unique_solution, split_col=3
)
assert all(eq.is_valid for eq in comprobacion)gaussian_elimination deja la forma escalonada (REF). gauss_jordan_elimination reduce hasta RREF. split_col es el índice donde empieza
La inversa y la resolución por inversa viven en prettycalc.core.matrix_inversion (también reexportadas desde matrix_ops y prettycalc.core):
from prettycalc.core import Matrix, Vector, classify_system, matrix_inverse, solve_via_inverse
A = Matrix([[2, 3], [-1, 1]])
inversa = matrix_inverse(A)
assert inversa.identity_check_passed
x, _ = solve_via_inverse(A, Vector([8, 1]))
analisis = classify_system(Matrix([
[3, 5, -4, 0],
[-3, -2, 4, 0],
[6, 1, -8, 0],
]))
print(analisis.parametric_vector_solution.to_plain_equation())
# x = [0, 0, 0] + x3*[4/3, 0, 1]El determinante, la adjunta y Cramer están en prettycalc.core.determinants, adjugate y cramer:
from prettycalc.core import (
Matrix,
Vector,
DeterminantMethod,
matrix_determinant,
calculate_adjugate_and_inverse,
solve_cramer,
)
A = Matrix([[1, 3, -3], [2, 0, 1], [-1, 4, -2]])
assert matrix_determinant(A, DeterminantMethod.SARRUS_3X3).value == -19
adjunta = calculate_adjugate_and_inverse(A)
assert adjunta.det_A == -19
solucion = solve_cramer(Matrix([[3, -2], [2, 5]]), Vector([7, 11]))
assert solucion.solution == [3, 1]La norma, la distancia y el producto exterior están en prettycalc.core.vector_ops. El Teorema de la Matriz Invertible está en prettycalc.core.theorems. Las propiedades del determinante están en prettycalc.core.determinants:
from prettycalc.core import (
Matrix,
Vector,
evaluate_invertible_matrix_theorem,
plu_decompose,
solve_via_plu,
vector_norm_exact,
vector_outer_product,
verify_determinant_properties,
)
assert vector_norm_exact(Vector([3, 4])) == (5, 1, 1)
assert vector_outer_product(Vector([1, -2, 3]), Vector([1, -2, 3])).shape == (3, 3)
invertible = Matrix([[1, 0, -2], [3, 1, -2], [-5, -1, 9]])
assert evaluate_invertible_matrix_theorem(invertible).is_invertible
props = verify_determinant_properties(
Matrix([[6, 1], [3, 2]]),
Matrix([[4, 3], [1, 2]]),
2,
)
assert props.det_AB == 45
permutada = Matrix([[0, 1, 2], [1, 0, 3], [4, -3, 8]])
factores = plu_decompose(permutada)
assert factores.is_valid and factores.permutation_count == 1
assert solve_via_plu(permutada, Vector([3, 4, 9])).x_solution == Vector([1, 1, 1])La factorización LU sin permutar filas y las dos sustituciones están en prettycalc.core.lu_decomposition:
from prettycalc.core import Matrix, Vector, lu_decompose, solve_many_via_lu
A = Matrix([[3, -7, -2], [-3, 5, 1], [6, -4, 0]])
factores = lu_decompose(A)
assert factores.is_valid
primero, segundo = solve_many_via_lu(A, [Vector([-7, 5, 2]), Vector([0, 0, 0])])
assert primero.factorization is segundo.factorization
assert primero.x_solution == Vector([3, 4, -6])Las aplicaciones de la sesión 8 están en prettycalc.core.applied_models:
from prettycalc.core import (
balance_chemical_equation,
solve_leontief_exchange,
solve_nutrition_mix,
analyze_network_flow,
coal_electric_steel_consumption,
cambridge_diet,
baltimore_traffic_network,
)
propano = balance_chemical_equation("C3H8 + O2 → CO2 + H2O")
assert propano.stoichiometric_coefficients == [1, 5, 3, 4]
precios = solve_leontief_exchange(coal_electric_steel_consumption())
assert precios.degrees_of_freedom == 1
composicion, requerimiento = cambridge_diet()
dieta = solve_nutrition_mix(composicion, requerimiento)
assert dieta.is_feasible
red = analyze_network_flow(baltimore_traffic_network())
assert red.parameter_range == (0, 500)PrettyCalc se distribuye bajo la licencia MIT. Puedes usar, copiar, modificar y redistribuir el código, con o sin fines comerciales, siempre que conserves el aviso de copyright y la licencia.