rgwfuncs 0.0.26__tar.gz → 0.0.28__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rgwfuncs
3
- Version: 0.0.26
3
+ Version: 0.0.28
4
4
  Summary: A functional programming paradigm for mathematical modelling and data science
5
5
  Home-page: https://github.com/ryangerardwilson/rgwfunc
6
6
  Author: Ryan Gerard Wilson
@@ -182,24 +182,38 @@ These examples illustrate the ability to handle basic arithmetic, the modulo ope
182
182
 
183
183
  ### 2. `simplify_algebraic_expression`
184
184
 
185
- Simplifies expressions and returns them in LaTeX format.
185
+ Simplifies expressions and returns them in LaTeX format. Optionally applies substitutions to variables within the expression before simplifying.
186
186
 
187
187
  - **Parameters:**
188
- - `expression` (str): A string of the expression to simplify.
188
+ - `expression` (str): A string representing the algebraic expression to simplify.
189
+ - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where keys are variable names and values are the numbers to substitute them with.
189
190
 
190
191
  - **Returns:**
191
- - `str`: Simplified expression in LaTeX.
192
+ - `str`: The simplified expression formatted as a LaTeX string.
192
193
 
193
- - **Example:**
194
+ - **Example Usage:**
194
195
 
195
196
  from rgwfuncs import simplify_algebraic_expression
197
+
198
+ # Example 1: Simplifying a polynomial expression without substitutions
196
199
  simplified_expr1 = simplify_algebraic_expression("2*x + 3*x")
197
200
  print(simplified_expr1) # Output: "5 x"
198
201
 
199
- simplified_expr2 = simplify_algebraic_expression("(np.diff(3*x**8)) / (np.diff(8*x**30) * 11*y**3)")
200
- print(simplified_expr2) # Output: "\frac{1}{110 x^{22} y^{3}}"
202
+ # Example 2: Simplifying a complex expression involving derivatives
203
+ simplified_expr2 = simplify_algebraic_expression(
204
+ "(np.diff(3*x**8)) / (np.diff(8*x**30) * 11*y**3)"
205
+ )
206
+ print(simplified_expr2) # Output: r"\frac{1}{110 x^{22} y^{3}}"
207
+
208
+ # Example 3: Simplifying with substitutions
209
+ simplified_expr3 = simplify_algebraic_expression("x**2 + y**2", subs={"x": 3, "y": 4})
210
+ print(simplified_expr3) # Output: "25"
211
+
212
+ # Example 4: Simplifying with partial substitution
213
+ simplified_expr4 = simplify_algebraic_expression("a*b + b", subs={"b": 2})
214
+ print(simplified_expr4) # Output: "a \cdot 2 + 2"
201
215
 
202
- These examples demonstrate simplification of polynomial expressions and more complex ratios involving derivatives.
216
+ These examples demonstrate the simplification of polynomial expressions, handling complex ratios involving derivatives, and applying variable substitutions before simplifying. The function handles expressions both with and without substitutions, providing flexibility in its usage.
203
217
 
204
218
  --------------------------------------------------------------------------------
205
219
 
@@ -252,6 +266,66 @@ Computes prime factors of a number and presents them in LaTeX format.
252
266
 
253
267
  --------------------------------------------------------------------------------
254
268
 
269
+ ### 5. `compute_matrix_operation`
270
+
271
+ Computes the results of 1D or 2D matrix operations and formats them as LaTeX strings.
272
+
273
+ - **Parameters:**
274
+ - `expression` (str): A string representing a sequence of matrix operations involving either 1D or 2D lists. Supported operations include addition (`+`), subtraction (`-`), multiplication (`*`), and division (`/`).
275
+
276
+ - **Returns:**
277
+ - `str`: The LaTeX-formatted string representation of the computed matrix, or an error message if the operations cannot be performed due to dimensional mismatches.
278
+
279
+ - **Example:**
280
+
281
+ from rgwfuncs import compute_matrix_operation
282
+
283
+ # Example with addition of 2D matrices
284
+ result = compute_matrix_operation("[[2, 6, 9], [1, 3, 5]] + [[1, 2, 3], [4, 5, 6]]")
285
+ print(result) # Output: \begin{bmatrix}3 & 8 & 12\\5 & 8 & 11\end{bmatrix}
286
+
287
+ # Example of mixed operations with 1D matrices treated as 2D
288
+ result = compute_matrix_operation("[3, 6, 9] + [1, 2, 3] - [2, 2, 2]")
289
+ print(result) # Output: \begin{bmatrix}2 & 6 & 10\end{bmatrix}
290
+
291
+ # Example with dimension mismatch
292
+ result = compute_matrix_operation("[[4, 3, 51]] + [[1, 1]]")
293
+ print(result) # Output: Operations between matrices must involve matrices of the same dimension
294
+
295
+ This function performs elementwise operations on both 1D and 2D matrices represented as Python lists and formats the result as a LaTeX string. It handles operations sequentially from left to right and gracefully handles dimension mismatches by returning a meaningful message. It utilizes Python's `ast.literal_eval` for safe and robust parsing.
296
+
297
+ --------------------------------------------------------------------------------
298
+
299
+ ### 6. `compute_ordered_series_operations`
300
+
301
+ Computes the result of operations on ordered series expressed as 1D lists, including the discrete difference operator `ddd`.
302
+
303
+ - **Parameters:**
304
+ - `expression` (str): A series operation expression. Supports operations such as "+", "-", "*", "/", and `ddd` for discrete differences.
305
+
306
+ - **Returns:**
307
+ - `str`: The string representation of the resultant series after performing operations, or an error message if series lengths do not match.
308
+
309
+ - **Example:**
310
+
311
+ from rgwfuncs import compute_ordered_series_operations
312
+
313
+ # Example with addition and discrete differences
314
+ result = compute_ordered_series_operations("ddd([2, 6, 9, 60]) + ddd([78, 79, 80])")
315
+ print(result) # Output: [4, 3, 51] + [1, 1]
316
+
317
+ # Example with elementwise subtraction
318
+ result = compute_ordered_series_operations("[10, 15, 21] - [5, 5, 5]")
319
+ print(result) # Output: [5, 10, 16]
320
+
321
+ # Example with length mismatch
322
+ result = compute_ordered_series_operations("[4, 3, 51] + [1, 1]")
323
+ print(result) # Output: Operations between ordered series must involve series of equal length
324
+
325
+ This function first applies the discrete difference operator to any series where applicable, then evaluates arithmetic operations between series. It returns a string representation of the result or an error message if the series lengths do not match. The function is robust, directly parsing and evaluating given series expressions with safety checks in place.
326
+
327
+ --------------------------------------------------------------------------------
328
+
255
329
  ## String Based Functions
256
330
 
257
331
  ### 1. send_telegram_message
@@ -156,24 +156,38 @@ These examples illustrate the ability to handle basic arithmetic, the modulo ope
156
156
 
157
157
  ### 2. `simplify_algebraic_expression`
158
158
 
159
- Simplifies expressions and returns them in LaTeX format.
159
+ Simplifies expressions and returns them in LaTeX format. Optionally applies substitutions to variables within the expression before simplifying.
160
160
 
161
161
  - **Parameters:**
162
- - `expression` (str): A string of the expression to simplify.
162
+ - `expression` (str): A string representing the algebraic expression to simplify.
163
+ - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where keys are variable names and values are the numbers to substitute them with.
163
164
 
164
165
  - **Returns:**
165
- - `str`: Simplified expression in LaTeX.
166
+ - `str`: The simplified expression formatted as a LaTeX string.
166
167
 
167
- - **Example:**
168
+ - **Example Usage:**
168
169
 
169
170
  from rgwfuncs import simplify_algebraic_expression
171
+
172
+ # Example 1: Simplifying a polynomial expression without substitutions
170
173
  simplified_expr1 = simplify_algebraic_expression("2*x + 3*x")
171
174
  print(simplified_expr1) # Output: "5 x"
172
175
 
173
- simplified_expr2 = simplify_algebraic_expression("(np.diff(3*x**8)) / (np.diff(8*x**30) * 11*y**3)")
174
- print(simplified_expr2) # Output: "\frac{1}{110 x^{22} y^{3}}"
176
+ # Example 2: Simplifying a complex expression involving derivatives
177
+ simplified_expr2 = simplify_algebraic_expression(
178
+ "(np.diff(3*x**8)) / (np.diff(8*x**30) * 11*y**3)"
179
+ )
180
+ print(simplified_expr2) # Output: r"\frac{1}{110 x^{22} y^{3}}"
181
+
182
+ # Example 3: Simplifying with substitutions
183
+ simplified_expr3 = simplify_algebraic_expression("x**2 + y**2", subs={"x": 3, "y": 4})
184
+ print(simplified_expr3) # Output: "25"
185
+
186
+ # Example 4: Simplifying with partial substitution
187
+ simplified_expr4 = simplify_algebraic_expression("a*b + b", subs={"b": 2})
188
+ print(simplified_expr4) # Output: "a \cdot 2 + 2"
175
189
 
176
- These examples demonstrate simplification of polynomial expressions and more complex ratios involving derivatives.
190
+ These examples demonstrate the simplification of polynomial expressions, handling complex ratios involving derivatives, and applying variable substitutions before simplifying. The function handles expressions both with and without substitutions, providing flexibility in its usage.
177
191
 
178
192
  --------------------------------------------------------------------------------
179
193
 
@@ -226,6 +240,66 @@ Computes prime factors of a number and presents them in LaTeX format.
226
240
 
227
241
  --------------------------------------------------------------------------------
228
242
 
243
+ ### 5. `compute_matrix_operation`
244
+
245
+ Computes the results of 1D or 2D matrix operations and formats them as LaTeX strings.
246
+
247
+ - **Parameters:**
248
+ - `expression` (str): A string representing a sequence of matrix operations involving either 1D or 2D lists. Supported operations include addition (`+`), subtraction (`-`), multiplication (`*`), and division (`/`).
249
+
250
+ - **Returns:**
251
+ - `str`: The LaTeX-formatted string representation of the computed matrix, or an error message if the operations cannot be performed due to dimensional mismatches.
252
+
253
+ - **Example:**
254
+
255
+ from rgwfuncs import compute_matrix_operation
256
+
257
+ # Example with addition of 2D matrices
258
+ result = compute_matrix_operation("[[2, 6, 9], [1, 3, 5]] + [[1, 2, 3], [4, 5, 6]]")
259
+ print(result) # Output: \begin{bmatrix}3 & 8 & 12\\5 & 8 & 11\end{bmatrix}
260
+
261
+ # Example of mixed operations with 1D matrices treated as 2D
262
+ result = compute_matrix_operation("[3, 6, 9] + [1, 2, 3] - [2, 2, 2]")
263
+ print(result) # Output: \begin{bmatrix}2 & 6 & 10\end{bmatrix}
264
+
265
+ # Example with dimension mismatch
266
+ result = compute_matrix_operation("[[4, 3, 51]] + [[1, 1]]")
267
+ print(result) # Output: Operations between matrices must involve matrices of the same dimension
268
+
269
+ This function performs elementwise operations on both 1D and 2D matrices represented as Python lists and formats the result as a LaTeX string. It handles operations sequentially from left to right and gracefully handles dimension mismatches by returning a meaningful message. It utilizes Python's `ast.literal_eval` for safe and robust parsing.
270
+
271
+ --------------------------------------------------------------------------------
272
+
273
+ ### 6. `compute_ordered_series_operations`
274
+
275
+ Computes the result of operations on ordered series expressed as 1D lists, including the discrete difference operator `ddd`.
276
+
277
+ - **Parameters:**
278
+ - `expression` (str): A series operation expression. Supports operations such as "+", "-", "*", "/", and `ddd` for discrete differences.
279
+
280
+ - **Returns:**
281
+ - `str`: The string representation of the resultant series after performing operations, or an error message if series lengths do not match.
282
+
283
+ - **Example:**
284
+
285
+ from rgwfuncs import compute_ordered_series_operations
286
+
287
+ # Example with addition and discrete differences
288
+ result = compute_ordered_series_operations("ddd([2, 6, 9, 60]) + ddd([78, 79, 80])")
289
+ print(result) # Output: [4, 3, 51] + [1, 1]
290
+
291
+ # Example with elementwise subtraction
292
+ result = compute_ordered_series_operations("[10, 15, 21] - [5, 5, 5]")
293
+ print(result) # Output: [5, 10, 16]
294
+
295
+ # Example with length mismatch
296
+ result = compute_ordered_series_operations("[4, 3, 51] + [1, 1]")
297
+ print(result) # Output: Operations between ordered series must involve series of equal length
298
+
299
+ This function first applies the discrete difference operator to any series where applicable, then evaluates arithmetic operations between series. It returns a string representation of the result or an error message if the series lengths do not match. The function is robust, directly parsing and evaluating given series expressions with safety checks in place.
300
+
301
+ --------------------------------------------------------------------------------
302
+
229
303
  ## String Based Functions
230
304
 
231
305
  ### 1. send_telegram_message
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rgwfuncs"
7
- version = "0.0.26"
7
+ version = "0.0.28"
8
8
  authors = [
9
9
  { name = "Ryan Gerard Wilson", email = "ryangerardwilson@gmail.com" },
10
10
  ]
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = rgwfuncs
3
- version = 0.0.26
3
+ version = 0.0.28
4
4
  author = Ryan Gerard Wilson
5
5
  author_email = ryangerardwilson@gmail.com
6
6
  description = A functional programming paradigm for mathematical modelling and data science
@@ -1,7 +1,7 @@
1
1
  # This file is automatically generated
2
2
  # Dynamically importing functions from modules
3
3
 
4
- from .algebra_lib import compute_algebraic_expression, get_prime_factors_latex, simplify_algebraic_expression, solve_algebraic_expression
4
+ from .algebra_lib import compute_algebraic_expression, compute_matrix_operation, compute_ordered_series_operation, get_prime_factors_latex, simplify_algebraic_expression, solve_algebraic_expression
5
5
  from .df_lib import append_columns, append_percentile_classification_column, append_ranged_classification_column, append_ranged_date_classification_column, append_rows, append_xgb_labels, append_xgb_logistic_regression_predictions, append_xgb_regression_predictions, bag_union_join, bottom_n_unique_values, cascade_sort, delete_rows, drop_duplicates, drop_duplicates_retain_first, drop_duplicates_retain_last, filter_dataframe, filter_indian_mobiles, first_n_rows, from_raw_data, insert_dataframe_in_sqlite_database, last_n_rows, left_join, limit_dataframe, load_data_from_path, load_data_from_query, load_data_from_sqlite_path, mask_against_dataframe, mask_against_dataframe_converse, numeric_clean, order_columns, print_correlation, print_dataframe, print_memory_usage, print_n_frequency_cascading, print_n_frequency_linear, rename_columns, retain_columns, right_join, send_data_to_email, send_data_to_slack, send_dataframe_via_telegram, sync_dataframe_to_sqlite_database, top_n_unique_values, union_join, update_rows
6
6
  from .docs_lib import docs
7
7
  from .str_lib import send_telegram_message
@@ -1,6 +1,7 @@
1
1
  import re
2
2
  import math
3
3
  import ast
4
+ # import numpy as np
4
5
  from sympy import symbols, latex, simplify, solve, diff, Expr
5
6
  from sympy.parsing.sympy_parser import parse_expr
6
7
  from typing import Tuple, List, Dict, Optional
@@ -35,7 +36,10 @@ def compute_algebraic_expression(expression: str) -> float:
35
36
  raise ValueError(f"Error computing expression: {e}")
36
37
 
37
38
 
38
- def simplify_algebraic_expression(expression: str) -> str:
39
+ def simplify_algebraic_expression(
40
+ expression: str,
41
+ subs: Optional[Dict[str, float]] = None
42
+ ) -> str:
39
43
  """
40
44
  Simplifies an algebraic expression and returns it in LaTeX format.
41
45
 
@@ -44,11 +48,17 @@ def simplify_algebraic_expression(expression: str) -> str:
44
48
 
45
49
  Parameters:
46
50
  expression (str): The algebraic expression to simplify.
51
+ subs (Optional[Dict[str, float]]): An optional dictionary of substitutions for variables
52
+ in the expression.
47
53
 
48
54
  Returns:
49
55
  str: The simplified expression represented as a LaTeX string.
56
+
57
+ Raises:
58
+ ValueError: If the expression cannot be simplified due to errors in expression or parameters.
50
59
  """
51
60
 
61
+
52
62
  def recursive_parse_function_call(
53
63
  func_call: str, prefix: str, sym_vars: Dict[str, Expr]) -> Tuple[str, List[Expr]]:
54
64
  # print(f"Parsing function call: {func_call}")
@@ -177,13 +187,18 @@ def simplify_algebraic_expression(expression: str) -> str:
177
187
  # print("Level 2 processed_expression:", processed_expression)
178
188
 
179
189
  try:
180
- if processed_expression.startswith(
181
- '[') and processed_expression.endswith(']'):
182
- return processed_expression
183
-
190
+ # Parse the expression
184
191
  expr = parse_expr(processed_expression, local_dict=sym_vars)
192
+
193
+ # Apply substitutions if provided
194
+ if subs:
195
+ subs_symbols = {symbols(k): v for k, v in subs.items()}
196
+ expr = expr.subs(subs_symbols)
197
+
198
+ # Simplify the expression
185
199
  final_result = simplify(expr)
186
200
 
201
+ # Convert the result to LaTeX format
187
202
  if final_result.free_symbols:
188
203
  latex_result = latex(final_result)
189
204
  return latex_result
@@ -195,7 +210,10 @@ def simplify_algebraic_expression(expression: str) -> str:
195
210
 
196
211
 
197
212
  def solve_algebraic_expression(
198
- expression: str, variable: str, subs: Optional[Dict[str, float]] = None) -> str:
213
+ expression: str,
214
+ variable: str,
215
+ subs: Optional[Dict[str, float]] = None
216
+ ) -> str:
199
217
  """
200
218
  Solves an algebraic equation for a specified variable and returns solutions in LaTeX format.
201
219
 
@@ -242,6 +260,198 @@ def solve_algebraic_expression(
242
260
  raise ValueError(f"Error solving the expression: {e}")
243
261
 
244
262
 
263
+ def compute_matrix_operation(expression: str) -> str:
264
+ """
265
+ Computes the result of a matrix-like operation on 1D or 2D list inputs and returns it as a LaTeX string.
266
+
267
+ Evaluates an operation where lists are treated as matrices, performs operations on them sequentially, and
268
+ returns the result formatted as a LaTeX-style string.
269
+
270
+ Parameters:
271
+ expression (str): The matrix operation expression to compute. Example format includes operations such as "+", "-", "*", "/".
272
+
273
+ Returns:
274
+ str: The LaTeX-formatted string representation of the result or a message indicating an error in dimensions.
275
+ """
276
+
277
+ def elementwise_operation(matrix1: List[List[float]], matrix2: List[List[float]], operation: str) -> List[List[float]]:
278
+ if len(matrix1) != len(matrix2) or any(len(row1) != len(row2) for row1, row2 in zip(matrix1, matrix2)):
279
+ return "Operations between matrices must involve matrices of the same dimension"
280
+
281
+ if operation == '+':
282
+ return [[a + b for a, b in zip(row1, row2)] for row1, row2 in zip(matrix1, matrix2)]
283
+ elif operation == '-':
284
+ return [[a - b for a, b in zip(row1, row2)] for row1, row2 in zip(matrix1, matrix2)]
285
+ elif operation == '*':
286
+ return [[a * b for a, b in zip(row1, row2)] for row1, row2 in zip(matrix1, matrix2)]
287
+ elif operation == '/':
288
+ return [[a / b for a, b in zip(row1, row2) if b != 0] for row1, row2 in zip(matrix1, matrix2)]
289
+ else:
290
+ return f"Unsupported operation {operation}"
291
+
292
+ try:
293
+ # Use a stack-based method to properly parse matrices
294
+ elements = []
295
+ buffer = ''
296
+ bracket_level = 0
297
+ operators = set('+-*/')
298
+
299
+ for char in expression:
300
+ if char == '[':
301
+ if bracket_level == 0 and buffer.strip():
302
+ elements.append(buffer.strip())
303
+ buffer = ''
304
+ bracket_level += 1
305
+ elif char == ']':
306
+ bracket_level -= 1
307
+ if bracket_level == 0:
308
+ buffer += char
309
+ elements.append(buffer.strip())
310
+ buffer = ''
311
+ continue
312
+ if bracket_level == 0 and char in operators:
313
+ if buffer.strip():
314
+ elements.append(buffer.strip())
315
+ buffer = ''
316
+ elements.append(char)
317
+ else:
318
+ buffer += char
319
+
320
+ if buffer.strip():
321
+ elements.append(buffer.strip())
322
+
323
+ result = ast.literal_eval(elements[0])
324
+
325
+ if not any(isinstance(row, list) for row in result):
326
+ result = [result] # Convert 1D matrix to 2D
327
+
328
+ i = 1
329
+ while i < len(elements):
330
+ operation = elements[i]
331
+ matrix = ast.literal_eval(elements[i + 1])
332
+
333
+ if not any(isinstance(row, list) for row in matrix):
334
+ matrix = [matrix]
335
+
336
+ operation_result = elementwise_operation(result, matrix, operation)
337
+
338
+ # Check if the operation resulted in an error message
339
+ if isinstance(operation_result, str):
340
+ return operation_result
341
+
342
+ result = operation_result
343
+ i += 2
344
+
345
+ # Create a LaTeX-style matrix representation
346
+ matrix_entries = '\\\\'.join(' & '.join(str(x) for x in row) for row in result)
347
+ return r"\begin{bmatrix}" + f"{matrix_entries}" + r"\end{bmatrix}"
348
+
349
+ except Exception as e:
350
+ return f"Error computing matrix operation: {e}"
351
+
352
+
353
+ def compute_ordered_series_operation(expression: str) -> str:
354
+ """
355
+ Computes the result of operations on ordered series expressed as 1D lists, including discrete difference (ddd),
356
+ and returns it as a string.
357
+
358
+ The function first applies the discrete difference operator to any series where applicable, then evaluates
359
+ arithmetic operations between series.
360
+
361
+ Parameters:
362
+ expression (str): The series operation expression to compute. Includes operations "+", "-", "*", "/", and "ddd".
363
+
364
+ Returns:
365
+ str: The string representation of the resultant series after performing operations, or an error message
366
+ if the series lengths do not match.
367
+
368
+ Raises:
369
+ ValueError: If the expression cannot be evaluated.
370
+ """
371
+
372
+ def elementwise_operation(series1: List[float], series2: List[float], operation: str) -> List[float]:
373
+ if len(series1) != len(series2):
374
+ return "Operations between ordered series must involve series of equal length"
375
+
376
+ if operation == '+':
377
+ return [a + b for a, b in zip(series1, series2)]
378
+ elif operation == '-':
379
+ return [a - b for a, b in zip(series1, series2)]
380
+ elif operation == '*':
381
+ return [a * b for a, b in zip(series1, series2)]
382
+ elif operation == '/':
383
+ return [a / b for a, b in zip(series1, series2) if b != 0]
384
+ else:
385
+ return f"Unsupported operation {operation}"
386
+
387
+ def discrete_difference(series: list) -> list:
388
+ """Computes the discrete difference of a series."""
389
+ return [series[i + 1] - series[i] for i in range(len(series) - 1)]
390
+
391
+ try:
392
+ # First, apply the discrete difference operator where applicable
393
+ pattern = r'ddd\((\[[^\]]*\])\)'
394
+ matches = re.findall(pattern, expression)
395
+
396
+ for match in matches:
397
+ if match.strip() == '[]':
398
+ result_series = [] # Handle the empty list case
399
+ else:
400
+ series = ast.literal_eval(match)
401
+ result_series = discrete_difference(series)
402
+ expression = expression.replace(f'ddd({match})', str(result_series))
403
+
404
+ # Now parse and evaluate the full expression with basic operations
405
+ elements = []
406
+ buffer = ''
407
+ bracket_level = 0
408
+ operators = set('+-*/')
409
+
410
+ for char in expression:
411
+ if char == '[':
412
+ if bracket_level == 0 and buffer.strip():
413
+ elements.append(buffer.strip())
414
+ buffer = ''
415
+ bracket_level += 1
416
+ elif char == ']':
417
+ bracket_level -= 1
418
+ if bracket_level == 0:
419
+ buffer += char
420
+ elements.append(buffer.strip())
421
+ buffer = ''
422
+ continue
423
+ if bracket_level == 0 and char in operators:
424
+ if buffer.strip():
425
+ elements.append(buffer.strip())
426
+ buffer = ''
427
+ elements.append(char)
428
+ else:
429
+ buffer += char
430
+
431
+ if buffer.strip():
432
+ elements.append(buffer.strip())
433
+
434
+ result = ast.literal_eval(elements[0])
435
+
436
+ i = 1
437
+ while i < len(elements):
438
+ operation = elements[i]
439
+ series = ast.literal_eval(elements[i + 1])
440
+ operation_result = elementwise_operation(result, series, operation)
441
+
442
+ # Check if the operation resulted in an error message
443
+ if isinstance(operation_result, str):
444
+ return operation_result
445
+
446
+ result = operation_result
447
+ i += 2
448
+
449
+ return str(result)
450
+
451
+ except Exception as e:
452
+ return f"Error computing ordered series operation: {e}"
453
+
454
+
245
455
  def get_prime_factors_latex(n: int) -> str:
246
456
  """
247
457
  Computes the prime factors of a number and returns the factorization as a LaTeX string.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rgwfuncs
3
- Version: 0.0.26
3
+ Version: 0.0.28
4
4
  Summary: A functional programming paradigm for mathematical modelling and data science
5
5
  Home-page: https://github.com/ryangerardwilson/rgwfunc
6
6
  Author: Ryan Gerard Wilson
@@ -182,24 +182,38 @@ These examples illustrate the ability to handle basic arithmetic, the modulo ope
182
182
 
183
183
  ### 2. `simplify_algebraic_expression`
184
184
 
185
- Simplifies expressions and returns them in LaTeX format.
185
+ Simplifies expressions and returns them in LaTeX format. Optionally applies substitutions to variables within the expression before simplifying.
186
186
 
187
187
  - **Parameters:**
188
- - `expression` (str): A string of the expression to simplify.
188
+ - `expression` (str): A string representing the algebraic expression to simplify.
189
+ - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where keys are variable names and values are the numbers to substitute them with.
189
190
 
190
191
  - **Returns:**
191
- - `str`: Simplified expression in LaTeX.
192
+ - `str`: The simplified expression formatted as a LaTeX string.
192
193
 
193
- - **Example:**
194
+ - **Example Usage:**
194
195
 
195
196
  from rgwfuncs import simplify_algebraic_expression
197
+
198
+ # Example 1: Simplifying a polynomial expression without substitutions
196
199
  simplified_expr1 = simplify_algebraic_expression("2*x + 3*x")
197
200
  print(simplified_expr1) # Output: "5 x"
198
201
 
199
- simplified_expr2 = simplify_algebraic_expression("(np.diff(3*x**8)) / (np.diff(8*x**30) * 11*y**3)")
200
- print(simplified_expr2) # Output: "\frac{1}{110 x^{22} y^{3}}"
202
+ # Example 2: Simplifying a complex expression involving derivatives
203
+ simplified_expr2 = simplify_algebraic_expression(
204
+ "(np.diff(3*x**8)) / (np.diff(8*x**30) * 11*y**3)"
205
+ )
206
+ print(simplified_expr2) # Output: r"\frac{1}{110 x^{22} y^{3}}"
207
+
208
+ # Example 3: Simplifying with substitutions
209
+ simplified_expr3 = simplify_algebraic_expression("x**2 + y**2", subs={"x": 3, "y": 4})
210
+ print(simplified_expr3) # Output: "25"
211
+
212
+ # Example 4: Simplifying with partial substitution
213
+ simplified_expr4 = simplify_algebraic_expression("a*b + b", subs={"b": 2})
214
+ print(simplified_expr4) # Output: "a \cdot 2 + 2"
201
215
 
202
- These examples demonstrate simplification of polynomial expressions and more complex ratios involving derivatives.
216
+ These examples demonstrate the simplification of polynomial expressions, handling complex ratios involving derivatives, and applying variable substitutions before simplifying. The function handles expressions both with and without substitutions, providing flexibility in its usage.
203
217
 
204
218
  --------------------------------------------------------------------------------
205
219
 
@@ -252,6 +266,66 @@ Computes prime factors of a number and presents them in LaTeX format.
252
266
 
253
267
  --------------------------------------------------------------------------------
254
268
 
269
+ ### 5. `compute_matrix_operation`
270
+
271
+ Computes the results of 1D or 2D matrix operations and formats them as LaTeX strings.
272
+
273
+ - **Parameters:**
274
+ - `expression` (str): A string representing a sequence of matrix operations involving either 1D or 2D lists. Supported operations include addition (`+`), subtraction (`-`), multiplication (`*`), and division (`/`).
275
+
276
+ - **Returns:**
277
+ - `str`: The LaTeX-formatted string representation of the computed matrix, or an error message if the operations cannot be performed due to dimensional mismatches.
278
+
279
+ - **Example:**
280
+
281
+ from rgwfuncs import compute_matrix_operation
282
+
283
+ # Example with addition of 2D matrices
284
+ result = compute_matrix_operation("[[2, 6, 9], [1, 3, 5]] + [[1, 2, 3], [4, 5, 6]]")
285
+ print(result) # Output: \begin{bmatrix}3 & 8 & 12\\5 & 8 & 11\end{bmatrix}
286
+
287
+ # Example of mixed operations with 1D matrices treated as 2D
288
+ result = compute_matrix_operation("[3, 6, 9] + [1, 2, 3] - [2, 2, 2]")
289
+ print(result) # Output: \begin{bmatrix}2 & 6 & 10\end{bmatrix}
290
+
291
+ # Example with dimension mismatch
292
+ result = compute_matrix_operation("[[4, 3, 51]] + [[1, 1]]")
293
+ print(result) # Output: Operations between matrices must involve matrices of the same dimension
294
+
295
+ This function performs elementwise operations on both 1D and 2D matrices represented as Python lists and formats the result as a LaTeX string. It handles operations sequentially from left to right and gracefully handles dimension mismatches by returning a meaningful message. It utilizes Python's `ast.literal_eval` for safe and robust parsing.
296
+
297
+ --------------------------------------------------------------------------------
298
+
299
+ ### 6. `compute_ordered_series_operations`
300
+
301
+ Computes the result of operations on ordered series expressed as 1D lists, including the discrete difference operator `ddd`.
302
+
303
+ - **Parameters:**
304
+ - `expression` (str): A series operation expression. Supports operations such as "+", "-", "*", "/", and `ddd` for discrete differences.
305
+
306
+ - **Returns:**
307
+ - `str`: The string representation of the resultant series after performing operations, or an error message if series lengths do not match.
308
+
309
+ - **Example:**
310
+
311
+ from rgwfuncs import compute_ordered_series_operations
312
+
313
+ # Example with addition and discrete differences
314
+ result = compute_ordered_series_operations("ddd([2, 6, 9, 60]) + ddd([78, 79, 80])")
315
+ print(result) # Output: [4, 3, 51] + [1, 1]
316
+
317
+ # Example with elementwise subtraction
318
+ result = compute_ordered_series_operations("[10, 15, 21] - [5, 5, 5]")
319
+ print(result) # Output: [5, 10, 16]
320
+
321
+ # Example with length mismatch
322
+ result = compute_ordered_series_operations("[4, 3, 51] + [1, 1]")
323
+ print(result) # Output: Operations between ordered series must involve series of equal length
324
+
325
+ This function first applies the discrete difference operator to any series where applicable, then evaluates arithmetic operations between series. It returns a string representation of the result or an error message if the series lengths do not match. The function is robust, directly parsing and evaluating given series expressions with safety checks in place.
326
+
327
+ --------------------------------------------------------------------------------
328
+
255
329
  ## String Based Functions
256
330
 
257
331
  ### 1. send_telegram_message
@@ -0,0 +1,122 @@
1
+ import sys
2
+ import os
3
+ import math
4
+
5
+ # flake8: noqa: E402
6
+ # Allow the following import statement to be AFTER sys.path modifications
7
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
8
+
9
+ from src.rgwfuncs.algebra_lib import (
10
+ compute_algebraic_expression,
11
+ simplify_algebraic_expression,
12
+ solve_algebraic_expression,
13
+ compute_matrix_operation,
14
+ compute_ordered_series_operation,
15
+ get_prime_factors_latex)
16
+
17
+
18
+ def test_compute_algebraic_expression():
19
+ test_cases = [
20
+ ("2 + 2", 4.0),
21
+ ("5 - 3", 2.0),
22
+ ("3 * 3", 9.0),
23
+ ("8 / 2", 4.0),
24
+ ("10 % 3", 1.0),
25
+ ("math.gcd(36, 60) * math.sin(math.radians(45)) * 10000", 84852.8137423857),
26
+ # ("np.diff([2,6,9,60])", r"\left[\begin{matrix}4\\3\\51\end{matrix}\right]"),
27
+ ]
28
+
29
+ for input_data, expected_output in test_cases:
30
+ result = compute_algebraic_expression(input_data)
31
+ assert math.isclose(result, expected_output, rel_tol=1e-9), f"Failed for {input_data}, got {result}"
32
+
33
+ def test_simplify_algebraic_expression():
34
+ test_cases = [
35
+ # Without substitutions
36
+ (("(np.diff(3*x**8)) / (np.diff(8*x**30) * 11*y**3)", None), r"\frac{1}{110 x^{22} y^{3}}"),
37
+
38
+ # With substitutions
39
+ (("x**2 + y**2", {"x": 3, "y": 4}), "25"),
40
+ (("a*b + b", {"b": 2}), r"2 a + 2"), # Assumes no simplification of `a*b`
41
+ (("(x**2 + y**2 + z**2)", {"x": 1, "y": 0, "z": 0}), "1")
42
+ ]
43
+
44
+ for (expression, subs), expected_output in test_cases:
45
+ output = simplify_algebraic_expression(expression, subs)
46
+ assert output == expected_output, (
47
+ f"Test failed for expression: {expression} with substitutions: {subs}. "
48
+ f"Expected {expected_output}, got {output}"
49
+ )
50
+
51
+
52
+ def test_solve_algebraic_expression():
53
+ test_cases = [
54
+ # Test case with substitutions
55
+ (
56
+ ("a*x**2 + b*x + c", "x", {"a": 3, "b": 7, "c": 5}),
57
+ r"\left[-7/6 - sqrt(11)*I/6, -7/6 + sqrt(11)*I/6\right]"
58
+ ),
59
+ ]
60
+
61
+ for (expression, variable, subs), expected_output in test_cases:
62
+ assert solve_algebraic_expression(expression, variable, subs) == expected_output
63
+
64
+
65
+ def test_compute_matrix_operation():
66
+ test_cases = [
67
+ ("[[2, 6, 9],[1, 3, 5]] + [[1, 2, 3],[4, 5, 6]]", r"\begin{bmatrix}3 & 8 & 12\\5 & 8 & 11\end{bmatrix}"),
68
+ ("[[10, 10, 10],[2, 4, 6]] - [[5, 3, 2],[1, 2, 1]]", r"\begin{bmatrix}5 & 7 & 8\\1 & 2 & 5\end{bmatrix}"),
69
+ ("[[2, 4],[6, 8]] * [[1, 0.5],[2, 0.25]]", r"\begin{bmatrix}2 & 2.0\\12 & 2.0\end{bmatrix}"),
70
+ ("[[8, 16],[32, 64]] / [[2, 2],[8, 16]]", r"\begin{bmatrix}4.0 & 8.0\\4.0 & 4.0\end{bmatrix}"),
71
+ ("[[2, 6, 9], [1, 3, 5]] + [[1, 2, 3], [4, 5, 6]] - [[1, 1, 1], [1, 1, 1]]", r"\begin{bmatrix}2 & 7 & 11\\4 & 7 & 10\end{bmatrix}"),
72
+ ("[2, 6, 9] + [1, 2, 3] - [1, 1, 1]", r"\begin{bmatrix}2 & 7 & 11\end{bmatrix}"),
73
+ ("[[1, 2], [3, 4]] + [[2, 3], [4, 5]] + [[1, 1], [1, 1]]", r"\begin{bmatrix}4 & 6\\8 & 10\end{bmatrix}"),
74
+ ("[3, 6, 9] - [1, 2, 3] + [5, 5, 5]", r"\begin{bmatrix}7 & 9 & 11\end{bmatrix}"),
75
+ ("[3, 6, 9] - [1, 2, 3, 4]", r"Operations between matrices must involve matrices of the same dimension"),
76
+
77
+ # Edge cases
78
+ ("[]", r"\begin{bmatrix}\end{bmatrix}"), # Empty list
79
+ ("[5]", r"\begin{bmatrix}5\end{bmatrix}"), # Single-element list
80
+ ]
81
+
82
+ for input_data, expected_output in test_cases:
83
+ result = compute_matrix_operation(input_data)
84
+ assert result == expected_output, f"Failed for {input_data}, got {result}"
85
+
86
+ # Example test function
87
+
88
+
89
+ def test_compute_ordered_series_operations():
90
+ test_cases = [
91
+ ("[2, 6, 9] + [1, 2, 3]", "[3, 8, 12]"),
92
+ ("[10, 15, 21] - [5, 5, 5]", "[5, 10, 16]"),
93
+ ("[2, 4, 6] * [1, 2, 3]", "[2, 8, 18]"),
94
+ ("[8, 16, 32] / [2, 2, 8]", "[4.0, 8.0, 4.0]"),
95
+ ("ddd([2, 6, 9, 60]) + ddd([78, 79, 80])", "Operations between ordered series must involve series of equal length"),
96
+ ("ddd([1, 3, 6, 10]) - ddd([0, 1, 1, 2])", "[1, 3, 3]"),
97
+
98
+ # Edge cases
99
+ ("ddd([1])", "[]"), # Single-element list, becomes empty
100
+ ("ddd([])", "[]"), # Empty list case
101
+ ("[5]", "[5]"), # Single-element list, unchanged
102
+ ("[]", "[]"), # Empty list
103
+ ("[4, 3, 51] + [1, 1]", "Operations between ordered series must involve series of equal length"), # Test unequal lengths
104
+ ]
105
+
106
+ for input_data, expected_output in test_cases:
107
+ result = compute_ordered_series_operation(input_data)
108
+ assert result == expected_output, f"Failed for {input_data}, got {result}"
109
+
110
+
111
+ def test_get_prime_factors_latex():
112
+ test_cases = [
113
+ (100, "2^{2} \\cdot 5^{2}"),
114
+ (60, "2^{2} \\cdot 3 \\cdot 5"),
115
+ (45, "3^{2} \\cdot 5"),
116
+ (1, ""), # Handle case with 1, which has no prime factors
117
+ (17, "17") # Prime number itself
118
+ ]
119
+
120
+ for n, expected_output in test_cases:
121
+ result = get_prime_factors_latex(n)
122
+ assert result == expected_output, f"Failed for {n}, got {result}"
@@ -1,59 +0,0 @@
1
- from src.rgwfuncs.algebra_lib import compute_algebraic_expression, simplify_algebraic_expression, solve_algebraic_expression, get_prime_factors_latex
2
- import sys
3
- import os
4
- import math
5
-
6
- # flake8: noqa: E402
7
- # Allow the following import statement to be AFTER sys.path modifications
8
- sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
9
-
10
-
11
- def test_compute_algebraic_expression():
12
- test_cases = [
13
- ("2 + 2", 4.0),
14
- ("5 - 3", 2.0),
15
- ("3 * 3", 9.0),
16
- ("8 / 2", 4.0),
17
- ("10 % 3", 1.0),
18
- ("math.gcd(36, 60) * math.sin(math.radians(45)) * 10000", 84852.8137423857),
19
- ]
20
-
21
- for input_data, expected_output in test_cases:
22
- result = compute_algebraic_expression(input_data)
23
- assert math.isclose(result, expected_output, rel_tol=1e-9), f"Failed for {input_data}, got {result}"
24
-
25
-
26
- def test_simplify_algebraic_expression():
27
- test_cases = [
28
- ("(np.diff(3*x**8)) / (np.diff(8*x**30) * 11*y**3)", r"\frac{1}{110 x^{22} y^{3}}"),
29
- ]
30
-
31
- for input_data, expected_output in test_cases:
32
- assert simplify_algebraic_expression(input_data) == expected_output
33
-
34
-
35
- def test_solve_algebraic_expression():
36
- test_cases = [
37
- # Test case with substitutions
38
- (
39
- ("a*x**2 + b*x + c", "x", {"a": 3, "b": 7, "c": 5}),
40
- r"\left[-7/6 - sqrt(11)*I/6, -7/6 + sqrt(11)*I/6\right]"
41
- ),
42
- ]
43
-
44
- for (expression, variable, subs), expected_output in test_cases:
45
- assert solve_algebraic_expression(expression, variable, subs) == expected_output
46
-
47
-
48
- def test_get_prime_factors_latex():
49
- test_cases = [
50
- (100, "2^{2} \\cdot 5^{2}"),
51
- (60, "2^{2} \\cdot 3 \\cdot 5"),
52
- (45, "3^{2} \\cdot 5"),
53
- (1, ""), # Handle case with 1, which has no prime factors
54
- (17, "17") # Prime number itself
55
- ]
56
-
57
- for n, expected_output in test_cases:
58
- result = get_prime_factors_latex(n)
59
- assert result == expected_output, f"Failed for {n}, got {result}"
File without changes