diff options
author | syn <isaqtm@gmail.com> | 2020-02-16 11:56:52 +0300 |
---|---|---|
committer | syn <isaqtm@gmail.com> | 2020-02-16 11:56:52 +0300 |
commit | fd78d0fd00e6b98ae8b9894db8be028575e205ac (patch) | |
tree | ee9dd35e871d222aa60a1958e9b6f28eaa6ecc54 | |
download | alg3-fd78d0fd00e6b98ae8b9894db8be028575e205ac.tar.gz |
Init commit
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | four.py | 55 | ||||
-rw-r--r-- | gen_all.py | 2 | ||||
-rw-r--r-- | hw3.tex | 134 | ||||
-rw-r--r-- | intro.tex | 97 | ||||
-rw-r--r-- | libsolve.py | 330 | ||||
-rw-r--r-- | one.py | 114 | ||||
-rw-r--r-- | render.py | 45 | ||||
-rw-r--r-- | two.py | 107 |
9 files changed, 886 insertions, 0 deletions
@@ -0,0 +1,2 @@ +Я стал еще более ленивым, поэтому многие матрицы в пдфке написаны не совсем в пдфке. +Их надо сгенерить скриптом (gen_all.py) @@ -0,0 +1,55 @@ +from libsolve import * +from fractions import Fraction +import numpy as np + +FOUR_SIMEQ = '\\overset{{\\texttt{{two.py}}}}\\simeq' + +# generate figure as plain file, so we can \input it +def gen_figure(figname, text): + with open(f'figures/fig_four_{figname}.tex', 'w') as fd: + fd.write('$$' + text + '$$') + +A = Matrix([ + [-1, 1, 1, -1], + [-7, 4, 4, -3], + [4, -1, -2, 1], + [4, -1, -2, 1] +]) + +lbdE = Matrix([ + [Poly([0, 1]), 0, 0, 0], + [0, Poly([0, 1]), 0, 0], + [0, 0, Poly([0, 1]), 0], + [0, 0, 0, Poly([0, 1])] +]) + +# uncomment to see characteristic poly +#print((A - lbdE).det()) + + + +A = A - Matrix([ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] +]) + +A = A@A + +before = A.to_tex() + +A.triangulate() + +A.make_D(0, -1) +A.make_U(1, 2) +A.make_D(1, Fraction(1, 4)) + +gen_figure('fsr_A_T', +f''' + {before} + {FOUR_SIMEQ} + {A.to_tex()} +''') + +print(A)
\ No newline at end of file diff --git a/gen_all.py b/gen_all.py new file mode 100644 index 0000000..07a1c0f --- /dev/null +++ b/gen_all.py @@ -0,0 +1,2 @@ +import one +import two @@ -0,0 +1,134 @@ +\documentclass[10pt,a5paper]{article} +\usepackage[svgnames, rgb]{xcolor} + +\input{intro} + +\lhead{\color{gray} Шарафатдинов Камиль 192} +\rhead{\color{gray} \texttt{hw3}} +\title{ИДЗ-3 по линейной алгебре} +\author{Шарафатдинов Камиль БПМИ-192} +\date{билд: \today} + + +% -- Here bet dragons -- +\begin{document}\thispagestyle{empty} + +\maketitle +\clearpage +\setcounter{page}{1} + +\dmquestion{1} + + Проверим, что векторы из условия являются решением системы + \input{figures/fig_one_proof_v0.tex} + \input{figures/fig_one_proof_v0.tex} + + + Найдем ФСР системы: + \input{figures/fig_one_init_to_triang} + + ФСР: + \begin{flalign*} + \lambda_2 = 1 \qquad& (4, 1, 0, 0, 0, 0)\\ + \lambda_4 = 1 \qquad& (-1, 0, 1, 1, 0, 0)\\ + \lambda_5 = 1 \qquad& (-1, 0, -2, 0, 2, 0)\\ + \lambda_6 = 1 \qquad& (1, 0, -2, 0, 0, 1) + \end{flalign*} + + Выразим векторы $v_1$ и $v_2$ (из условия) через ФСР (мы так можем, потому что ФСР - базис этого подпространства) + + Для этого нужно решить две системы: + \input{figures/fig_one_convert_v1} + \[ + u_1 = (1, -3, 3, -1) + \] + \input{figures/fig_one_convert_v2} + \[ + u_2 = (2, 3, 1, -2) + \] + + Теперь надо дополнить эту систему до базиса $\mathbb{R}^4$: + \input{figures/fig_one_solve_last} + + Дополнить до базиса можно векторами $(0, 0, 1, 0)$ и $(0, 0, 0, 1)$ + + То есть последние два вектора из ФСР - дополнение до базиса подпространства. + + \begin{flalign*} + (-1, 0, -2, 0, 2, 0)\\ + (1, 0, -2, 0, 0, 1) + \end{flalign*} + +\dmquestion{2} + + $\Image \varphi$ - линейная оболочка столбцов. + Найдем матрицу, задающую $\Image \varphi$ по алгоритму от Димы: + + Найдем ФСР $A^Tx = 0$: + \input{figures/fig_two_fsr_A_T} + + ФСР: + \[ + (2, -1, 1, 0), \quad \br{ \frac{7}{5}, -\frac{4}{5}, 0, 1 } = (7, -4, 0, 5) + \] + + Значит, $\Image \varphi = \left\{ x \ | \ Bx = 0\right\}$, где + \[ + B = \begin{bmatrix} + 2 & -1 & 1 & 0\\ + 7 & -4 & 0 & 5 + \end{bmatrix} + \] + + Тогда $\Image \varphi \cap \ker \varphi = \left\{x | Ax = 0, Bx = 0\right\}$ + + \input{figures/fig_two_AB_sol} + + ФСР такой системы - $(-3, -4, 2, 1)$ + + Значит, $\Image \varphi \cap \ker \varphi = \langle(-3, -4, 2, 1)\rangle$ + + $\Image \varphi$ - линейная оболочка столбцов, + а $\ker \varphi$ - линейная оболочка ФСР $Ax = 0$. + Тогда $\Image \varphi + \ker \varphi$ - линейная оболочка всех этих векторов. + Надо только найти в них базис: + + \input{figures/fig_two_ker_A} + + $ + \ker \varphi = \langle (-\frac{3}{2}, -3, 1, 0), (0, 2, 0, 1) \rangle + = + \ker \varphi = \langle (-3, -6, 2, 0), (0, 2, 0, 1) \rangle + $ + + Теперь надо найти базис из столбцов $A$ и базиса в $\ker \varphi$: + + \input{figures/fig_two_imker} + + Ненулевые строки - базис (возьмем векторы из левой матрицы). + + Поэтому + $ + \Image \varphi + \ker \varphi = + \langle + (-2, 14, 18, 14), + (-3, -9, -3, -3), + (-3, -6, 2, 0) + \rangle + $ + +%\dmquestion{4} +% Найдем хар. многочлен $\varphi$: +% \[ +% \mathrm{det} (\varphi - \lambda E) +% \overset{\texttt{four.py}}= +% \lambda^4 - \lambda^3 + \lambda^2 = +% \lambda^2(\lambda - 1)^2 +% \] +% +% $ +% V^1 = \ker ((\varphi - E)^2) +% $, так как у каждого собственного значения степень 2 +% \input{figures/fig_four_fsr_A_T} + +\end{document} diff --git a/intro.tex b/intro.tex new file mode 100644 index 0000000..f4f9d67 --- /dev/null +++ b/intro.tex @@ -0,0 +1,97 @@ +\usepackage[sfdefault,condensed,scaled=0.9]{roboto} +\usepackage{inconsolata} +\setmonofont[Scale=0.9]{Inconsolata} + +\setlength\headheight{13.6pt} + +\usepackage{ + amsmath, amssymb, mathtools, relsize, + graphicx, xcolor, + fancyhdr, hyperref, enumerate, framed +} +\usepackage[shortlabels]{enumitem} + +\flushbottom + +\renewcommand{\baselinestretch}{1.1} + +\usepackage{geometry}\geometry{letterpaper, % Set page margins + left=0.7in, right=0.7in, + top=0.8in, bottom=0.9in, + headsep=.1in +} + +\setlength\FrameSep{0.75em} +\setlength\OuterFrameSep{\partopsep} + +\newenvironment{cframed}[1][gray] +{ + \def\FrameCommand{ + \fboxsep=\FrameSep\fcolorbox{#1}{white} + } + \MakeFramed{ + \advance\hsize-\width \FrameRestore + } +} +{\endMakeFramed} + +\makeatletter +\newenvironment{sqcases}{% + \matrix@check\sqcases\env@sqcases +}{% + \endarray\right.% +} +\def\env@sqcases{% + \let\@ifnextchar\new@ifnextchar + \left\lbrack + \def\arraystretch{1.2}% + \array{@{}l@{\quad}l@{}}% +} +\makeatother + +\DeclareRobustCommand{\divby}{% + \mathrel{\vbox{\baselineskip.65ex\lineskiplimit0pt\hbox{.}\hbox{.}\hbox{.}}}% +} + +\newcommand{\question}[2]{ + \bigskip\bigskip + \begin{cframed} + \noindent \textbf{#1} + #2 + \end{cframed} +} + +\newcommand{\dmquestion}[1]{ + \begin{center} \textbf{#1} \end{center} +} + +\newcommand{\br}[1]{\left( #1 \right)} +\newcommand{\brac}[2]{ \br{ \frac{#1}{#2} } } +\newcommand{\dbrac}[2]{ \br{ \dfrac{#1}{#2} } } +\newcommand*{\qed}{\hfill\ensuremath{\blacksquare}} +\newcommand*{\qedempty}{\hfill\ensuremath{\square}} + +\newcommand{\explain}[1]{ + \begin{bmatrix} + #1 + \end{bmatrix} +} + +\newcommand{\probability}[1]{\mathrm{Pr} \left[ #1 \right]} +\newcommand{\expected}[1]{\mathrm{E} \left[ #1 \right]} + +\newcommand{\todo}{\texttt{todo!}} + +\newcommand{\osmall}[1]{\overline{o}\left( #1 \right)} +\DeclareMathOperator{\dif}{d \!} +\DeclareMathOperator{\Image}{Im} + +\hypersetup{colorlinks=true, linkcolor=magenta} + +% -- Left/right header text and footer (to appear on every page) -- +\pagestyle{fancy} +\renewcommand{\footrulewidth}{0.4pt} +\renewcommand{\headrulewidth}{0.4pt} + +\cfoot{} +\rfoot{\thepage} diff --git a/libsolve.py b/libsolve.py new file mode 100644 index 0000000..e9a0677 --- /dev/null +++ b/libsolve.py @@ -0,0 +1,330 @@ +from __future__ import annotations +from typing import Iterable, Union +from fractions import Fraction +from itertools import zip_longest + + +def is_scalar(obj): + return isinstance(obj, (Fraction, int)) + + +POLY_COLOR = None +# POLY_COLOR = '36' # Uncomment to have color + + +class PolyRenderBase: + def render(self, poly: Poly) -> str: + raise NotImplementedError() + + def hint(self, poly: Poly) -> int: + raise NotImplementedError() + + +class Poly: + def __init__(self, vec: Iterable, letter='x', renderer=None): + ''' + vec: big-endian coefficients + ''' + from render import UnicodeRender + self.vec = list(vec) + self.letter = letter + self.renderer = renderer or UnicodeRender() + self._trim_zeros() + + def _trim_zeros(self): + ''' + Trim trailing zeros in coefficients: [0, 1, 1, 0] -> [0, 1, 1] + Needed for multiplication to work correctly + ''' + len_zeros = 0 + for c in reversed(self.vec): + if c != 0: + break + len_zeros += 1 + if len_zeros > 0: + self.vec = self.vec[:-len_zeros] + if len(self.vec) == 0: + self.vec = [0] + + def __mul__(self, rhs: Union[Poly, Fraction, int]): + if is_scalar(rhs): + return Poly([c * rhs for c in self.vec]) + + elif isinstance(rhs, Poly): + # no fft 4 u + result = [0] * (self.deg() + rhs.deg() + 1) + self._trim_zeros() + rhs._trim_zeros() + for i in range(len(self.vec)): + for j in range(len(rhs.vec)): + if all(c != 0 for c in (self.vec[i], rhs.vec[j])): + result[i + j] += self.vec[i] * rhs.vec[j] + return Poly(result) + + else: + raise TypeError(f'{type(rhs)} not supported') + + def __truediv__(self, rhs: Union[Fraction, int]): + if is_scalar(rhs): + return Poly([c * Fraction(1, rhs) for c in self.vec]) + else: + raise TypeError(f'{type(rhs)} not supported') + + def __add__(self, rhs: Union[Poly, Fraction, int]): + if is_scalar(rhs): + return Poly([self.vec[0] + rhs] + self.vec[1:]) + elif isinstance(rhs, Poly): + result = [] + for pair in zip_longest(self.vec, rhs.vec): + result.append(sum(c for c in pair if c is not None)) + return Poly(result) + + def __sub__(self, rhs: Union[Poly, Fraction, int]): + return self + (-rhs) + + def __neg__(self): + return Poly(-c for c in self.vec) + + def deg(self): + ''' + Get degree of poly + ''' + d = len(self.vec) - 1 + for c in reversed(self.vec): + if c != 0: + return d + else: + d -= 1 + return max(d, 0) + + def shift(self, deg): + ''' + divide by x^deg, drop rest + ''' + for i in range(deg): + del self.vec[0] + + def __repr__(self): + return self.renderer.render(self) + + def hint(self): + return self.renderer.hint(self) + + +class Row: + ''' + Matrix row. + ''' + + def __init__(self, it: Iterable, dtype=Poly): + def make_poly(obj): + if isinstance(obj, (int, Fraction)): + return Poly([obj]) + elif isinstance(obj, Poly): + return obj + else: + raise TypeError(f'{type(obj)} not supported') + + self.lst = list(map(make_poly, it)) + self.hints = [1] * len(self.lst) + + def __add__(self, obj: Row): + ''' + Add another row + ''' + assert isinstance(obj, Row) + assert len(obj.lst) == len(self.lst) + pairs = zip(self.lst, obj.lst) + return Row(map(lambda x: x[0] + x[1], pairs)) + + def __mul__(self, k: Union[int, Fraction]): + ''' + Multiply by int or fractions.Fraction + ''' + assert isinstance(k, (int, Fraction)) + return Row(map(lambda x: x * k, self.lst)) + + def __iter__(self): + return iter(self.lst) + + def __getitem__(self, key): + return self.lst[key] + + def __setitem__(self, key, val): + self.lst[key] = val + + def __len__(self): + return len(self.lst) + + def __repr__(self): + parts = [] + for el, hint in zip(self.lst, self.hints): + part = '{el: >{hint}}'.format(el=repr(el), hint=hint) + if el.deg() > 0 and POLY_COLOR is not None: + part = '\x1b[' + POLY_COLOR + 'm' + part + '\x1b[0m' + parts.append(part) + + return ('[' + ' '.join(parts) + ']') + + def get_hints(self): + ''' + Get hints for other structures to align items + ''' + return [el.hint() for el in self.lst] + + def set_hints(self, hints): + ''' + Set hints to align items within row + ''' + self.hints = hints + + +class Matrix: + ''' + Matrix. You can apply three elementary transforms to self. + ''' + + def __init__(self, rows): + def make_row(obj): + if isinstance(obj, Row): + return obj + else: + return Row(obj) + + self.rows = list(map(make_row, rows)) + assert all(len(row) == len(self.rows[0]) for row in self.rows) + + def make_S(self, i: int, j: int, lbd: Union[int, Fraction], axis=0): + ''' + if axis == 0, do transform on rows, else on cols + M[i] = M[i] + M[j] * lbd + ''' + if axis == 0: + self.rows[i] = self.rows[i] + self.rows[j] * lbd + else: + for row in self.rows: + row[i] = row[i] + row[j] * lbd + + def make_U(self, i: int, j: int, axis=0): + ''' + if axis == 0, do transform on rows, else on cols + Swap M[i] and M[j] + ''' + if axis == 0: + self.rows[i], self.rows[j] = self.rows[j], self.rows[i] + else: + for row in self.rows: + row[i], row[j] = row[j], row[i] + + def make_D(self, i: int, lbd: Union[int, Fraction], axis=0): + ''' + if axis == 0, do transform on rows, else on cols + Multiply M[i] by rational lbd + ''' + if axis == 0: + self.rows[i] = self.rows[i] * lbd + else: + for row in self.rows: + row[i] = row[i] * lbd + + def det(self) -> Poly: + ''' + Get determinant of matrix + ''' + assert all(len(row) == len(self.rows) for row in self.rows) + if len(self.rows) == 1: + return self.rows[0][0] + res = Poly([0]) + try: + for i in range(len(self.rows[0])): + cofactor = Matrix([ + self.rows[j][:i] + self.rows[j][i + 1:] + for j in range(1, len(self.rows)) + ]) + res += cofactor.det() * (-1) ** i * self.rows[0][i] + except Exception as e: + print(self) + raise e + + return res + + def __sub__(self, oth): + return self + (-oth) + + def __neg__(self): + rows = [row * (-1) for row in self.rows] + return Matrix(rows) + + def __add__(self, oth): + rows = [row1 + row2 for row1, row2 in zip(self.rows, oth.rows)] + return Matrix(rows) + + def __getitem__(self, idx): + return self.rows[idx] + + def __setitem__(self, idx, val): + self.rows[idx] = val + + @property + def shape(self): + return len(self.rows), len(self.rows[0]) + + def __matmul__(self, other): + assert self.shape[1] == other.shape[0] + rows = [ + [ + sum(( + self.rows[j][i] * other.rows[i][k] + for i in range(self.shape[1]) + ), Poly([0])) + for k in range(other.shape[1]) + ] for j in range(self.shape[0]) + ] + return Matrix(rows) + + def __repr__(self): + hints = [row.get_hints() for row in self.rows] + max_hints = [ + max(hints[j][i] for j in range(len(hints))) + for i in range(len(hints[0])) + ] + + for row in self.rows: + row.set_hints(max_hints) + + return '\n'.join(repr(row) for row in self.rows) + + def to_tex(self): + parts = [] + for row in self.rows: + parts.append(' & '.join(map(str, row.lst))) + return '\\begin{bmatrix}\n' + '\\\\\n'.join(parts) + '\n\\end{bmatrix}' + + def triangulate(self): + for i in range(self.shape[1]): + for j in range(i, self.shape[0]): + assert(self[j][i].deg() == 0) + if self[j][i].vec[0] != 0: + # check we are main variable + if not all(self[j][k].vec[0] == 0 for k in range(i)): + continue + + for k in range(self.shape[0]): + assert(self[k][i].deg() == 0) + if k == j: + continue + coef = -Fraction(self[k][i].vec[0]) / Fraction(self[j][i].vec[0]) + self[k] = self[k] + self[j] * coef + break + +class Permutation: + def __init__(self, perm: Iterable): + self.perm = list(perm) + + def apply(self, now: list): + assert len(self.perm) == len(now) + res = [0] * len(self.perm) + for i in range(len(self.perm)): + res[self.perm[i]] = now[i] + + return res @@ -0,0 +1,114 @@ +from libsolve import * +from fractions import Fraction +import numpy as np + +ONE_SIMEQ = '\\overset{{\\texttt{{one.py}}}}\\simeq' + +# generate figure as plain file, so we can \input it +def gen_figure(figname, text): + with open(f'figures/fig_one_{figname}.tex', 'w') as fd: + fd.write('$$' + text + '$$') + +m = Matrix([ + [-1, 4, 1, -2, 1, 3], + [-1, 4, 1, -2, 1, 3], + [1, -4, 3, -2, 7, 5] +]) + + +vectors = [ + [3, 1, -7, -3, 3, -1], + [2, 2, 5, 3, 1, -2], +] +for i, v in enumerate(vectors): + v_t = Matrix([[i] for i in [3, 1, -7, -3, 3, -1]]) + gen_figure(f'proof_v{i}', + f''' + {m.to_tex()} + \\times + {v_t.to_tex()} + = + {(m @ v_t).to_tex()} + ''') + +init = m.to_tex() +m.make_S(0, 1, -1) +m.make_S(1, 2, 1) +m.make_D(1, Fraction(1, 4)) +m.make_S(2, 1, -3) + +init_triang = m.to_tex() + +gen_figure('init_to_triang', +f''' + {init} + {ONE_SIMEQ} + {init_triang} +''') + + + + + +# steps are the same every time, cause we change only last col +def convert_steps(mat, mat_no): + before = mat.to_tex() + mat.make_S(0, 1, -4) + mat.make_S(2, 0, 1) + mat.make_S(3, 0, 1) + mat.make_D(0, -1) + mat.make_S(0, 4, -1) + mat.make_S(2, 4, 3) + mat.make_S(3, 4, 1) + + mat.make_S(0, 5, 1) + mat.make_S(2, 5, 1) + mat.make_S(3, 5, -1) + after = mat.to_tex() + + gen_figure(f'convert_v{mat_no}', + f''' + {before} + {ONE_SIMEQ} + {after} + ''') + +convert_steps(Matrix([ + [4,-1,-1,1,3], + [1,0,0,0,1], + [0,1,-2,-2,-7], + [0,1,0,0,-3], + [0,0,1,0,3], + [0,0,0,1,-1] +]), 1) + + +convert_steps(Matrix([ + [4,-1,-1,1,2], + [1,0,0,0,2], + [0,1,-2,-2,5], + [0,1,0,0,3], + [0,0,1,0,1], + [0,0,0,1,-2] +]), 2) + + + + + + +m = Matrix([ + [1, -3, 3, 1], + [2, 3, 1, -2] +]) + +before = m.to_tex() +m.make_S(1, 0, -2) +after = m.to_tex() + +gen_figure('solve_last', +f''' + {before} + {ONE_SIMEQ} + {after} +''') diff --git a/render.py b/render.py new file mode 100644 index 0000000..6cd3c7d --- /dev/null +++ b/render.py @@ -0,0 +1,45 @@ +from libsolve import Poly, PolyRenderBase + + +class UnicodeRender(PolyRenderBase): + def __init__(self): + # may not work. see + # https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts + # to test with your font + self.sup = '⁰¹²³⁴⁵⁶⁷⁸⁹' # must be <sup>0123456789</sup> + + def render(self, poly: Poly) -> str: + rev = list(reversed(poly.vec)) + if all(r == 0 for r in rev): + return '0' + d = poly.deg() + res = [] + for i in range(len(rev)): + if rev[i] == 0: + continue + if i == 0: + if rev[i] < 0: + res.append('-') + else: + if rev[i] < 0: + res.append(' - ') + else: + res.append(' + ') + + if abs(rev[i]) != 1 or i == d: + res.append(str(abs(rev[i]))) + if i != d: + res.append(poly.letter) + if d - i != 1: + res.append(self._int2sup(d - i)) + return ''.join(res) + + def hint(self, poly: Poly) -> int: + return len(self.render(poly)) + + def _int2sup(self, n): + res = [] + while n > 0: + res.append(self.sup[n % 10]) + n //= 10 + return ''.join(reversed(res)) @@ -0,0 +1,107 @@ +from libsolve import * +from fractions import Fraction +import numpy as np + +TWO_SIMEQ = '\\overset{{\\texttt{{two.py}}}}\\simeq' + +# generate figure as plain file, so we can \input it +def gen_figure(figname, text): + with open(f'figures/fig_two_{figname}.tex', 'w') as fd: + fd.write('$$' + text + '$$') + +AT = Matrix([ + [-2, 14, 18, 14], + [-3, -9, -3, -3], + [-12, -6, 18, 12], + [6, 18, 6, 6] +]) + + +before = AT.to_tex() + +AT.make_D(0, -Fraction(1, 2)) +AT.make_D(1, -Fraction(1, 3)) +AT.make_D(2, -Fraction(1, 6)) +AT.make_D(3, Fraction(1, 6)) + +AT.make_S(1, 0, -1) +AT.make_S(2, 0, -2) +AT.make_S(3, 0, -1) + +AT.make_S(2, 1, -Fraction(3, 2)) +AT.make_S(3, 1, -1) + +AT.make_D(1, Fraction(1, 2)) + +gen_figure('fsr_A_T', +f''' + {before} + {TWO_SIMEQ} + {AT.to_tex()} +''') + + +AB = Matrix([ + [-2, -3, -12, 6], + [14, -9, -6, 18], + [18, -3, 18, 6], + [14, -3, 12, 6], + [2, -1, 1, 0], + [7, -4, 0, 5] +]) + +before = AB.to_tex() + +AB.triangulate() + +AB.make_D(0, Fraction(1, 2)) +AB.make_D(1, -Fraction(1, 30)) +AB.make_U(2, 4) + + +gen_figure('AB_sol', +f''' +{before} +{TWO_SIMEQ} +{AB.to_tex()} +''') + + +A = Matrix([ + [-2, -3, -12, 6], + [14, -9, -6, 18], + [18, -3, 18, 6], + [14, -3, 12, 6] +]) + +before = A.to_tex() +A.triangulate() + +A.make_D(0, -1) +A.make_D(1, -Fraction(1, 30)) + +gen_figure('ker_A', +f''' + {before} + {TWO_SIMEQ} + {A.to_tex()} +''') + +imker = Matrix([ + [-2, 14, 18, 14], + [-3, -9, -3, -3], + [-12, -6, 18, 12], + [6, 18, 6, 6], + [-3, -6, 2, 0], + [0, 2, 0, 1] +]) + +before = imker.to_tex() +imker.triangulate() + +gen_figure('imker', +f''' + {before} + {TWO_SIMEQ} + {imker.to_tex()} +''')
\ No newline at end of file |