mxlpy 0.16.0__py3-none-any.whl → 0.17.0__py3-none-any.whl
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.
- mxlpy/__init__.py +4 -1
- mxlpy/fns.py +513 -21
- mxlpy/meta/codegen_latex.py +279 -14
- mxlpy/meta/source_tools.py +122 -4
- mxlpy/model.py +50 -24
- mxlpy/npe/__init__.py +38 -0
- mxlpy/npe/_torch.py +436 -0
- mxlpy/report.py +33 -6
- mxlpy/sbml/_import.py +5 -2
- mxlpy/surrogates/__init__.py +7 -6
- mxlpy/surrogates/_poly.py +12 -9
- mxlpy/surrogates/_torch.py +137 -43
- mxlpy/symbolic/strikepy.py +1 -3
- mxlpy/types.py +17 -4
- {mxlpy-0.16.0.dist-info → mxlpy-0.17.0.dist-info}/METADATA +1 -2
- {mxlpy-0.16.0.dist-info → mxlpy-0.17.0.dist-info}/RECORD +18 -17
- mxlpy/npe.py +0 -277
- {mxlpy-0.16.0.dist-info → mxlpy-0.17.0.dist-info}/WHEEL +0 -0
- {mxlpy-0.16.0.dist-info → mxlpy-0.17.0.dist-info}/licenses/LICENSE +0 -0
mxlpy/meta/codegen_latex.py
CHANGED
@@ -37,7 +37,26 @@ def _list_of_symbols(args: list[str]) -> list[sympy.Symbol | sympy.Expr]:
|
|
37
37
|
|
38
38
|
|
39
39
|
def default_init[T1, T2](d: dict[T1, T2] | None) -> dict[T1, T2]:
|
40
|
-
"""Return empty dict if d is None.
|
40
|
+
"""Return empty dict if d is None.
|
41
|
+
|
42
|
+
Parameters
|
43
|
+
----------
|
44
|
+
d
|
45
|
+
Dictionary to check
|
46
|
+
|
47
|
+
Returns
|
48
|
+
-------
|
49
|
+
dict
|
50
|
+
Original dictionary if not None, otherwise an empty dictionary
|
51
|
+
|
52
|
+
Examples
|
53
|
+
--------
|
54
|
+
>>> default_init(None)
|
55
|
+
{}
|
56
|
+
>>> default_init({"key": "value"})
|
57
|
+
{'key': 'value'}
|
58
|
+
|
59
|
+
"""
|
41
60
|
return {} if d is None else d
|
42
61
|
|
43
62
|
|
@@ -256,7 +275,23 @@ def _stoichiometries_to_latex(stoich: Mapping[str, float | Derived]) -> str:
|
|
256
275
|
|
257
276
|
@dataclass
|
258
277
|
class TexReaction:
|
259
|
-
"""Collection for reaction.
|
278
|
+
"""Collection for reaction.
|
279
|
+
|
280
|
+
Parameters
|
281
|
+
----------
|
282
|
+
fn
|
283
|
+
Rate function for the reaction
|
284
|
+
args
|
285
|
+
List of argument names for the rate function
|
286
|
+
|
287
|
+
Examples
|
288
|
+
--------
|
289
|
+
>>> def rate_fn(k, s): return k * s
|
290
|
+
>>> reaction = TexReaction(fn=rate_fn, args=["k1", "S"])
|
291
|
+
>>> reaction.fn(0.1, 1.0)
|
292
|
+
0.1
|
293
|
+
|
294
|
+
"""
|
260
295
|
|
261
296
|
fn: RateFn
|
262
297
|
args: list[str]
|
@@ -264,7 +299,35 @@ class TexReaction:
|
|
264
299
|
|
265
300
|
@dataclass
|
266
301
|
class TexExport:
|
267
|
-
"""Container for LaTeX export.
|
302
|
+
"""Container for LaTeX export.
|
303
|
+
|
304
|
+
This class handles the conversion of model components to LaTeX format
|
305
|
+
for exporting models as LaTeX documents.
|
306
|
+
|
307
|
+
Parameters
|
308
|
+
----------
|
309
|
+
parameters
|
310
|
+
Dictionary of parameter names and their values
|
311
|
+
variables
|
312
|
+
Dictionary of variable names and their initial values
|
313
|
+
derived
|
314
|
+
Dictionary of derived variables and their definitions
|
315
|
+
reactions
|
316
|
+
Dictionary of reaction names and their rate functions
|
317
|
+
stoichiometries
|
318
|
+
Dictionary mapping reaction names to stoichiometry dictionaries
|
319
|
+
|
320
|
+
Examples
|
321
|
+
--------
|
322
|
+
>>> parameters = {"k1": 0.1, "k2": 0.2}
|
323
|
+
>>> variables = {"S": 1.0, "P": 0.0}
|
324
|
+
>>> derived = {"total": Derived(fn=lambda s, p: s + p, args=["S", "P"])}
|
325
|
+
>>> reactions = {"v1": TexReaction(fn=lambda k, s: k*s, args=["k1", "S"])}
|
326
|
+
>>> stoich = {"v1": {"S": -1, "P": 1}}
|
327
|
+
>>> tex = TexExport(parameters, variables, derived, reactions, stoich)
|
328
|
+
>>> latex_doc = tex.export_document(author="User", title="My Model")
|
329
|
+
|
330
|
+
"""
|
268
331
|
|
269
332
|
parameters: dict[str, float]
|
270
333
|
variables: dict[str, float]
|
@@ -298,7 +361,27 @@ class TexExport:
|
|
298
361
|
return {k: v for k, v in p2.items() if k not in p1 or p1[k] != v}
|
299
362
|
|
300
363
|
def __sub__(self, other: object) -> TexExport:
|
301
|
-
"""Return difference of two tex exports.
|
364
|
+
"""Return difference of two tex exports.
|
365
|
+
|
366
|
+
Parameters
|
367
|
+
----------
|
368
|
+
other
|
369
|
+
Another TexExport instance to compare with
|
370
|
+
|
371
|
+
Returns
|
372
|
+
-------
|
373
|
+
TexExport
|
374
|
+
A new TexExport containing only the elements that differ
|
375
|
+
|
376
|
+
Examples
|
377
|
+
--------
|
378
|
+
>>> tex1 = TexExport({"k": 1.0}, {}, {}, {}, {})
|
379
|
+
>>> tex2 = TexExport({"k": 2.0}, {}, {}, {}, {})
|
380
|
+
>>> diff = tex1 - tex2
|
381
|
+
>>> diff.parameters
|
382
|
+
{'k': 2.0}
|
383
|
+
|
384
|
+
"""
|
302
385
|
if not isinstance(other, TexExport):
|
303
386
|
raise TypeError
|
304
387
|
|
@@ -315,7 +398,28 @@ class TexExport:
|
|
315
398
|
)
|
316
399
|
|
317
400
|
def rename_with_glossary(self, gls: dict[str, str]) -> TexExport:
|
318
|
-
"""Rename all elements according to glossary.
|
401
|
+
"""Rename all elements according to glossary.
|
402
|
+
|
403
|
+
Parameters
|
404
|
+
----------
|
405
|
+
gls
|
406
|
+
Dictionary mapping original names to glossary names
|
407
|
+
|
408
|
+
Returns
|
409
|
+
-------
|
410
|
+
TexExport
|
411
|
+
A new TexExport with renamed elements
|
412
|
+
|
413
|
+
Examples
|
414
|
+
--------
|
415
|
+
>>> tex = TexExport({"k": 1.0}, {"S": 1.0}, {}, {}, {})
|
416
|
+
>>> renamed = tex.rename_with_glossary({"k": "rate", "S": "substrate"})
|
417
|
+
>>> renamed.parameters
|
418
|
+
{'rate': 1.0}
|
419
|
+
>>> renamed.variables
|
420
|
+
{'substrate': 1.0}
|
421
|
+
|
422
|
+
"""
|
319
423
|
|
320
424
|
def _add_gls_if_found(k: str) -> str:
|
321
425
|
if (new := gls.get(k)) is not None:
|
@@ -343,7 +447,21 @@ class TexExport:
|
|
343
447
|
)
|
344
448
|
|
345
449
|
def export_variables(self) -> str:
|
346
|
-
"""Export variables.
|
450
|
+
"""Export variables as LaTeX table.
|
451
|
+
|
452
|
+
Returns
|
453
|
+
-------
|
454
|
+
str
|
455
|
+
LaTeX code for variables table
|
456
|
+
|
457
|
+
Examples
|
458
|
+
--------
|
459
|
+
>>> tex = TexExport({}, {"S": 1.0, "P": 0.5}, {}, {}, {})
|
460
|
+
>>> latex = tex.export_variables()
|
461
|
+
>>> "Model variables" in latex
|
462
|
+
True
|
463
|
+
|
464
|
+
"""
|
347
465
|
return _table(
|
348
466
|
headers=["Model name", "Initial concentration"],
|
349
467
|
rows=[
|
@@ -360,7 +478,21 @@ class TexExport:
|
|
360
478
|
)
|
361
479
|
|
362
480
|
def export_parameters(self) -> str:
|
363
|
-
"""Export parameters.
|
481
|
+
"""Export parameters as LaTeX table.
|
482
|
+
|
483
|
+
Returns
|
484
|
+
-------
|
485
|
+
str
|
486
|
+
LaTeX code for parameters table
|
487
|
+
|
488
|
+
Examples
|
489
|
+
--------
|
490
|
+
>>> tex = TexExport({"k1": 0.1, "k2": 0.2}, {}, {}, {}, {})
|
491
|
+
>>> latex = tex.export_parameters()
|
492
|
+
>>> "Model parameters" in latex
|
493
|
+
True
|
494
|
+
|
495
|
+
"""
|
364
496
|
return _table(
|
365
497
|
headers=["Parameter name", "Parameter value"],
|
366
498
|
rows=[
|
@@ -374,7 +506,23 @@ class TexExport:
|
|
374
506
|
)
|
375
507
|
|
376
508
|
def export_derived(self) -> str:
|
377
|
-
"""Export derived quantities.
|
509
|
+
"""Export derived quantities as LaTeX equations.
|
510
|
+
|
511
|
+
Returns
|
512
|
+
-------
|
513
|
+
str
|
514
|
+
LaTeX code with derived quantity equations
|
515
|
+
|
516
|
+
Examples
|
517
|
+
--------
|
518
|
+
>>> def sum_fn(x, y): return x + y
|
519
|
+
>>> derived = {"total": Derived(fn=sum_fn, args=["S", "P"])}
|
520
|
+
>>> tex = TexExport({}, {}, derived, {}, {})
|
521
|
+
>>> latex = tex.export_derived()
|
522
|
+
>>> "total" in latex
|
523
|
+
True
|
524
|
+
|
525
|
+
"""
|
378
526
|
return _latex_list(
|
379
527
|
rows=[
|
380
528
|
_dmath(
|
@@ -385,7 +533,23 @@ class TexExport:
|
|
385
533
|
)
|
386
534
|
|
387
535
|
def export_reactions(self) -> str:
|
388
|
-
"""Export reactions.
|
536
|
+
"""Export reactions as LaTeX equations.
|
537
|
+
|
538
|
+
Returns
|
539
|
+
-------
|
540
|
+
str
|
541
|
+
LaTeX code with reaction rate equations
|
542
|
+
|
543
|
+
Examples
|
544
|
+
--------
|
545
|
+
>>> def rate_fn(k, s): return k * s
|
546
|
+
>>> reactions = {"v1": TexReaction(fn=rate_fn, args=["k1", "S"])}
|
547
|
+
>>> tex = TexExport({}, {}, {}, reactions, {})
|
548
|
+
>>> latex = tex.export_reactions()
|
549
|
+
>>> "v1" in latex
|
550
|
+
True
|
551
|
+
|
552
|
+
"""
|
389
553
|
return _latex_list(
|
390
554
|
rows=[
|
391
555
|
_dmath(
|
@@ -396,7 +560,22 @@ class TexExport:
|
|
396
560
|
)
|
397
561
|
|
398
562
|
def export_stoichiometries(self) -> str:
|
399
|
-
"""Export stoichiometries.
|
563
|
+
"""Export stoichiometries as LaTeX table.
|
564
|
+
|
565
|
+
Returns
|
566
|
+
-------
|
567
|
+
str
|
568
|
+
LaTeX code for stoichiometries table
|
569
|
+
|
570
|
+
Examples
|
571
|
+
--------
|
572
|
+
>>> stoich = {"v1": {"S": -1, "P": 1}}
|
573
|
+
>>> tex = TexExport({}, {}, {}, {}, stoich)
|
574
|
+
>>> latex = tex.export_stoichiometries()
|
575
|
+
>>> "Model stoichiometries" in latex
|
576
|
+
True
|
577
|
+
|
578
|
+
"""
|
400
579
|
return _table(
|
401
580
|
headers=["Rate name", "Stoichiometry"],
|
402
581
|
rows=[
|
@@ -413,7 +592,21 @@ class TexExport:
|
|
413
592
|
)
|
414
593
|
|
415
594
|
def export_all(self) -> str:
|
416
|
-
"""Export all model parts.
|
595
|
+
"""Export all model parts as a complete LaTeX document section.
|
596
|
+
|
597
|
+
Returns
|
598
|
+
-------
|
599
|
+
str
|
600
|
+
LaTeX code containing all model components
|
601
|
+
|
602
|
+
Examples
|
603
|
+
--------
|
604
|
+
>>> tex = TexExport({"k": 1.0}, {"S": 1.0}, {}, {}, {})
|
605
|
+
>>> latex = tex.export_all()
|
606
|
+
>>> "Parameters" in latex and "Variables" in latex
|
607
|
+
True
|
608
|
+
|
609
|
+
"""
|
417
610
|
sections = []
|
418
611
|
if len(self.variables) > 0:
|
419
612
|
sections.append(
|
@@ -456,7 +649,28 @@ class TexExport:
|
|
456
649
|
author: str = "mxlpy",
|
457
650
|
title: str = "Model construction",
|
458
651
|
) -> str:
|
459
|
-
"""Export
|
652
|
+
r"""Export complete LaTeX document with all model components.
|
653
|
+
|
654
|
+
Parameters
|
655
|
+
----------
|
656
|
+
author
|
657
|
+
Name of the author for the document
|
658
|
+
title
|
659
|
+
Title for the document
|
660
|
+
|
661
|
+
Returns
|
662
|
+
-------
|
663
|
+
str
|
664
|
+
Complete LaTeX document as a string
|
665
|
+
|
666
|
+
Examples
|
667
|
+
--------
|
668
|
+
>>> tex = TexExport({"k": 1.0}, {"S": 1.0}, {}, {}, {})
|
669
|
+
>>> doc = tex.export_document(author="Jane Doe", title="My Model")
|
670
|
+
>>> "\\title{My Model}" in doc and "\\author{Jane Doe}" in doc
|
671
|
+
True
|
672
|
+
|
673
|
+
"""
|
460
674
|
content = self.export_all()
|
461
675
|
return rf"""\documentclass{{article}}
|
462
676
|
\usepackage[english]{{babel}}
|
@@ -491,7 +705,33 @@ def generate_latex_code(
|
|
491
705
|
model: Model,
|
492
706
|
gls: dict[str, str] | None = None,
|
493
707
|
) -> str:
|
494
|
-
"""Export as LaTeX.
|
708
|
+
"""Export model as LaTeX document.
|
709
|
+
|
710
|
+
Parameters
|
711
|
+
----------
|
712
|
+
model
|
713
|
+
The model to export
|
714
|
+
gls
|
715
|
+
Optional glossary mapping for renaming model components
|
716
|
+
|
717
|
+
Returns
|
718
|
+
-------
|
719
|
+
str
|
720
|
+
Complete LaTeX document as string
|
721
|
+
|
722
|
+
Examples
|
723
|
+
--------
|
724
|
+
>>> from mxlpy import Model
|
725
|
+
>>> model = Model()
|
726
|
+
>>> model.add_parameter("k1", 0.1)
|
727
|
+
>>> model.add_variable("S", 1.0)
|
728
|
+
>>> latex = generate_latex_code(model)
|
729
|
+
>>> "Model parameters" in latex and "Model variables" in latex
|
730
|
+
True
|
731
|
+
>>> # With glossary
|
732
|
+
>>> latex = generate_latex_code(model, {"k1": "rate", "S": "substrate"})
|
733
|
+
|
734
|
+
"""
|
495
735
|
gls = default_init(gls)
|
496
736
|
return _to_tex_export(model).rename_with_glossary(gls).export_document()
|
497
737
|
|
@@ -501,7 +741,32 @@ def get_model_tex_diff(
|
|
501
741
|
m2: Model,
|
502
742
|
gls: dict[str, str] | None = None,
|
503
743
|
) -> str:
|
504
|
-
"""Create LaTeX diff
|
744
|
+
"""Create LaTeX diff showing changes between two models.
|
745
|
+
|
746
|
+
Parameters
|
747
|
+
----------
|
748
|
+
m1
|
749
|
+
First model (considered as base model)
|
750
|
+
m2
|
751
|
+
Second model (compared against the base)
|
752
|
+
gls
|
753
|
+
Optional glossary mapping for renaming model components
|
754
|
+
|
755
|
+
Returns
|
756
|
+
-------
|
757
|
+
str
|
758
|
+
LaTeX document section showing differences between models
|
759
|
+
|
760
|
+
Examples
|
761
|
+
--------
|
762
|
+
>>> from mxlpy import Model
|
763
|
+
>>> m1 = Model().add_parameter("k1", 0.1)
|
764
|
+
>>> m2 = Model().add_parameter("k1", 0.2)
|
765
|
+
>>> diff = get_model_tex_diff(m1, m2)
|
766
|
+
>>> "Model changes" in diff and "Parameters" in diff
|
767
|
+
True
|
768
|
+
|
769
|
+
"""
|
505
770
|
gls = default_init(gls)
|
506
771
|
section_label = "sec:model-diff"
|
507
772
|
|
mxlpy/meta/source_tools.py
CHANGED
@@ -24,6 +24,8 @@ __all__ = [
|
|
24
24
|
|
25
25
|
@dataclass
|
26
26
|
class Context:
|
27
|
+
"""Context for converting a function to sympy expression."""
|
28
|
+
|
27
29
|
symbols: dict[str, sympy.Symbol | sympy.Expr]
|
28
30
|
caller: Callable
|
29
31
|
parent_module: ModuleType | None
|
@@ -34,6 +36,7 @@ class Context:
|
|
34
36
|
caller: Callable | None = None,
|
35
37
|
parent_module: ModuleType | None = None,
|
36
38
|
) -> "Context":
|
39
|
+
"""Update the context with new values."""
|
37
40
|
return Context(
|
38
41
|
symbols=self.symbols if symbols is None else symbols,
|
39
42
|
caller=self.caller if caller is None else caller,
|
@@ -44,7 +47,26 @@ class Context:
|
|
44
47
|
|
45
48
|
|
46
49
|
def get_fn_source(fn: Callable) -> str:
|
47
|
-
"""Get the string representation of a function.
|
50
|
+
"""Get the string representation of a function.
|
51
|
+
|
52
|
+
Parameters
|
53
|
+
----------
|
54
|
+
fn
|
55
|
+
The function to extract source from
|
56
|
+
|
57
|
+
Returns
|
58
|
+
-------
|
59
|
+
str
|
60
|
+
String representation of the function's source code
|
61
|
+
|
62
|
+
Examples
|
63
|
+
--------
|
64
|
+
>>> def example_fn(x): return x * 2
|
65
|
+
>>> source = get_fn_source(example_fn)
|
66
|
+
>>> print(source)
|
67
|
+
def example_fn(x): return x * 2
|
68
|
+
|
69
|
+
"""
|
48
70
|
try:
|
49
71
|
return inspect.getsource(fn)
|
50
72
|
except OSError: # could not get source code
|
@@ -52,7 +74,31 @@ def get_fn_source(fn: Callable) -> str:
|
|
52
74
|
|
53
75
|
|
54
76
|
def get_fn_ast(fn: Callable) -> ast.FunctionDef:
|
55
|
-
"""Get the source code of a function as an AST.
|
77
|
+
"""Get the source code of a function as an AST.
|
78
|
+
|
79
|
+
Parameters
|
80
|
+
----------
|
81
|
+
fn
|
82
|
+
The function to convert to AST
|
83
|
+
|
84
|
+
Returns
|
85
|
+
-------
|
86
|
+
ast.FunctionDef
|
87
|
+
Abstract syntax tree representation of the function
|
88
|
+
|
89
|
+
Raises
|
90
|
+
------
|
91
|
+
TypeError
|
92
|
+
If the input is not a function
|
93
|
+
|
94
|
+
Examples
|
95
|
+
--------
|
96
|
+
>>> def example_fn(x): return x * 2
|
97
|
+
>>> ast_tree = get_fn_ast(example_fn)
|
98
|
+
>>> isinstance(ast_tree, ast.FunctionDef)
|
99
|
+
True
|
100
|
+
|
101
|
+
"""
|
56
102
|
tree = ast.parse(textwrap.dedent(get_fn_source(fn)))
|
57
103
|
if not isinstance(fn_def := tree.body[0], ast.FunctionDef):
|
58
104
|
msg = "Not a function"
|
@@ -61,6 +107,27 @@ def get_fn_ast(fn: Callable) -> ast.FunctionDef:
|
|
61
107
|
|
62
108
|
|
63
109
|
def sympy_to_inline(expr: sympy.Expr) -> str:
|
110
|
+
"""Convert a sympy expression to inline Python code.
|
111
|
+
|
112
|
+
Parameters
|
113
|
+
----------
|
114
|
+
expr
|
115
|
+
The sympy expression to convert
|
116
|
+
|
117
|
+
Returns
|
118
|
+
-------
|
119
|
+
str
|
120
|
+
Python code string for the expression
|
121
|
+
|
122
|
+
Examples
|
123
|
+
--------
|
124
|
+
>>> import sympy
|
125
|
+
>>> x = sympy.Symbol('x')
|
126
|
+
>>> expr = x**2 + 2*x + 1
|
127
|
+
>>> sympy_to_inline(expr)
|
128
|
+
'x**2 + 2*x + 1'
|
129
|
+
|
130
|
+
"""
|
64
131
|
return cast(str, pycode(expr, fully_qualified_modules=True))
|
65
132
|
|
66
133
|
|
@@ -70,7 +137,32 @@ def sympy_to_fn(
|
|
70
137
|
args: list[str],
|
71
138
|
expr: sympy.Expr,
|
72
139
|
) -> str:
|
73
|
-
"""Convert a sympy expression to a python function.
|
140
|
+
"""Convert a sympy expression to a python function.
|
141
|
+
|
142
|
+
Parameters
|
143
|
+
----------
|
144
|
+
fn_name
|
145
|
+
Name of the function to generate
|
146
|
+
args
|
147
|
+
List of argument names for the function
|
148
|
+
expr
|
149
|
+
Sympy expression to convert to a function body
|
150
|
+
|
151
|
+
Returns
|
152
|
+
-------
|
153
|
+
str
|
154
|
+
String representation of the generated function
|
155
|
+
|
156
|
+
Examples
|
157
|
+
--------
|
158
|
+
>>> import sympy
|
159
|
+
>>> x, y = sympy.symbols('x y')
|
160
|
+
>>> expr = x**2 + y
|
161
|
+
>>> print(sympy_to_fn(fn_name="square_plus_y", args=["x", "y"], expr=expr))
|
162
|
+
def square_plus_y(x: float, y: float) -> float:
|
163
|
+
return x**2 + y
|
164
|
+
|
165
|
+
"""
|
74
166
|
fn_args = ", ".join(f"{i}: float" for i in args)
|
75
167
|
|
76
168
|
return f"""def {fn_name}({fn_args}) -> float:
|
@@ -82,7 +174,33 @@ def fn_to_sympy(
|
|
82
174
|
fn: Callable,
|
83
175
|
model_args: list[sympy.Symbol | sympy.Expr] | None = None,
|
84
176
|
) -> sympy.Expr:
|
85
|
-
"""Convert a python function to a sympy expression.
|
177
|
+
"""Convert a python function to a sympy expression.
|
178
|
+
|
179
|
+
Parameters
|
180
|
+
----------
|
181
|
+
fn
|
182
|
+
The function to convert
|
183
|
+
model_args
|
184
|
+
Optional list of sympy symbols to substitute for function arguments
|
185
|
+
|
186
|
+
Returns
|
187
|
+
-------
|
188
|
+
sympy.Expr
|
189
|
+
Sympy expression equivalent to the function
|
190
|
+
|
191
|
+
Examples
|
192
|
+
--------
|
193
|
+
>>> def square_fn(x):
|
194
|
+
... return x**2
|
195
|
+
>>> import sympy
|
196
|
+
>>> fn_to_sympy(square_fn)
|
197
|
+
x**2
|
198
|
+
>>> # With model_args
|
199
|
+
>>> y = sympy.Symbol('y')
|
200
|
+
>>> fn_to_sympy(square_fn, [y])
|
201
|
+
y**2
|
202
|
+
|
203
|
+
"""
|
86
204
|
fn_def = get_fn_ast(fn)
|
87
205
|
fn_args = [str(arg.arg) for arg in fn_def.args.args]
|
88
206
|
sympy_expr = _handle_fn_body(
|