"""
matrix building blocks - row entry, row, and rows placeholder
(MatrixRowEntry, MatrixRow, MatrixRows class definition)
"""
from typing import Union, Tuple
import os
if os.environ.get('__USE_CUDA', '0') == '1':
import cupy as np
from cupy import ndarray
else:
import numpy as np
from numpy import ndarray
from g3d.defs import G3DDisplay
[docs]
class MatrixRowEntry:
"""
"""
def __init__(self, i: int = 0, val: float = 0.) -> None:
self._idx = i
self._coef = val
def __reset(self, i: int = 0, val: float = 0.) -> None:
self._idx = i
self._coef = val
[docs]
def nullify(self) -> None:
"""
"""
self.__reset()
@property
def idx(self) -> int:
"""
:return:
"""
return self._idx
@idx.setter
def idx(self, i: int) -> None:
self._idx = i
@property
def coef(self) -> float:
"""
:return:
"""
return self._coef
@coef.setter
def coef(self, val: float) -> None:
self._coef = val
[docs]
def scale(self, f: float) -> None:
"""
:param f:
"""
self._coef *= f
[docs]
def add(self, val: float) -> None:
"""
:param val:
"""
self._coef += val
[docs]
def print(self) -> None:
"""
"""
print(' column index: %d, coefficient: %f' % (self._idx, self._coef))
[docs]
class MatrixRow:
"""
"""
def __init__(self, i: int = 0) -> None:
self._idx = i
self._size = 0
self._entries = []
def __reset(self, i: int = 0) -> None:
self._idx = i
self._size = 0
self._entries = []
[docs]
def nullify(self) -> None:
"""
"""
self.__reset()
@property
def idx(self) -> int:
"""
:return:
"""
return self._idx
@idx.setter
def idx(self, i: int) -> None:
self._idx = i
@property
def size(self) -> int:
"""
:return:
"""
return self._size
[docs]
def get_entries(self) -> list:
"""
:return:
"""
return self._entries
def __find_entry(self, col: int) -> Union[MatrixRowEntry, int]:
for entry in self._entries:
if entry.idx == col:
return entry
return -1
def __add_new_entry(self, col: int, coef: float) -> MatrixRowEntry:
entry = MatrixRowEntry(col, coef)
self._entries.append(entry)
self._size += 1
return entry
[docs]
def add_entry(self, col: int, coef: float) -> None:
"""
:param col:
:param coef:
:return:
"""
entry = self.__find_entry(col)
if type(entry) is MatrixRowEntry:
entry.add(coef)
return None
self.__add_new_entry(col, coef)
return None
[docs]
def add_to_diagonal(self, val: float) -> None:
"""
:param val:
"""
col = self._idx
self.add_entry(col, val)
[docs]
def set_diagonal(self, coef: float) -> None:
"""
:param coef:
:return:
"""
col = self._idx
entry = self.__find_entry(col)
if type(entry) is MatrixRowEntry:
entry.coef = coef
return None
self.__add_new_entry(col, coef)
return None
[docs]
def scale(self, f: float) -> None:
"""
:param f:
"""
for entry in self._entries:
entry.scale(f)
[docs]
def get_entry(self, i: int) -> Union[MatrixRowEntry, None]:
"""
:param i:
:return:
"""
if i < len(self._entries):
return self._entries[i]
else:
return None
[docs]
def get_col(self, i: int) -> int:
"""
:param i:
:return:
"""
if i < len(self._entries):
return self._entries[i].idx
else:
return -1
[docs]
def get_coef(self, i: int) -> Union[float, None]:
"""
:param i:
:return:
"""
if i < len(self._entries):
return self._entries[i].coef
else:
return None
[docs]
def sort(self) -> None:
"""
"""
if self._size > 1:
for i in range(self._size - 1):
flag = 0
for j in range(self._size - i - 1):
if self._entries[j].idx > self._entries[j + 1].idx:
self._entries[j], self._entries[j + 1] = self._entries[j + 1], self._entries[j]
flag = 1
if flag == 0:
break
[docs]
def print(self) -> None:
"""
"""
g3d_disp = G3DDisplay()
g3d_disp.hline('-')
print(' row index: %d (number of columns: %d)' % (self._idx, self._size))
g3d_disp.hline('-')
for entry in self._entries:
entry.print()
[docs]
class MatrixRows:
"""
"""
def __init__(self) -> None:
self._size = 0
self._rows = []
def __reset(self) -> None:
self._size = 0
self._rows = []
[docs]
def nullify(self) -> None:
"""
"""
self.__reset()
@property
def size(self) -> int:
"""
:return:
"""
return self._size
[docs]
def get_rows(self) -> list:
"""
:return:
"""
return self._rows
[docs]
def get_row(self, ir: int) -> Union[MatrixRow, None]:
"""
:param ir:
:return:
"""
if ir < len(self._rows):
return self._rows[ir]
else:
return None
[docs]
def get_entry(self, ir: int, ic: int) -> Union[MatrixRowEntry, None]:
"""
:param ir:
:param ic:
:return:
"""
if ir < len(self._rows):
return self._rows[ir].get_entry(ic)
else:
return None
[docs]
def get_col(self, ir: int, ic: int) -> int:
"""
:param ir:
:param ic:
:return:
"""
if ir < len(self._rows):
return self._rows[ir].get_col(ic)
else:
return -1
[docs]
def get_coef(self, ir: int, ic: int) -> Union[float, None]:
"""
:param ir:
:param ic:
:return:
"""
if ir < len(self._rows):
return self._rows[ir].get_coef(ic)
else:
return None
def __find_row(self, idx: int) -> Union[MatrixRow, None]:
for row in self._rows:
if row.idx == idx:
return row
return None
def __add_new_row(self, idx: int) -> MatrixRow:
row = MatrixRow(idx)
self._rows.append(row)
self._size += 1
return row
[docs]
def add_row(self, idx: int = 0) -> MatrixRow:
"""
:param idx:
:return:
"""
row = self.__find_row(idx)
if type(row) is MatrixRow:
return row
return self.__add_new_row(idx)
[docs]
def add_entry(self, idx: int, col: int, coef: float) -> None:
"""
:param idx:
:param col:
:param coef:
"""
row = self.add_row(idx)
row.add_entry(col, coef)
[docs]
def add_to_diagonals(self, val: float) -> None:
"""
:param val:
"""
for row in self._rows:
row.add_to_diagonal(val)
[docs]
def set_diagonals(self, coef: float) -> None:
"""
:param coef:
"""
for row in self._rows:
row.set_diagonal(coef)
[docs]
def scale(self, f: float) -> None:
"""
:param f:
"""
for row in self._rows:
row.scale(f)
[docs]
def sort(self) -> None:
"""
"""
if self._size > 1:
# sort rows
for i in range(self._size - 1):
flag = 0
for j in range(self._size - i - 1):
if self._rows[j].idx > self._rows[j + 1].idx:
self._rows[j], self._rows[j + 1] = self._rows[j + 1], self._rows[j]
flag = 1
if flag == 0:
break
# for each row, sort columns
for i in range(self._size):
self._rows[i].sort()
[docs]
def count_entries(self) -> int:
"""
:return:
"""
N = 0
for row in self._rows:
N += row.size
return N
[docs]
def print(self) -> None:
"""
"""
g3d_disp = G3DDisplay()
g3d_disp.hline('=')
print('listing matrix entries')
print('(number of rows: %d, number of entries: %d)' % (self._size, self.count_entries()))
g3d_disp.hline('=')
for row in self._rows:
row.print()
[docs]
def get_matrix_dimensions(self) -> Tuple[int, int]:
"""
:return:
"""
ni = 0
nj = 0
for row in self._rows:
ni = max(ni, row.idx)
for entry in row.get_entries():
nj = max(nj, entry.idx)
return ni + 1, nj + 1