def rescale_row(self, i: int, s) -> HtmlFragment: """Replace i-th row of self by s times i-th row of self. The operation is done in place.""" return HtmlFragment(''.join([r'\[', self._latex_(), self._format_row_operations(self._rescale_row(i, s)), r'\rightarrow', self._latex_() + r'\]']))
def lu_swap(self, r1: int, r2: int) -> HtmlFragment: """Swap rows r1 and r2 of self, up to second diagonal. Used in LUP factorization. This operation is done in place.""" return HtmlFragment(''.join([r'\[', self._latex_(), self._format_row_operations(self._lu_swap(r1, r2)), r'\rightarrow', self._latex_(), r'\]']))
def swap_rows(self, r1: int, r2: int) -> HtmlFragment: """Swap rows r1 and r2 of self. The operation is done in place.""" return HtmlFragment(''.join([r'\[', self._latex_(), self._format_row_operations(self._swap_rows(r1, r2)), r'\rightarrow', self._latex_(), r'\]']))
def add_multiple_of_row(self, i: int, j: int, s) -> HtmlFragment: """Add s times row j to row i. The operation is done in place.""" return HtmlFragment(''.join([r'\[', self._latex_(), self._format_row_operations(self._add_multiple_of_row(i, j, s)), r'\rightarrow', self._latex_(), r'\]']))
def col_expansion(self, i: int) -> HtmlFragment: """Laplace expansion on i-th column.""" output = list() output.append(r'\[') for j in range(self.M.nrows()): if j > 0: output.append('+') output.append(r'(-1)^{' f'{j+1} + {i+1}' r'}\cdot') output.append(f'({self.M[j, i]})' r'\cdot') N = self.M[[k for k in range(self.M.nrows()) if k != j], [k for k in range(self.M.ncols()) if k != i]] output.append(IMatrix(N).as_determinant()._latex_()) output.append(r'\]') return HtmlFragment(''.join(output))
def my_run_simplex_method(self): output = [] while not self.is_optimal(): self.pivots += 1 if self.entering() is None: self.enter(self.pivot_select_entering()) if self.leaving() is None: if self.possible_leaving(): self.leave(self.pivot_select_leaving()) output.append(self._html_()) if self.leaving() is None: output.append("The problem is unbounded in $()$ direction.".format( latex(self.entering()))) break output.append(self._preupdate_output("primal")) self.update() if self.is_optimal(): output.append(self._html_()) return HtmlFragment("\n".join(output))
def to_reduced_form(self): """Transform self to the reduced echelon form of self.""" output = list() for changed_row in range(1, self.M.nrows()): operations = {i: r'\ ' for i in range(self.M.nrows())} unchanged = self._latex_() for row in range(0, changed_row): factor = -self.M[row][changed_row] operations.update(self._add_multiple_of_row(row, changed_row, factor)) output.append(r'\[') output.append(unchanged) output.append(self._format_row_operations(operations)) output.append(r'\rightarrow') output.append(self._latex_()) output.append(r'\]') return HtmlFragment('\n'.join(output))
def _html_(self): r""" HTML representation of a table. Strings of html will be parsed for math inside dollar and double-dollar signs. 2D graphics will be displayed in the cells. Expressions will be latexed. The ``align`` option for tables is ignored in HTML output. Specifying ``header_column=True`` may not have any visible effect in the Sage notebook, depending on the version of the notebook. OUTPUT: A :class:`~sage.misc.html.HtmlFragment` instance. EXAMPLES:: sage: T = table([[r'$\sin(x)$', '$x$', 'text'], [1,34342,3], [identity_matrix(2),5,6]]) sage: T._html_() <div.../div> sage: print(T._html_()) <div class="notruncate"> <table class="table_form"> <tbody> <tr class ="row-a"> <td><script type="math/tex">\sin(x)</script></td> <td><script type="math/tex">x</script></td> <td>text</td> </tr> <tr class ="row-b"> <td><script type="math/tex">1</script></td> <td><script type="math/tex">34342</script></td> <td><script type="math/tex">3</script></td> </tr> <tr class ="row-a"> <td><script type="math/tex">\left(\begin{array}{rr} 1 & 0 \\ 0 & 1 \end{array}\right)</script></td> <td><script type="math/tex">5</script></td> <td><script type="math/tex">6</script></td> </tr> </tbody> </table> </div> Note that calling ``html(table(...))`` has the same effect as calling ``table(...)._html_()``:: sage: T = table([["$x$", r"$\sin(x)$"]] + [(x,n(sin(x), digits=2)) for x in [0..3]], header_row=True, frame=True) sage: T +-----+-----------+ | $x$ | $\sin(x)$ | +=====+===========+ | 0 | 0.00 | +-----+-----------+ | 1 | 0.84 | +-----+-----------+ | 2 | 0.91 | +-----+-----------+ | 3 | 0.14 | +-----+-----------+ sage: print(html(T)) <div class="notruncate"> <table border="1" class="table_form"> <tbody> <tr> <th><script type="math/tex">x</script></th> <th><script type="math/tex">\sin(x)</script></th> </tr> <tr class ="row-a"> <td><script type="math/tex">0</script></td> <td><script type="math/tex">0.00</script></td> </tr> <tr class ="row-b"> <td><script type="math/tex">1</script></td> <td><script type="math/tex">0.84</script></td> </tr> <tr class ="row-a"> <td><script type="math/tex">2</script></td> <td><script type="math/tex">0.91</script></td> </tr> <tr class ="row-b"> <td><script type="math/tex">3</script></td> <td><script type="math/tex">0.14</script></td> </tr> </tbody> </table> </div> """ from itertools import cycle rows = self._rows header_row = self._options['header_row'] if self._options['frame']: frame = 'border="1"' else: frame = '' s = StringIO() if rows: s.writelines([ # If the table has < 100 rows, don't truncate the output in the notebook '<div class="notruncate">\n' if len(rows) <= 100 else '<div class="truncate">', '<table {} class="table_form">\n'.format(frame), '<tbody>\n', ]) # First row: if header_row: s.write('<tr>\n') self._html_table_row(s, rows[0], header=header_row) s.write('</tr>\n') rows = rows[1:] # Other rows: for row_class, row in zip(cycle(["row-a", "row-b"]), rows): s.write('<tr class ="{}">\n'.format(row_class)) self._html_table_row(s, row, header=False) s.write('</tr>\n') s.write('</tbody>\n</table>\n</div>') from sage.misc.html import HtmlFragment return HtmlFragment(s.getvalue())
def to_echelon_form(self) -> HtmlFragment: """Transform self to the echelon form of self.""" output = list() # Gaussian elimination algorithm is derived from # https://ask.sagemath.org/question/8840/how-to-show-the-steps-of-gauss-method/ col = 0 # all cols before this are already done for row in range(0, self.M.nrows()): # Need to swap in a nonzero entry from below while col < self.M.ncols() and self.M[row][col] == 0: for i in self.M.nonzero_positions_in_column(col): if i > row: output.append(r'\[') output.append(self._latex_()) output.append(self._format_row_operations(self._swap_rows(row, i))) output.append(r'\rightarrow') output.append(self._latex_()) output.append(r'\]') break else: col += 1 if col >= self.M.ncols() - self.separate: break # Now guaranteed M[row][col] != 0 if self.M[row][col] != 1: if not is_invertible(self.M[row][col]): output.append(f'<br>Przerywam eliminację bo nie wiem, czy wyrażenie ' f'${sage.all.latex(self.M[row][col])}$ jest niezerowe.') break else: output.append(r'\[') output.append(self._latex_()) output.append(self._format_row_operations(self._rescale_row(row, 1 / self.M[row][col]))) output.append(r'\rightarrow') output.append(self._latex_()) output.append(r'\]') change_flag = False unchanged = self._latex_() operations = dict() for changed_row in range(row + 1, self.M.nrows()): if self.M[changed_row][col] != 0: change_flag = True factor = -1 * self.M[changed_row][col] / self.M[row][col] operations.update(self._add_multiple_of_row(changed_row, row, factor)) if change_flag: output.append(r'\[') output.append(unchanged) output.append(self._format_row_operations(operations)) output.append(r'\rightarrow') output.append(self._latex_()) output.append(r'\]') col += 1 return HtmlFragment('\n'.join(output))