def calcp(prev_r, curr_r): prev_c = sympy.shape(prev_r)[1] curr_c = sympy.shape(curr_r)[1] if prev_c != curr_c: return -1 maxdiff = -1 * sys.maxsize for i in range(curr_c): diff = abs(curr_r[i] - prev_r[i]) if diff > maxdiff: maxdiff = diff return maxdiff
def gseid_iter(m, b, out, k): a = None # coeficiente que acompaña a xi acc = None # acumulador reasignado en cada iteracion r, c = sympy.shape(m) for i in range(r): acc = b[i] for j in range(c): if i == j: a = m[i, j] continue # aca se diferencian gseid_iter y jacobi_iter if j > i: acc -= out[k-1, j] * m[i, j] else: acc -= out[k, j] * m[i, j] acc /= a acc = acc.evalf() newrow = out.row(k) newrow[i] = acc out.row_del(k) out = out.row_insert(k, newrow) return out
def AntiSymmetricMatrix(value): """ That means all the values in the diagonal are zero And M[i, j] = -M[j, i] """ if not IS.SquareMatrix(value): return False if IS.NumpyArray(value): if np.any(np.diag(value) != 0): return False matrix = np.copy(value) return np.all(np.abs(matrix + np.transpose(matrix)) < 1e-13) if IS.SympyBasic(value): if IS.SympyMatrix(value): pass elif IS.SympyArray(value): value = sp.Matrix(value) else: return False n, = sp.shape(value)[0] return (value + value.T) == sp.zeros(n, n) if IS.Tuple(value) or IS.List(value): value = np.array(value) return IS.AntiSymmetricMatrix(value) return False
def report_plist(plist): c = sympy.shape(plist)[1] s = "\nPrecisiones obtenidas en cada iteracion:\n" for i in range(c): s += ("Iter %d" % i).center(20) s += str(plist[i]).center(25) + "\n" print(s)
def report_m(m, hdr=""): r, c = sympy.shape(m) s = hdr for i in range(r): for j in range(c): s += str(m[i, j]).center(25) s += "\n" print(s)
def inf_norm(m): maxval = -1 * sys.maxsize r, c = sympy.shape(m) for i in range(r): acc = 0 for j in range(c): acc += abs(m[i, j]) if maxval < acc: maxval = acc return maxval.evalf()
def cofactor_expansion(M): n = sym.shape(M)[0] if n == 1: return M[0,0] total = 0 for i in range(n): minor = M.copy() minor.row_del(0) minor.col_del(i) total += (-1)**i * M[0,i] * cofactor_expansion(minor) return total
def SquareMatrix(value): if not IS.Matrix(value): return False if IS.NumpyArray(value): shape = value.shape if shape[0] == shape[1]: return True return False if IS.SympyBasic(value): if IS.SympyMatrix(value): shape = sp.shape(value) elif IS.SympyArray(value): shape = sp.shape(value) else: return False if shape[0] == shape[1]: return True return False if IS.Tuple(value) or IS.List(value): value = np.array(value) return IS.SquareMatrix(value) return False
def m_err(x, y, f_expr, w_expr, prod, calc_prod, B, X): n = sympy.shape(B)[0] acc = 0 for i in range(n): acc += X[i] * B[i] prod = prod.subs({"w": w_expr}) p = prod.subs({"f": f_expr, "g": f_expr}).evalf() f_sq = calc_prod(x, y, p) err = (f_sq - acc)**(1 / 2) return err
def converg(m): acc = None # suma de valores absolutos en la columna q no estan en la diagonal diag = None # valor absoluto del elemento de la columna que está en la diagonal r, c = sympy.shape(m) for i in range(r): acc = 0 for j in range(c): if i == j: diag = abs(m[j, i]) else: acc += abs(m[j, i]) if diag < acc: return False return True
def report_iters(out, algoritmo): r, c = sympy.shape(out) s = "\nVectores X obtenidos por metodo de %s:\n" % ("JACOBI" if algoritmo else "GAUSS-SEIDEL") s += ("vector X".center(20)) for i in range(c): s += ("x%d" % i).center(25) s += "\n" for i in range(r): s += ("x%d" % i).center(20) for j in range(c): s += str(out[i, j]).center(25) s += "\n" print(s)
def sel(m, b, iter_fc, n=sys.maxsize, p=0): out = sympy.Matrix([]) plist = sympy.Matrix([]) c = sympy.shape(m)[1] out = out.row_insert(0, sympy.Matrix([[0 for i in range(c)]])) plist = plist.col_insert(0, sympy.Matrix([[sys.maxsize]])) k = 1 while k < n + 1 and plist[k - 1] > p: out = out.row_insert(k, sympy.Matrix([[0 for i in range(c)]])) out = iter_fc(m, b, out, k) newp = calcp(out.row(k - 1), out.row(k)) plist = plist.col_insert(k, sympy.Matrix([[newp]])) if plist[k] < 0: raise ValueError("Precision negativa, revisar input") k += 1 return out, plist
if __name__ == "__main__": inputlist = parseargs(sys.argv[1:], NFIELDS) algoritmo = 1 if "j" in inputlist[0] else 0 n = symparse(inputlist[1]) n = n if n > 0 else sys.maxsize p = symparse(inputlist[2]) p = p if p > 0 else 0 norm_in = symparse(inputlist[3]) b = symparse_seqline(inputlist[4]) b = sympy.Matrix([b]).T m = sympy.Matrix([[]]) for line in inputlist[5:]: newrow = symparse_seqline(line) idx = sympy.shape(m)[0] m = m.row_insert(idx, sympy.Matrix([newrow])) iter_fc = jacobi_iter if algoritmo else gseid_iter norm = inf_norm if norm_in != 1 else uno_norm minv = minvrs(m) x_direc = direc_sel(m, b) cond = cond_sel(m, minv, norm) nm = norm(m) nminv = norm(minv) conv = converg(m) out, plist = sel(m, b, iter_fc, n, p)
def direc_sel(m, b): ret = minvrs(m) * b r = sympy.shape(b)[0] for i in range(r): ret[i] = ret[i].evalf() return ret
def eliminate_state_from_transition_matrix( self, labels: list = None, use_parameters: bool = False) -> Tuple[sp.Matrix, sp.Matrix]: """Returns a matrix, A, and vector, B, corresponding to a linear ODE system describing the state probabilities. Because the state occupancy probabilities must add up to zero, the transition matrix is always singular. We can use this fact to remove one state variable from the system of equations. The labels parameter allows you to choose which variable is eliminated and also the ordering of the states. :param labels: A list of labels. The order of which determines the ordering of outputted system. :param use_parameters: If true substitute in parameters of the transition rates :return: A pair of symbolic matrices, A & B, defining a system of ODEs of the format dX/dt = AX + B. """ if labels is None: labels = list(self.graph.nodes)[:-1] for label in labels: if label not in self.graph.nodes(): raise Exception( f"Provided label, {label} is not present in the graph") _, matrix = self.get_transition_matrix() eliminated_states = [ state for state in self.graph.nodes() if state not in labels ] assert len(eliminated_states) == 1 eliminated_state = eliminated_states[0] matrix = matrix.T shape = sp.shape(matrix) assert shape[0] == shape[1] # List describing the mapping from self.graph.nodes to labels. # permutation[i] = j corresponds to a mapping which takes # graph.nodes[i] to graph.nodes[j]. Map the row to be eliminated to the # end. permutation = [ list(self.graph.nodes()).index(n) for n in labels + [eliminated_state] ] assert len(np.unique(permutation)) == shape[0] matrix = matrix[permutation, permutation] M = sp.eye(shape[0]) replacement_row = np.full(shape[0], -1) M[-1, :] = replacement_row[None, :] A_matrix = matrix @ M B_vec = matrix @ sp.Matrix([[0] * (shape[0] - 1) + [1]]).T if use_parameters: if len(self.rate_expressions) == 0: raise Exception() else: A_matrix = A_matrix.subs(self.rate_expressions) B_vec = B_vec.subs(self.rate_expressions) return A_matrix[0:-1, 0:-1], B_vec[0:-1, :]