rgwfuncs 0.0.50__tar.gz → 0.0.53__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rgwfuncs
3
- Version: 0.0.50
3
+ Version: 0.0.53
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
@@ -370,17 +370,17 @@ Converts a polynomial expression written in Python syntax to a LaTeX formatted s
370
370
 
371
371
  Expands a polynomial expression written in Python syntax and converts it into a LaTeX formatted string. This function takes algebraic expressions provided as strings using Python's syntax, applies polynomial expansion through SymPy, and translates them into LaTeX representations, suitable for academic or professional documentation. It supports expressions with named variables and provides an option to substitute specific values into the expression before expansion.
372
372
 
373
- - Parameters:
373
+ Parameters:
374
374
  - `expression` (str): The algebraic expression to expand and convert to LaTeX. This string should be formatted using Python syntax acceptable by SymPy.
375
375
  - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers with which to substitute those variables before expanding.
376
376
 
377
- - Returns:
377
+ Returns:
378
378
  - `str`: The LaTeX formatted string of the expanded expression.
379
379
 
380
- - Raises:
380
+ Raises:
381
381
  - `ValueError`: If the expression cannot be parsed due to syntax errors.
382
382
 
383
- - Example:
383
+ Example:
384
384
 
385
385
  from rgwfuncs import expand_polynomial_expression
386
386
 
@@ -406,17 +406,17 @@ Expands a polynomial expression written in Python syntax and converts it into a
406
406
 
407
407
  Factors a polynomial expression written in Python syntax and converts it into a LaTeX formatted string. This function parses an algebraic expression, performs polynomial factoring using SymPy, and converts the factored expression into a LaTeX representation, ideal for academic or professional use. Optional substitutions can be made before factoring.
408
408
 
409
- - Parameters:
409
+ Parameters:
410
410
  - `expression` (str): The polynomial expression to factor and convert to LaTeX. This should be a valid expression formatted using Python syntax.
411
411
  - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions. The keys are variable names in the expression, and the values are numbers that replace these variables.
412
412
 
413
- - Returns:
413
+ Returns:
414
414
  - `str`: The LaTeX formatted string representing the factored expression.
415
415
 
416
- - Raises:
416
+ Raises:
417
417
  - `ValueError`: If the expression cannot be parsed due to syntax errors.
418
418
 
419
- - Example:
419
+ Example:
420
420
 
421
421
  from rgwfuncs import factor_polynomial_expression
422
422
 
@@ -430,35 +430,7 @@ Factors a polynomial expression written in Python syntax and converts it into a
430
430
 
431
431
  --------------------------------------------------------------------------------
432
432
 
433
- ### 8. `cancel_polynomial_expression`
434
-
435
- Cancels common factors within a polynomial expression written in Python syntax and converts it to a LaTeX formatted string. This function parses an algebraic expression, cancels common factors using SymPy, and translates the reduced expression into a LaTeX representation. It can also accommodate optional substitutions to be made prior to simplification.
436
-
437
- - Parameters:
438
- - `expression` (str): The algebraic expression to simplify and convert to LaTeX. This string should be formatted using Python syntax.
439
- - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers to substitute.
440
-
441
- - Returns:
442
- - `str`: The LaTeX formatted string of the simplified expression. If the expression involves indeterminate forms due to operations like division by zero, a descriptive error message is returned instead.
443
-
444
- - Raises:
445
- - `ValueError`: If the expression cannot be parsed due to syntax errors or involves undefined operations, such as division by zero.
446
-
447
- - Example:
448
-
449
- from rgwfuncs import cancel_polynomial_expression
450
-
451
- # Cancel common factors within a polynomial expression
452
- latex_result1 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)")
453
- print(latex_result1) # Output: "x + 2"
454
-
455
- # Cancel with substituted values
456
- latex_result2 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)", {"x": 2})
457
- print(latex_result2) # Output: "Undefined result. This could be a division by zero error."
458
-
459
- --------------------------------------------------------------------------------
460
-
461
- ### 9. `simplify_polynomial_expression`
433
+ ### 8. `simplify_polynomial_expression`
462
434
 
463
435
  Simplifies an algebraic expression in polynomial form and returns it in LaTeX format. Takes an algebraic expression, in polynomial form, written in Python syntax and simplifies it. The result is returned as a LaTeX formatted string, suitable for academic or professional documentation.
464
436
 
@@ -469,7 +441,7 @@ Simplifies an algebraic expression in polynomial form and returns it in LaTeX fo
469
441
  • Returns:
470
442
  - `str`: The simplified expression formatted as a LaTeX string.
471
443
 
472
- • Example Usage:
444
+ • Example:
473
445
 
474
446
  from rgwfuncs import simplify_polynomial_expression
475
447
 
@@ -491,6 +463,34 @@ Simplifies an algebraic expression in polynomial form and returns it in LaTeX fo
491
463
 
492
464
  --------------------------------------------------------------------------------
493
465
 
466
+ ### 9. `cancel_polynomial_expression`
467
+
468
+ Cancels common factors within a polynomial expression written in Python syntax and converts it to a LaTeX formatted string. This function parses an algebraic expression, cancels common factors using SymPy, and translates the reduced expression into a LaTeX representation. It can also accommodate optional substitutions to be made prior to simplification.
469
+
470
+ • Parameters:
471
+ - `expression` (str): The algebraic expression to simplify and convert to LaTeX. This string should be formatted using Python syntax.
472
+ - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers to substitute.
473
+
474
+ • Returns:
475
+ - `str`: The LaTeX formatted string of the simplified expression. If the expression involves indeterminate forms due to operations like division by zero, a descriptive error message is returned instead.
476
+
477
+ • Raises:
478
+ - `ValueError`: If the expression cannot be parsed due to syntax errors or involves undefined operations, such as division by zero.
479
+
480
+ • Example:
481
+
482
+ from rgwfuncs import cancel_polynomial_expression
483
+
484
+ # Cancel common factors within a polynomial expression
485
+ latex_result1 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)")
486
+ print(latex_result1) # Output: "x + 2"
487
+
488
+ # Cancel with substituted values
489
+ latex_result2 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)", {"x": 2})
490
+ print(latex_result2) # Output: "Undefined result. This could be a division by zero error."
491
+
492
+ --------------------------------------------------------------------------------
493
+
494
494
  ### 10. `solve_homogeneous_polynomial_expression`
495
495
 
496
496
  Solves a homogeneous polynomial expression for a specified variable and returns solutions in LaTeX format. Assumes that the expression is homoegeneous (i.e. equal to zero), and solves for a designated variable. May optionally include substitutions for other variables in the equation. The solutions are provided as a LaTeX formatted string. The method solves equations for specified variables, with optional substitutions, returning LaTeX-formatted solutions.
@@ -514,6 +514,46 @@ Solves a homogeneous polynomial expression for a specified variable and returns
514
514
 
515
515
  --------------------------------------------------------------------------------
516
516
 
517
+ ### 11. `plot_polynomial_functions`
518
+
519
+ This function plots polynomial functions described by a list of expressions and their corresponding substitution dictionaries. It generates SVG markup of the plots, with options for specifying the domain, axis zoom, and legend display.
520
+
521
+ • Parameters:
522
+ - `functions` (`List[Dict[str, Dict[str, Any]]]`): A list of dictionaries, each containing:
523
+ - A key which is a string representing a Python/NumPy expression (e.g., `"x**2"`, `"np.diff(x,2)"`).
524
+ - A value which is a dictionary containing substitutions for the expression. Must include an `"x"` key, either as `"*"` for default domain or a NumPy array.
525
+ - `zoom` (`float`): Determines the numeric axis range from `-zoom` to `+zoom` for both x and y axes (default is `10.0`).
526
+ - `show_legend` (`bool`): Specifies whether to include a legend in the plot (default is `True`).
527
+ - `open_file` (`bool`): If saving to path is not desireable, opens the svg as a temp file, else opens the file from the actual location using the system's default viewer (defaults to False).
528
+ - `save_path` (`Optional[str]`): If specified, saves the output string as a .svg at the indicated path (defaults to None).
529
+
530
+ • Returns:
531
+ - `str`: The raw SVG markup of the resulting plot.
532
+
533
+ • Example:
534
+
535
+ from rgwfuncs import plot_polynomial_functions
536
+
537
+ # Generate the SVG
538
+ plot_svg_string = plot_polynomial_functions(
539
+ functions=[
540
+ {"x**2": {"x": "*"}}, # Single expression, "*" means plot all discernable points
541
+ {"x**2/(2 + a) + a": {"x": np.linspace(-3, 4, 101), "a": 1.23}},
542
+ {"np.diff(x**3, 2)": {"x": np.linspace(-2, 2, 10)}}
543
+ ],
544
+ zoom=2
545
+ )
546
+
547
+ # Write the SVG to an actual file
548
+ with open("plot.svg", "w", encoding="utf-8") as file:
549
+ file.write(plot_svg_string)
550
+
551
+ • Displaying the SVG:
552
+
553
+ ![Plot](./media/plot_polynomial_functions_example_1.svg)
554
+
555
+ --------------------------------------------------------------------------------
556
+
517
557
  ## String Based Functions
518
558
 
519
559
  ### 1. send_telegram_message
@@ -343,17 +343,17 @@ Converts a polynomial expression written in Python syntax to a LaTeX formatted s
343
343
 
344
344
  Expands a polynomial expression written in Python syntax and converts it into a LaTeX formatted string. This function takes algebraic expressions provided as strings using Python's syntax, applies polynomial expansion through SymPy, and translates them into LaTeX representations, suitable for academic or professional documentation. It supports expressions with named variables and provides an option to substitute specific values into the expression before expansion.
345
345
 
346
- - Parameters:
346
+ Parameters:
347
347
  - `expression` (str): The algebraic expression to expand and convert to LaTeX. This string should be formatted using Python syntax acceptable by SymPy.
348
348
  - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers with which to substitute those variables before expanding.
349
349
 
350
- - Returns:
350
+ Returns:
351
351
  - `str`: The LaTeX formatted string of the expanded expression.
352
352
 
353
- - Raises:
353
+ Raises:
354
354
  - `ValueError`: If the expression cannot be parsed due to syntax errors.
355
355
 
356
- - Example:
356
+ Example:
357
357
 
358
358
  from rgwfuncs import expand_polynomial_expression
359
359
 
@@ -379,17 +379,17 @@ Expands a polynomial expression written in Python syntax and converts it into a
379
379
 
380
380
  Factors a polynomial expression written in Python syntax and converts it into a LaTeX formatted string. This function parses an algebraic expression, performs polynomial factoring using SymPy, and converts the factored expression into a LaTeX representation, ideal for academic or professional use. Optional substitutions can be made before factoring.
381
381
 
382
- - Parameters:
382
+ Parameters:
383
383
  - `expression` (str): The polynomial expression to factor and convert to LaTeX. This should be a valid expression formatted using Python syntax.
384
384
  - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions. The keys are variable names in the expression, and the values are numbers that replace these variables.
385
385
 
386
- - Returns:
386
+ Returns:
387
387
  - `str`: The LaTeX formatted string representing the factored expression.
388
388
 
389
- - Raises:
389
+ Raises:
390
390
  - `ValueError`: If the expression cannot be parsed due to syntax errors.
391
391
 
392
- - Example:
392
+ Example:
393
393
 
394
394
  from rgwfuncs import factor_polynomial_expression
395
395
 
@@ -403,35 +403,7 @@ Factors a polynomial expression written in Python syntax and converts it into a
403
403
 
404
404
  --------------------------------------------------------------------------------
405
405
 
406
- ### 8. `cancel_polynomial_expression`
407
-
408
- Cancels common factors within a polynomial expression written in Python syntax and converts it to a LaTeX formatted string. This function parses an algebraic expression, cancels common factors using SymPy, and translates the reduced expression into a LaTeX representation. It can also accommodate optional substitutions to be made prior to simplification.
409
-
410
- - Parameters:
411
- - `expression` (str): The algebraic expression to simplify and convert to LaTeX. This string should be formatted using Python syntax.
412
- - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers to substitute.
413
-
414
- - Returns:
415
- - `str`: The LaTeX formatted string of the simplified expression. If the expression involves indeterminate forms due to operations like division by zero, a descriptive error message is returned instead.
416
-
417
- - Raises:
418
- - `ValueError`: If the expression cannot be parsed due to syntax errors or involves undefined operations, such as division by zero.
419
-
420
- - Example:
421
-
422
- from rgwfuncs import cancel_polynomial_expression
423
-
424
- # Cancel common factors within a polynomial expression
425
- latex_result1 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)")
426
- print(latex_result1) # Output: "x + 2"
427
-
428
- # Cancel with substituted values
429
- latex_result2 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)", {"x": 2})
430
- print(latex_result2) # Output: "Undefined result. This could be a division by zero error."
431
-
432
- --------------------------------------------------------------------------------
433
-
434
- ### 9. `simplify_polynomial_expression`
406
+ ### 8. `simplify_polynomial_expression`
435
407
 
436
408
  Simplifies an algebraic expression in polynomial form and returns it in LaTeX format. Takes an algebraic expression, in polynomial form, written in Python syntax and simplifies it. The result is returned as a LaTeX formatted string, suitable for academic or professional documentation.
437
409
 
@@ -442,7 +414,7 @@ Simplifies an algebraic expression in polynomial form and returns it in LaTeX fo
442
414
  • Returns:
443
415
  - `str`: The simplified expression formatted as a LaTeX string.
444
416
 
445
- • Example Usage:
417
+ • Example:
446
418
 
447
419
  from rgwfuncs import simplify_polynomial_expression
448
420
 
@@ -464,6 +436,34 @@ Simplifies an algebraic expression in polynomial form and returns it in LaTeX fo
464
436
 
465
437
  --------------------------------------------------------------------------------
466
438
 
439
+ ### 9. `cancel_polynomial_expression`
440
+
441
+ Cancels common factors within a polynomial expression written in Python syntax and converts it to a LaTeX formatted string. This function parses an algebraic expression, cancels common factors using SymPy, and translates the reduced expression into a LaTeX representation. It can also accommodate optional substitutions to be made prior to simplification.
442
+
443
+ • Parameters:
444
+ - `expression` (str): The algebraic expression to simplify and convert to LaTeX. This string should be formatted using Python syntax.
445
+ - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers to substitute.
446
+
447
+ • Returns:
448
+ - `str`: The LaTeX formatted string of the simplified expression. If the expression involves indeterminate forms due to operations like division by zero, a descriptive error message is returned instead.
449
+
450
+ • Raises:
451
+ - `ValueError`: If the expression cannot be parsed due to syntax errors or involves undefined operations, such as division by zero.
452
+
453
+ • Example:
454
+
455
+ from rgwfuncs import cancel_polynomial_expression
456
+
457
+ # Cancel common factors within a polynomial expression
458
+ latex_result1 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)")
459
+ print(latex_result1) # Output: "x + 2"
460
+
461
+ # Cancel with substituted values
462
+ latex_result2 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)", {"x": 2})
463
+ print(latex_result2) # Output: "Undefined result. This could be a division by zero error."
464
+
465
+ --------------------------------------------------------------------------------
466
+
467
467
  ### 10. `solve_homogeneous_polynomial_expression`
468
468
 
469
469
  Solves a homogeneous polynomial expression for a specified variable and returns solutions in LaTeX format. Assumes that the expression is homoegeneous (i.e. equal to zero), and solves for a designated variable. May optionally include substitutions for other variables in the equation. The solutions are provided as a LaTeX formatted string. The method solves equations for specified variables, with optional substitutions, returning LaTeX-formatted solutions.
@@ -487,6 +487,46 @@ Solves a homogeneous polynomial expression for a specified variable and returns
487
487
 
488
488
  --------------------------------------------------------------------------------
489
489
 
490
+ ### 11. `plot_polynomial_functions`
491
+
492
+ This function plots polynomial functions described by a list of expressions and their corresponding substitution dictionaries. It generates SVG markup of the plots, with options for specifying the domain, axis zoom, and legend display.
493
+
494
+ • Parameters:
495
+ - `functions` (`List[Dict[str, Dict[str, Any]]]`): A list of dictionaries, each containing:
496
+ - A key which is a string representing a Python/NumPy expression (e.g., `"x**2"`, `"np.diff(x,2)"`).
497
+ - A value which is a dictionary containing substitutions for the expression. Must include an `"x"` key, either as `"*"` for default domain or a NumPy array.
498
+ - `zoom` (`float`): Determines the numeric axis range from `-zoom` to `+zoom` for both x and y axes (default is `10.0`).
499
+ - `show_legend` (`bool`): Specifies whether to include a legend in the plot (default is `True`).
500
+ - `open_file` (`bool`): If saving to path is not desireable, opens the svg as a temp file, else opens the file from the actual location using the system's default viewer (defaults to False).
501
+ - `save_path` (`Optional[str]`): If specified, saves the output string as a .svg at the indicated path (defaults to None).
502
+
503
+ • Returns:
504
+ - `str`: The raw SVG markup of the resulting plot.
505
+
506
+ • Example:
507
+
508
+ from rgwfuncs import plot_polynomial_functions
509
+
510
+ # Generate the SVG
511
+ plot_svg_string = plot_polynomial_functions(
512
+ functions=[
513
+ {"x**2": {"x": "*"}}, # Single expression, "*" means plot all discernable points
514
+ {"x**2/(2 + a) + a": {"x": np.linspace(-3, 4, 101), "a": 1.23}},
515
+ {"np.diff(x**3, 2)": {"x": np.linspace(-2, 2, 10)}}
516
+ ],
517
+ zoom=2
518
+ )
519
+
520
+ # Write the SVG to an actual file
521
+ with open("plot.svg", "w", encoding="utf-8") as file:
522
+ file.write(plot_svg_string)
523
+
524
+ • Displaying the SVG:
525
+
526
+ ![Plot](./media/plot_polynomial_functions_example_1.svg)
527
+
528
+ --------------------------------------------------------------------------------
529
+
490
530
  ## String Based Functions
491
531
 
492
532
  ### 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.50"
7
+ version = "0.0.53"
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.50
3
+ version = 0.0.53
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 cancel_polynomial_expression, compute_constant_expression, compute_constant_expression_involving_matrices, compute_constant_expression_involving_ordered_series, compute_prime_factors, expand_polynomial_expression, factor_polynomial_expression, python_polynomial_expression_to_latex, simplify_polynomial_expression, solve_homogeneous_polynomial_expression
4
+ from .algebra_lib import cancel_polynomial_expression, compute_constant_expression, compute_constant_expression_involving_matrices, compute_constant_expression_involving_ordered_series, compute_prime_factors, expand_polynomial_expression, factor_polynomial_expression, plot_polynomial_functions, python_polynomial_expression_to_latex, simplify_polynomial_expression, solve_homogeneous_polynomial_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 .interactive_shell_lib import interactive_shell
@@ -1,14 +1,18 @@
1
1
  import re
2
2
  import math
3
3
  import ast
4
+ import subprocess
5
+ import tempfile
4
6
  from sympy import symbols, latex, simplify, solve, diff, Expr, factor, cancel, Eq
5
7
  from sympy.core.sympify import SympifyError
6
8
  from sympy.core import S
7
9
  from sympy.parsing.sympy_parser import parse_expr
8
10
  from sympy import __all__ as sympy_functions
9
11
  from sympy.parsing.sympy_parser import (standard_transformations, implicit_multiplication_application)
10
-
11
- from typing import Tuple, List, Dict, Optional
12
+ from typing import Tuple, List, Dict, Optional, Any
13
+ import numpy as np
14
+ import matplotlib.pyplot as plt
15
+ from io import BytesIO
12
16
 
13
17
 
14
18
  def compute_prime_factors(n: int) -> str:
@@ -285,7 +289,6 @@ def python_polynomial_expression_to_latex(
285
289
  Raises:
286
290
  ValueError: If the expression cannot be parsed due to syntax errors.
287
291
  """
288
-
289
292
  transformations = standard_transformations + (implicit_multiplication_application,)
290
293
 
291
294
  def parse_and_convert_expression(expr_str: str, sym_vars: Dict[str, Expr]) -> Expr:
@@ -411,69 +414,6 @@ def factor_polynomial_expression(
411
414
  return latex_result
412
415
 
413
416
 
414
- def cancel_polynomial_expression(
415
- expression: str,
416
- subs: Optional[Dict[str, float]] = None
417
- ) -> str:
418
- """
419
- Cancels common factors within a polynomial expression and converts it to LaTeX format.
420
-
421
- This function parses an algebraic expression given in Python syntax, cancels any common factors,
422
- and converts the resulting simplified expression into a LaTeX formatted string. The function can
423
- also handle optional substitutions of variables before performing the cancellation.
424
-
425
- Parameters:
426
- expression (str): The algebraic expression to simplify and convert to LaTeX.
427
- It should be a valid expression formatted using Python syntax.
428
- subs (Optional[Dict[str, float]]): An optional dictionary where the keys are variable names in the
429
- expression, and the values are the corresponding numbers to substitute
430
- into the expression before simplification.
431
-
432
- Returns:
433
- str: The LaTeX formatted string of the simplified expression. If the expression involves
434
- indeterminate forms due to operations like division by zero, a descriptive error message is returned instead.
435
-
436
- Raises:
437
- ValueError: If the expression cannot be parsed due to syntax errors or if operations result in
438
- undefined behavior, such as division by zero.
439
-
440
- """
441
- transformations = standard_transformations + (implicit_multiplication_application,)
442
-
443
- def parse_and_cancel_expression(expr_str: str, sym_vars: Dict[str, symbols]) -> symbols:
444
- try:
445
- expr = parse_expr(expr_str, local_dict=sym_vars, transformations=transformations)
446
- if subs:
447
- if not isinstance(subs, dict):
448
- raise ValueError(f"Substitutions must be a dictionary. Received: {subs}")
449
- subs_symbols = {symbols(k): v for k, v in subs.items()}
450
- expr = expr.subs(subs_symbols)
451
-
452
- canceled_expr = cancel(expr)
453
-
454
- # Check for NaN or indeterminate forms
455
- if canceled_expr.has(S.NaN) or canceled_expr.has(S.Infinity) or canceled_expr.has(S.ComplexInfinity):
456
- return "Undefined result. This could be a division by zero error."
457
-
458
- return canceled_expr
459
-
460
- except (SyntaxError, ValueError, TypeError, AttributeError, ZeroDivisionError, SympifyError) as e:
461
- return f"Error: {str(e)}"
462
-
463
- variable_names = set(re.findall(r'\b[a-zA-Z]\w*\b', expression))
464
- sym_vars = {var: symbols(var) for var in variable_names}
465
-
466
- expr = parse_and_cancel_expression(expression, sym_vars)
467
-
468
- # If the expression is already a string (i.e., "Undefined" or error message), return it directly
469
- if isinstance(expr, str):
470
- return expr
471
-
472
- # Otherwise, convert to LaTeX as usual
473
- latex_result = latex(expr)
474
- return latex_result
475
-
476
-
477
417
  def simplify_polynomial_expression(
478
418
  expression: str,
479
419
  subs: Optional[Dict[str, float]] = None
@@ -649,6 +589,69 @@ def simplify_polynomial_expression(
649
589
  raise ValueError(f"Error simplifying expression: {e}")
650
590
 
651
591
 
592
+ def cancel_polynomial_expression(
593
+ expression: str,
594
+ subs: Optional[Dict[str, float]] = None
595
+ ) -> str:
596
+ """
597
+ Cancels common factors within a polynomial expression and converts it to LaTeX format.
598
+
599
+ This function parses an algebraic expression given in Python syntax, cancels any common factors,
600
+ and converts the resulting simplified expression into a LaTeX formatted string. The function can
601
+ also handle optional substitutions of variables before performing the cancellation.
602
+
603
+ Parameters:
604
+ expression (str): The algebraic expression to simplify and convert to LaTeX.
605
+ It should be a valid expression formatted using Python syntax.
606
+ subs (Optional[Dict[str, float]]): An optional dictionary where the keys are variable names in the
607
+ expression, and the values are the corresponding numbers to substitute
608
+ into the expression before simplification.
609
+
610
+ Returns:
611
+ str: The LaTeX formatted string of the simplified expression. If the expression involves
612
+ indeterminate forms due to operations like division by zero, a descriptive error message is returned instead.
613
+
614
+ Raises:
615
+ ValueError: If the expression cannot be parsed due to syntax errors or if operations result in
616
+ undefined behavior, such as division by zero.
617
+
618
+ """
619
+ transformations = standard_transformations + (implicit_multiplication_application,)
620
+
621
+ def parse_and_cancel_expression(expr_str: str, sym_vars: Dict[str, symbols]) -> symbols:
622
+ try:
623
+ expr = parse_expr(expr_str, local_dict=sym_vars, transformations=transformations)
624
+ if subs:
625
+ if not isinstance(subs, dict):
626
+ raise ValueError(f"Substitutions must be a dictionary. Received: {subs}")
627
+ subs_symbols = {symbols(k): v for k, v in subs.items()}
628
+ expr = expr.subs(subs_symbols)
629
+
630
+ canceled_expr = cancel(expr)
631
+
632
+ # Check for NaN or indeterminate forms
633
+ if canceled_expr.has(S.NaN) or canceled_expr.has(S.Infinity) or canceled_expr.has(S.ComplexInfinity):
634
+ return "Undefined result. This could be a division by zero error."
635
+
636
+ return canceled_expr
637
+
638
+ except (SyntaxError, ValueError, TypeError, AttributeError, ZeroDivisionError, SympifyError) as e:
639
+ return f"Error: {str(e)}"
640
+
641
+ variable_names = set(re.findall(r'\b[a-zA-Z]\w*\b', expression))
642
+ sym_vars = {var: symbols(var) for var in variable_names}
643
+
644
+ expr = parse_and_cancel_expression(expression, sym_vars)
645
+
646
+ # If the expression is already a string (i.e., "Undefined" or error message), return it directly
647
+ if isinstance(expr, str):
648
+ return expr
649
+
650
+ # Otherwise, convert to LaTeX as usual
651
+ latex_result = latex(expr)
652
+ return latex_result
653
+
654
+
652
655
  def solve_homogeneous_polynomial_expression(
653
656
  expression: str,
654
657
  variable: str,
@@ -701,3 +704,184 @@ def solve_homogeneous_polynomial_expression(
701
704
 
702
705
  except Exception as e:
703
706
  raise ValueError(f"Error solving the expression: {e}")
707
+
708
+
709
+ def plot_polynomial_functions(
710
+ functions: List[Dict[str, Dict[str, Any]]],
711
+ zoom: float = 10.0,
712
+ show_legend: bool = True,
713
+ open_file: bool = False,
714
+ save_path: Optional[str] = None,
715
+ ) -> str:
716
+ """
717
+ Plots expressions described by a list of dictionaries of the form:
718
+ [
719
+ { "expression_string": { "x": "*", "a":..., "b":... } },
720
+ { "expression_string": { "x": np.linspace(...), "a":..., ... } },
721
+ ...
722
+ ]
723
+
724
+ In each top-level dictionary, there is exactly one key (a string
725
+ representing a Python/NumPy expression) and one value (a dictionary of
726
+ substitutions). This substitutions dictionary must have an "x" key:
727
+ • "x": "*" -> Use a default domain from -zoom..+zoom.
728
+ • "x": np.array(...) -> Use that array as the domain.
729
+ Other variables (like "a", "b", etc.) may also appear in the same dict.
730
+
731
+ Additionally, we use latexify_expression(...) to transform the expression
732
+ into a nice LaTeX form for the legend, including a special Δ notation for np.diff(...).
733
+
734
+ Parameters
735
+ ----------
736
+ functions : List[Dict[str, Dict[str, Any]]]
737
+ A list of items. Each item is a dictionary:
738
+ key = expression string (e.g., "x**2", "np.diff(x,2)", etc.)
739
+ value = a dictionary of substitutions. Must contain "x",
740
+ either as "*" or a NumPy array. May contain additional
741
+ parameters like "a", "b", etc.
742
+ zoom : float
743
+ Sets the numeric axis range from -zoom..+zoom in both x and y.
744
+ show_legend : bool
745
+ Whether to add a legend to the plot (defaults to True).
746
+ open_file : bool
747
+ If saving to path is not desireable, opens the svg as a temp file, else opens
748
+ the file from the actual location using the system's default viewer (defaults to
749
+ False).
750
+ save_path : Optional[str]
751
+ If specified, saves the output string as a .svg at the indicated path (defaults to
752
+ None).
753
+
754
+ Returns
755
+ -------
756
+ str
757
+ The raw SVG markup of the resulting plot.
758
+ """
759
+
760
+ def latexify_expression(expr_str: str) -> str:
761
+ # Regex to locate np.diff(...) with an optional second argument
762
+ DIFF_PATTERN = r"np\.diff\s*\(\s*([^,\)]+)(?:,\s*(\d+))?\)"
763
+
764
+ def diff_replacer(match: re.Match) -> str:
765
+ inside = match.group(1).strip()
766
+ exponent = match.group(2)
767
+ inside_no_np = inside.replace("np.", "")
768
+ if exponent:
769
+ return rf"\Delta^{exponent}\left({inside_no_np}\right)"
770
+ else:
771
+ return rf"\Delta\left({inside_no_np}\right)"
772
+
773
+ expr_tmp = re.sub(DIFF_PATTERN, diff_replacer, expr_str)
774
+ expr_tmp = expr_tmp.replace("np.", "")
775
+ try:
776
+ latex_expr = python_polynomial_expression_to_latex(expr_tmp)
777
+ return latex_expr
778
+ except Exception:
779
+ # Fallback: just do naive **
780
+ return expr_tmp.replace("**", "^")
781
+
782
+ def handle_open_and_save(
783
+ svg_string: str,
784
+ open_file: bool,
785
+ save_path: Optional[str]
786
+ ) -> None:
787
+ # Save the SVG to a file if a save path is provided
788
+ if save_path:
789
+ try:
790
+ with open(save_path, 'w', encoding='utf-8') as file:
791
+ file.write(svg_string)
792
+ print(f"[INFO] SVG saved to: {save_path}")
793
+ except IOError as e:
794
+ print(f"[ERROR] Failed to save SVG to {save_path}. IOError: {e}")
795
+
796
+ # Handle opening the file if requested
797
+ if open_file and save_path:
798
+ result = subprocess.run(["xdg-open", save_path], stderr=subprocess.DEVNULL)
799
+ if result.returncode != 0:
800
+ print("[ERROR] Failed to open the SVG file with the default viewer.")
801
+ elif open_file:
802
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".svg") as tmpfile:
803
+ temp_svg_path = tmpfile.name
804
+ tmpfile.write(svg_string.encode('utf-8'))
805
+ result = subprocess.run(["xdg-open", temp_svg_path], stderr=subprocess.DEVNULL)
806
+ if result.returncode != 0:
807
+ print("[ERROR] Failed to open the SVG file with the default viewer.")
808
+
809
+ buffer = BytesIO()
810
+ fig, ax = plt.subplots()
811
+
812
+ for entry in functions:
813
+ if len(entry) != 1:
814
+ print("Skipping invalid item. Must have exactly 1 expression->substitutions pair.")
815
+ continue
816
+
817
+ expression, sub_dict = list(entry.items())[0]
818
+ if "x" not in sub_dict:
819
+ print(f"Skipping '{expression}' because sub-dict lacks 'x' key.")
820
+ continue
821
+
822
+ # If "x" is "*", create a default domain
823
+ x_val = sub_dict["x"]
824
+ if isinstance(x_val, str) and x_val == "*":
825
+ x_values = np.linspace(-zoom, zoom, 1201)
826
+ sub_dict["x"] = x_values
827
+ elif isinstance(x_val, np.ndarray):
828
+ x_values = x_val
829
+ else:
830
+ print(f"Skipping '{expression}' because 'x' is neither '*' nor a NumPy array.")
831
+ continue
832
+
833
+ # Evaluate the expression
834
+ try:
835
+ eval_context = {"np": np}
836
+ eval_context.update(sub_dict)
837
+ y_values = eval(expression, {"np": np}, eval_context)
838
+ except Exception as e:
839
+ print(f"Error evaluating expression '{expression}': {e}")
840
+ continue
841
+
842
+ if not isinstance(y_values, np.ndarray):
843
+ print(f"Skipping '{expression}' because it did not produce a NumPy array.")
844
+ continue
845
+
846
+ # If y_values is shorter than x_values (like np.diff), truncate x
847
+ if len(y_values) < len(x_values):
848
+ x_values = x_values[:len(y_values)]
849
+
850
+ # Convert expression to a nice LaTeX string
851
+ label_expr = latexify_expression(expression)
852
+ ax.plot(x_values, y_values, label=rf"${label_expr}$")
853
+
854
+ # Configure axes
855
+ ax.set_xlim(-zoom, zoom)
856
+ ax.set_ylim(-zoom, zoom)
857
+ ax.spines['left'].set_position('zero')
858
+ ax.spines['bottom'].set_position('zero')
859
+ ax.spines['right'].set_color('none')
860
+ ax.spines['top'].set_color('none')
861
+ ax.set_aspect('equal', 'box')
862
+ ax.xaxis.set_ticks_position('bottom')
863
+ ax.yaxis.set_ticks_position('left')
864
+ ax.grid(True)
865
+
866
+ # Show legend
867
+ if show_legend:
868
+ leg = ax.legend(
869
+ loc='upper center',
870
+ bbox_to_anchor=(0.5, -0.03),
871
+ fancybox=True,
872
+ shadow=True,
873
+ ncol=1
874
+ )
875
+ plt.savefig(
876
+ buffer,
877
+ format='svg',
878
+ bbox_inches='tight',
879
+ bbox_extra_artists=[leg] # ensures the legend is fully captured
880
+ )
881
+ else:
882
+ plt.savefig(buffer, format='svg', bbox_inches='tight')
883
+
884
+ plt.close(fig)
885
+ svg_string = buffer.getvalue().decode('utf-8')
886
+ handle_open_and_save(svg_string, open_file, save_path)
887
+ return svg_string
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rgwfuncs
3
- Version: 0.0.50
3
+ Version: 0.0.53
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
@@ -370,17 +370,17 @@ Converts a polynomial expression written in Python syntax to a LaTeX formatted s
370
370
 
371
371
  Expands a polynomial expression written in Python syntax and converts it into a LaTeX formatted string. This function takes algebraic expressions provided as strings using Python's syntax, applies polynomial expansion through SymPy, and translates them into LaTeX representations, suitable for academic or professional documentation. It supports expressions with named variables and provides an option to substitute specific values into the expression before expansion.
372
372
 
373
- - Parameters:
373
+ Parameters:
374
374
  - `expression` (str): The algebraic expression to expand and convert to LaTeX. This string should be formatted using Python syntax acceptable by SymPy.
375
375
  - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers with which to substitute those variables before expanding.
376
376
 
377
- - Returns:
377
+ Returns:
378
378
  - `str`: The LaTeX formatted string of the expanded expression.
379
379
 
380
- - Raises:
380
+ Raises:
381
381
  - `ValueError`: If the expression cannot be parsed due to syntax errors.
382
382
 
383
- - Example:
383
+ Example:
384
384
 
385
385
  from rgwfuncs import expand_polynomial_expression
386
386
 
@@ -406,17 +406,17 @@ Expands a polynomial expression written in Python syntax and converts it into a
406
406
 
407
407
  Factors a polynomial expression written in Python syntax and converts it into a LaTeX formatted string. This function parses an algebraic expression, performs polynomial factoring using SymPy, and converts the factored expression into a LaTeX representation, ideal for academic or professional use. Optional substitutions can be made before factoring.
408
408
 
409
- - Parameters:
409
+ Parameters:
410
410
  - `expression` (str): The polynomial expression to factor and convert to LaTeX. This should be a valid expression formatted using Python syntax.
411
411
  - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions. The keys are variable names in the expression, and the values are numbers that replace these variables.
412
412
 
413
- - Returns:
413
+ Returns:
414
414
  - `str`: The LaTeX formatted string representing the factored expression.
415
415
 
416
- - Raises:
416
+ Raises:
417
417
  - `ValueError`: If the expression cannot be parsed due to syntax errors.
418
418
 
419
- - Example:
419
+ Example:
420
420
 
421
421
  from rgwfuncs import factor_polynomial_expression
422
422
 
@@ -430,35 +430,7 @@ Factors a polynomial expression written in Python syntax and converts it into a
430
430
 
431
431
  --------------------------------------------------------------------------------
432
432
 
433
- ### 8. `cancel_polynomial_expression`
434
-
435
- Cancels common factors within a polynomial expression written in Python syntax and converts it to a LaTeX formatted string. This function parses an algebraic expression, cancels common factors using SymPy, and translates the reduced expression into a LaTeX representation. It can also accommodate optional substitutions to be made prior to simplification.
436
-
437
- - Parameters:
438
- - `expression` (str): The algebraic expression to simplify and convert to LaTeX. This string should be formatted using Python syntax.
439
- - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers to substitute.
440
-
441
- - Returns:
442
- - `str`: The LaTeX formatted string of the simplified expression. If the expression involves indeterminate forms due to operations like division by zero, a descriptive error message is returned instead.
443
-
444
- - Raises:
445
- - `ValueError`: If the expression cannot be parsed due to syntax errors or involves undefined operations, such as division by zero.
446
-
447
- - Example:
448
-
449
- from rgwfuncs import cancel_polynomial_expression
450
-
451
- # Cancel common factors within a polynomial expression
452
- latex_result1 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)")
453
- print(latex_result1) # Output: "x + 2"
454
-
455
- # Cancel with substituted values
456
- latex_result2 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)", {"x": 2})
457
- print(latex_result2) # Output: "Undefined result. This could be a division by zero error."
458
-
459
- --------------------------------------------------------------------------------
460
-
461
- ### 9. `simplify_polynomial_expression`
433
+ ### 8. `simplify_polynomial_expression`
462
434
 
463
435
  Simplifies an algebraic expression in polynomial form and returns it in LaTeX format. Takes an algebraic expression, in polynomial form, written in Python syntax and simplifies it. The result is returned as a LaTeX formatted string, suitable for academic or professional documentation.
464
436
 
@@ -469,7 +441,7 @@ Simplifies an algebraic expression in polynomial form and returns it in LaTeX fo
469
441
  • Returns:
470
442
  - `str`: The simplified expression formatted as a LaTeX string.
471
443
 
472
- • Example Usage:
444
+ • Example:
473
445
 
474
446
  from rgwfuncs import simplify_polynomial_expression
475
447
 
@@ -491,6 +463,34 @@ Simplifies an algebraic expression in polynomial form and returns it in LaTeX fo
491
463
 
492
464
  --------------------------------------------------------------------------------
493
465
 
466
+ ### 9. `cancel_polynomial_expression`
467
+
468
+ Cancels common factors within a polynomial expression written in Python syntax and converts it to a LaTeX formatted string. This function parses an algebraic expression, cancels common factors using SymPy, and translates the reduced expression into a LaTeX representation. It can also accommodate optional substitutions to be made prior to simplification.
469
+
470
+ • Parameters:
471
+ - `expression` (str): The algebraic expression to simplify and convert to LaTeX. This string should be formatted using Python syntax.
472
+ - `subs` (Optional[Dict[str, float]]): An optional dictionary of substitutions where the keys are variable names in the expression, and the values are the numbers to substitute.
473
+
474
+ • Returns:
475
+ - `str`: The LaTeX formatted string of the simplified expression. If the expression involves indeterminate forms due to operations like division by zero, a descriptive error message is returned instead.
476
+
477
+ • Raises:
478
+ - `ValueError`: If the expression cannot be parsed due to syntax errors or involves undefined operations, such as division by zero.
479
+
480
+ • Example:
481
+
482
+ from rgwfuncs import cancel_polynomial_expression
483
+
484
+ # Cancel common factors within a polynomial expression
485
+ latex_result1 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)")
486
+ print(latex_result1) # Output: "x + 2"
487
+
488
+ # Cancel with substituted values
489
+ latex_result2 = cancel_polynomial_expression("(x**2 - 4) / (x - 2)", {"x": 2})
490
+ print(latex_result2) # Output: "Undefined result. This could be a division by zero error."
491
+
492
+ --------------------------------------------------------------------------------
493
+
494
494
  ### 10. `solve_homogeneous_polynomial_expression`
495
495
 
496
496
  Solves a homogeneous polynomial expression for a specified variable and returns solutions in LaTeX format. Assumes that the expression is homoegeneous (i.e. equal to zero), and solves for a designated variable. May optionally include substitutions for other variables in the equation. The solutions are provided as a LaTeX formatted string. The method solves equations for specified variables, with optional substitutions, returning LaTeX-formatted solutions.
@@ -514,6 +514,46 @@ Solves a homogeneous polynomial expression for a specified variable and returns
514
514
 
515
515
  --------------------------------------------------------------------------------
516
516
 
517
+ ### 11. `plot_polynomial_functions`
518
+
519
+ This function plots polynomial functions described by a list of expressions and their corresponding substitution dictionaries. It generates SVG markup of the plots, with options for specifying the domain, axis zoom, and legend display.
520
+
521
+ • Parameters:
522
+ - `functions` (`List[Dict[str, Dict[str, Any]]]`): A list of dictionaries, each containing:
523
+ - A key which is a string representing a Python/NumPy expression (e.g., `"x**2"`, `"np.diff(x,2)"`).
524
+ - A value which is a dictionary containing substitutions for the expression. Must include an `"x"` key, either as `"*"` for default domain or a NumPy array.
525
+ - `zoom` (`float`): Determines the numeric axis range from `-zoom` to `+zoom` for both x and y axes (default is `10.0`).
526
+ - `show_legend` (`bool`): Specifies whether to include a legend in the plot (default is `True`).
527
+ - `open_file` (`bool`): If saving to path is not desireable, opens the svg as a temp file, else opens the file from the actual location using the system's default viewer (defaults to False).
528
+ - `save_path` (`Optional[str]`): If specified, saves the output string as a .svg at the indicated path (defaults to None).
529
+
530
+ • Returns:
531
+ - `str`: The raw SVG markup of the resulting plot.
532
+
533
+ • Example:
534
+
535
+ from rgwfuncs import plot_polynomial_functions
536
+
537
+ # Generate the SVG
538
+ plot_svg_string = plot_polynomial_functions(
539
+ functions=[
540
+ {"x**2": {"x": "*"}}, # Single expression, "*" means plot all discernable points
541
+ {"x**2/(2 + a) + a": {"x": np.linspace(-3, 4, 101), "a": 1.23}},
542
+ {"np.diff(x**3, 2)": {"x": np.linspace(-2, 2, 10)}}
543
+ ],
544
+ zoom=2
545
+ )
546
+
547
+ # Write the SVG to an actual file
548
+ with open("plot.svg", "w", encoding="utf-8") as file:
549
+ file.write(plot_svg_string)
550
+
551
+ • Displaying the SVG:
552
+
553
+ ![Plot](./media/plot_polynomial_functions_example_1.svg)
554
+
555
+ --------------------------------------------------------------------------------
556
+
517
557
  ## String Based Functions
518
558
 
519
559
  ### 1. send_telegram_message
File without changes