fumi-python-lib
Loading...
Searching...
No Matches
basic_algebraic_calculation_class.py
1import sympy
2import numpy
3from IPython.display import Math
4from IPython.display import display
5import copy
6
8
9 def __init__(self, input_variable_list = []):
10 '''
11 Initialze object.
12 Variables can be defined at __init__. In that case, insert a list of variables as first argument.
13 '''
14 self.left_hand_side = 'f(x)'
15 self.right_hand_side = sympy.symbols("x")
16 self.matrix_symbol = None
17 self.matrix_element_symbols = None
18 self.expanded_right_hand_side = None
23 self.variable_list = None
24 self.variable_symbols = None
25 self.latex_paste_mode = False
26 if len(input_variable_list) != 0:
27 self.variable_list = input_variable_list
28 self.variable_symbols = input_variable_list
30
31 def copy_class(self):
32 '''
33 Copy object
34 '''
35 return copy.copy(self)
36
37 def select_print_mode(self, Bool):
38 '''
39 Select Print Mode (Default : False)
40 False : Print with IPython.Display (Output is in Latex format if a jupyer notebook-based application is used.)
41 True : Print with print function(The output is in Latex formula notation. Pasteable in overleaf or Cloud latex.)
42 '''
43 self.latex_paste_mode = Bool
44
45 def set_formula(self, lhs, rhs):
46 '''
47 Assign left hand side and right hand side
48 '''
49 self.left_hand_side = lhs
50 self.right_hand_side = rhs
51
52 def set_left_hand_side(self, lhs):
53 '''
54 Assign left hand side
55 '''
56 self.left_hand_side = lhs
57
58 def set_right_hand_side(self, rhs):
59 '''
60 Assign right hand side
61 '''
62 self.right_hand_side = rhs
63
64 def set_variable_symbols(self, input_list=None):
65 '''
66 Registor the variables created by sympy.symbol to this class.
67 It is used for differentiating and integrating.
68 '''
69 self.variable_symbols = []
70 if input_list is not None:
71 self.variable_list = input_list
72 for i in range( len( self.variable_list ) ):
73 self.variable_symbols.append( sympy.symbols( self.variable_list[i] ) )
74
75 def get_formula(self):
76 '''
77 Return left hand side and right hand side
78 '''
79 return self.left_hand_side, self.right_hand_side
80
82 '''
83 Return left hand side
84 '''
85 return self.left_hand_side
86
88 '''
89 Return right hand side
90 '''
91 return self.right_hand_side
92
93 def create_variables(self, input_variable_list):
94 '''
95 Create variables as algebra using sympy.symbols
96 input_variable_list : list of variables.
97 '''
99 for i in range( len( input_variable_list ) ):
100 self.created_variable_symbols.append( sympy.symbols( input_variable_list[i] ) )
101
102 self.set_variable_symbols( input_variable_list )
103 return self.created_variable_symbols
104
105 def assign_values(self, symbol, values,round_digits=None, update_flag=False ):
106 '''
107 Assign and round variables.
108 symbol : list of slgebaric variables
109 values : list of numerical variables
110 round_digits : number of digits(default: noround)
111 update_flag : flag for updating original function(default: noupdate)
112 '''
113 self.variable_values_args = sympy.lambdify( symbol, self.right_hand_side, "numpy" )
114 if round_digits is not None:
115 for i in range( len( values ) ):
116 values[i] = round( values[i], int(round_digits) )
117 self.variable_values = self.variable_values_args( *values )
118
119 if update_flag:
120 if isinstance(self.variable_values, sympy.MatrixBase) or isinstance(self.variable_values, numpy.ndarray):
121 self.right_hand_side = sympy.Matrix( self.variable_values )
122 else:
124
126 '''
127 Return registered symbols
128 '''
129 return self.variable_symbols
130
132 '''
133 Return assigned values
134 '''
135 return self.variable_values
136
137 def round_right_hand_side(self, round_digits):
138 '''
139 Improve readability when the formula will be dumped since the default number of digits displayed is very large.
140 The rounded function is overridden by the original function.
141 Therefore, it is recommended to use this function only at the end of the function output.
142 In addition, the problem of +1.0 and -1.0 being displayed after rounding has been eliminated.
143 (+1.0 and -1.0 when rounding with zero digits forces the assignment of +1 and -1.)
144 '''
145 replacements = {}
146
147 if isinstance(self.right_hand_side, sympy.MatrixBase):
148 rounded_matrix = self.right_hand_side.applyfunc(lambda x: round(x, round_digits))
149 self.right_hand_side = rounded_matrix
150 else:
151 if isinstance(self.right_hand_side, (sympy.Basic, sympy.Expr)):
152 for n in self.right_hand_side.atoms( sympy.Number ):
153 val = round( n, round_digits )
154 if abs( round( val, 0 ) ) == 1:
155 replacements[n] = int( round( val, 0 ) )
156 else:
157 replacements[n] = round( n, round_digits )
158 self.right_hand_side = self.right_hand_side.xreplace( replacements )
159 else:
160 self.right_hand_side = round( self.right_hand_side, round_digits )
161
162 return self.right_hand_side
163
164 def create_martix_symbols(self, matrixsymbol, row, col, elementsymbol=None):
165 '''
166 Create matrix as algebra
167 matrixsymbol : variable that represents the entire matrix. (recommend to use capital letter)
168 row : maximum row number
169 col : maximum column number
170 elementsymbol : symbol of each elements (if elementsymbol is none, lowercase letter is adpoted)
171 '''
172 self.matrix_symbol = []
173 self.matrix_element_symbols = []
174 matrix = []
175 for i in range( row ):
176 rowindex = "_"+str(i+1)
177 row = []
178 for j in range( col ):
179 colindex = "_" + str(j+1)
180 elements = None
181 if elementsymbol is None:
182 elements = matrixsymbol.lower() + rowindex+colindex
183 else :
184 elements = elementsymbol + rowindex + colindex
185 self.matrix_element_symbols.append( sympy.symbols( elements ) )
186 row.append( elements )
187 matrix.append( row )
188 self.matrix_symbol = sympy.Matrix( matrix )
189 return self.matrix_symbol, self.matrix_element_symbols
190
191 def print_formula(self):
192 '''
193 Dump formula.
194 Select print mode in self.select_print_mode()
195 False : Print with IPython.Display (Output is in Latex format if a jupyer notebook-based application is used.)
196 True : Print with print function(The output is in Latex formula notation. Pasteable in overleaf or Cloud latex.)
197 '''
198 if not self.latex_paste_mode:
199 display( Math( f'{self.left_hand_side} = {sympy.latex( self.right_hand_side )}' ) )
200 elif self.latex_paste_mode:
201 print( self.left_hand_side , "=", sympy.latex( self.right_hand_side ), "\\\\" )
202
203 def print_external_input(self, external_input_lhs=None, external_input_rhs=None):
204 '''
205 Dump external input
206 Select print mode in self.select_print_mode()
207 False : Print with IPython.Display (Output is in Latex format if a jupyer notebook-based application is used.)
208 True : Print with print function(The output is in Latex formula notation. Pasteable in overleaf or Cloud latex.)
209 '''
210 dum_lhs = 'f'
211 if external_input_lhs is not None:
212 dum_lhs = external_input_lhs
213 if external_input_rhs is not None:
214 if not self.latex_paste_mode:
215 display( Math( f'{dum_lhs} = {sympy.latex( external_input_rhs )}' ) )
216 elif self.latex_paste_mode :
217 print( dum_lhs, " = ", sympy.latex( external_input_rhs ), "\\\\" )
218
219 def expand_formula(self, assign_flag=False):
220 '''
221 Expand formula.
222 assign_flag : flag to update original function. (default : no update)
223 '''
224 self.expanded_right_hand_side = self.right_hand_side.expand()
225 if not self.latex_paste_mode:
226 display( Math( f'{self.left_hand_side} = {sympy.latex( self.expanded_right_hand_side )}' ) )
227 elif self.latex_paste_mode:
228 print( self.left_hand_side , "=", sympy.latex( self.expanded_right_hand_side ), "\\\\" )
229
230 if True:
232
233 def get_matrix(self, input):
234 '''
235 Return matrix
236 '''
237 return sympy.Matrix( input )
238
239 def indefinite_integral(self, val, update_flag=False):
240 '''
241 Execute indefinite integral with variable called in 2nd argument.
242 '''
243 self.integrated_left_hand_side = '\\int ' + self.left_hand_side + 'd' + str(val)
244 self.integrated_right_hand_side = sympy.integrate( self.right_hand_side, val )
245 if update_flag :
249
250 def definite_integral(self, val, min, max, update_flag=False):
251 '''
252 Execute definite integral with variable called in 2nd argument from min(3rd argument) to max(4th argument).
253 '''
254 self.integrated_left_hand_side = '\\int_{' + str(min) + '}^{' + str(max) + '}' + self.left_hand_side + 'd' + str(val)
255 self.integrated_right_hand_side = sympy.integrate( self.right_hand_side, ( val, min, max ) )
256 if update_flag:
260
261 def differentiate(self, val, update_flag=False):
262 '''
263 Execute differentiate with variable called in 2nd argument.
264 '''
265 self.differentiated_left_hand_side = '\\frac{d}{d' + str(val) + '}' + self.left_hand_side
266 self.differentiated_right_hand_side = sympy.diff( self.right_hand_side , val )
267 if update_flag:
271