Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pymbolic
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Andreas Klöckner
pymbolic
Commits
e8de9f50
Commit
e8de9f50
authored
5 years ago
by
zachjweiner
Browse files
Options
Downloads
Patches
Plain Diff
add test for nonsmooth/discontinuous differentiating
parent
81afd8a2
No related branches found
No related tags found
1 merge request
!26
Add more math functions
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
pymbolic/mapper/differentiator.py
+12
-11
12 additions, 11 deletions
pymbolic/mapper/differentiator.py
test/test_pymbolic.py
+19
-0
19 additions, 0 deletions
test/test_pymbolic.py
with
31 additions
and
11 deletions
pymbolic/mapper/differentiator.py
+
12
−
11
View file @
e8de9f50
...
...
@@ -33,7 +33,7 @@ import pymbolic.mapper.evaluator
def
map_math_functions_by_name
(
i
,
func
,
pars
,
allow_non_smooth
=
False
,
allow_discontinu
ity
=
False
):
allow_discontinu
ous
=
False
):
try
:
f
=
pymbolic
.
evaluate
(
func
,
{
"
math
"
:
math
,
"
cmath
"
:
cmath
})
except
pymbolic
.
mapper
.
evaluator
.
UnknownVariableError
:
...
...
@@ -62,16 +62,17 @@ def map_math_functions_by_name(i, func, pars,
return
make_f
(
"
exp
"
)(
*
pars
)
elif
f
is
math
.
fabs
and
len
(
pars
)
==
1
:
if
allow_non_smooth
:
return
make_f
(
"
sign
"
)(
*
pars
)
from
pymbolic.functions
import
sign
return
sign
(
*
pars
)
else
:
raise
ValueError
(
"
fabs is not smooth
"
"
, pass allow_non_smooth=True to return sign
"
)
elif
f
is
math
.
copysign
and
len
(
pars
)
==
2
:
if
allow_discontinu
ity
:
if
allow_discontinu
ous
:
return
0
else
:
raise
ValueError
(
"
sign is discontinuous
"
"
, pass allow_discontinu
ity
=True to return 0
"
)
"
, pass allow_discontinu
ous
=True to return 0
"
)
else
:
raise
RuntimeError
(
"
unrecognized function, cannot differentiate
"
)
...
...
@@ -93,7 +94,7 @@ class DifferentiationMapper(pymbolic.mapper.RecursiveMapper):
"""
def
__init__
(
self
,
variable
,
func_map
=
map_math_functions_by_name
,
allow_non_smooth
=
False
,
allow_discontinu
ity
=
False
):
allow_non_smooth
=
False
,
allow_discontinu
ous
=
False
):
"""
:arg variable: A :class:`pymbolic.primitives.Variable` instance
by which to differentiate.
...
...
@@ -103,20 +104,20 @@ class DifferentiationMapper(pymbolic.mapper.RecursiveMapper):
which are not smooth (e.g., ``fabs``), i.e., by ignoring the
discontinuity in the resulting derivative.
Defaults to *False*.
:arg allow_discontinu
ity
: Whether to allow differentiation of
:arg allow_discontinu
ous
: Whether to allow differentiation of
which are not continuous (e.g., ``sign``), i.e., by ignoring the
discontinuity.
Defaults to *False*.
.. versionchanged:: 2019.2
Added *allow_non_smooth* and *allow_discontinu
ity
*.
Added *allow_non_smooth* and *allow_discontinu
ous
*.
"""
self
.
variable
=
variable
self
.
function_map
=
func_map
self
.
allow_non_smooth
=
allow_non_smooth
self
.
allow_discontinu
ity
=
allow_discontinu
ity
self
.
allow_discontinu
ous
=
allow_discontinu
ous
def
rec_undiff
(
self
,
expr
,
*
args
):
"""
This method exists for the benefit of subclasses that may need to
...
...
@@ -138,7 +139,7 @@ class DifferentiationMapper(pymbolic.mapper.RecursiveMapper):
self
.
function_map
(
i
,
expr
.
function
,
self
.
rec_undiff
(
expr
.
parameters
,
*
args
),
allow_non_smooth
=
self
.
allow_non_smooth
,
allow_discontinu
ity
=
self
.
allow_discontinu
ity
)
allow_discontinu
ous
=
self
.
allow_discontinu
ous
)
*
self
.
rec
(
par
,
*
args
)
for
i
,
par
in
enumerate
(
expr
.
parameters
)
)
...
...
@@ -230,9 +231,9 @@ def differentiate(expression,
variable
,
func_mapper
=
map_math_functions_by_name
,
allow_non_smooth
=
False
,
allow_discontinu
ity
=
False
):
allow_discontinu
ous
=
False
):
if
not
isinstance
(
variable
,
(
primitives
.
Variable
,
primitives
.
Subscript
)):
variable
=
primitives
.
make_variable
(
variable
)
return
DifferentiationMapper
(
variable
,
func_mapper
,
allow_non_smooth
=
allow_non_smooth
,
allow_discontinu
ity
=
allow_discontinu
ity
)(
expression
)
allow_discontinu
ous
=
allow_discontinu
ous
)(
expression
)
This diff is collapsed.
Click to expand it.
test/test_pymbolic.py
+
19
−
0
View file @
e8de9f50
...
...
@@ -641,6 +641,25 @@ def test_multiplicative_stringify_preserves_association():
assert_parse_roundtrip
(
"
(-1)*(((-1)*x) / 5)
"
)
def
test_differentiator_flags_for_nonsmooth_and_discontinuous
():
import
pymbolic.functions
as
pf
from
pymbolic.mapper.differentiator
import
differentiate
x
=
prim
.
Variable
(
'
x
'
)
with
pytest
.
raises
(
ValueError
):
differentiate
(
pf
.
fabs
(
x
),
x
)
result
=
differentiate
(
pf
.
fabs
(
x
),
x
,
allow_non_smooth
=
True
)
assert
result
==
pf
.
sign
(
x
)
with
pytest
.
raises
(
ValueError
):
differentiate
(
pf
.
sign
(
x
),
x
)
result
=
differentiate
(
pf
.
sign
(
x
),
x
,
allow_discontinuous
=
True
)
assert
result
==
0
if
__name__
==
"
__main__
"
:
import
sys
if
len
(
sys
.
argv
)
>
1
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment