Repository: sympy/sympy
Pull request: Added assumptions in Dynamicsymbols
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->
Added assumptions to dynamicsymbols
#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234". See
https://github.com/blog/1506-closing-issues-via-pull-requests . Please also
write a comment on that issue linking back to this pull request once it is
open. -->
Fixes #17739

#### Brief description of what is fixed or changed
Added assumptions in dynamicsymbols so it can be positive, real, etc.

#### Other comments


#### Release Notes

<!-- Write the release notes for this release below. See
https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more information
on how to write release notes. The bot will check your release notes
automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
* physics.vector
   * Added assumptions to dynamicsymbols
   * Added test for dynamicsymbols
<!-- END RELEASE NOTES -->


Problem statement:
dynamicsymbols needs to accept assumptions
This is the current behavior:

```
Python 3.6.7 | packaged by conda-forge | (default, Nov 21 2018, 02:32:25) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.8.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import sympy as sm                                                                                                                                                                                         

In [2]: import sympy.physics.mechanics as me                                                                                                                                                                       

In [3]: f = me.dynamicsymbols('f')                                                                                                                                                                                 

In [4]: sm.sqrt(f**2)                                                                                                                                                                                              
Out[4]: sqrt(f(t)**2)

In [5]: sm.sqrt(f**2).simplify()                                                                                                                                                                                   
Out[5]: sqrt(f(t)**2)

In [6]: f = me.dynamicsymbols('f', real=True)                                                                                                                                                                      
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-327862d9c326> in <module>
----> 1 f = me.dynamicsymbols('f', real=True)

TypeError: dynamicsymbols() got an unexpected keyword argument 'real'

In [7]: t = sm.symbols('t')                                                                                                                                                                                        

In [8]: f = sm.Function('f', real=True)(t)                                                                                                                                                                         

In [9]: sm.sqrt(f**2)                                                                                                                                                                                              
Out[9]: Abs(f(t))

In [10]: sm.sqrt(f**2).simplify()                                                                                                                                                                                  
Out[10]: Abs(f(t))

In [11]: sm.__version__                                                                                                                                                                                            
Out[11]: '1.4'
```

It is not possible to set assumptions on the functions generated by `dynamicsymbols()`.

Hints from issue discussion:
It also doesn't seem like the assumption of a function carries to its derivative. I'm not sure how to specify that the derivative can also be assumed to be real.

```
In [13]: fd = f.diff()                                                                                                                                                                                             

In [14]: sm.sqrt(fd**2)                                                                                                                                                                                            
Out[14]: sqrt(Derivative(f(t), t)**2)

In [15]: sm.sqrt(fd**2).simplify()                                                                                                                                                                                 
Out[15]: sqrt(Derivative(f(t), t)**2)
```
Even if the assumptions are manually added to the derivatives it doesn't simplify:

```
In [16]: fdd = sm.Derivative(sm.Derivative(f, t, real=True), t, real=True)                                                                                                                                         

In [17]: sm.sqrt(fdd**2)                                                                                                                                                                                           
Out[17]: sqrt(Derivative(f(t), (t, 2))**2)
```
I would like to work on this issue as I am currently trying to get a hang of the SymPy library.
hi @moorepants  !
this is mridul pandey  may i take this up!!
I would start on passing in the assumptions. The second part of the issue I'm not sure about.

You want something like:

```
def dynamicsymbols(*symbols, level=None, **asumptions):
```

and then pass in the assumptions to the Function calls internal to the function.
Should I start working on the issue?
hi @shivangisrivastava0408 are you working on this ! or i should take this up!!

I am working on it.

On Thu, Oct 24, 2019, 1:45 AM mridulpandey <notifications@github.com> wrote:

> hi @shivangisrivastava0408 <https://github.com/shivangisrivastava0408>
> are you working on this ! or i should take this up!!
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/sympy/sympy/issues/17739?email_source=notifications&email_token=AI7TKIDVYE7XXEJULE5RUGDQQCWHJA5CNFSM4JBM72B2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECCXJLY#issuecomment-545617071>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AI7TKIC55AXFLEKYFF5IHC3QQCWHJANCNFSM4JBM72BQ>
> .
>

okay thanks. :-)
@moorepants as no one has submitted any PR for this issue, I want to start working on this issue so can you assign me this issue.

Commit message: Added test of dynamicsymbols

Patch to review:
diff --git a/sympy/physics/vector/functions.py b/sympy/physics/vector/functions.py
index 6ae2e7369965..a2addcc770ed 100644
--- a/sympy/physics/vector/functions.py
+++ b/sympy/physics/vector/functions.py
@@ -572,7 +572,7 @@ def partial_velocity(vel_vecs, gen_speeds, frame):
     return vec_partials
 
 
-def dynamicsymbols(names, level=0):
+def dynamicsymbols(names, level=0,**assumptions):
     """Uses symbols and Function for functions of time.
 
     Creates a SymPy UndefinedFunction, which is then initialized as a function
@@ -592,15 +592,23 @@ def dynamicsymbols(names, level=0):
     ========
 
     >>> from sympy.physics.vector import dynamicsymbols
-    >>> from sympy import diff, Symbol
+    >>> from sympy import diff, Symbol, sqrt
     >>> q1 = dynamicsymbols('q1')
     >>> q1
     q1(t)
+    >>> q2= dynamicsymbols('q2', real=True)
+    q2(t)
+    >>> q2.is_real
+    True
+    >>> q3= dynamicsymbols('q3', positive=True)
+    q3(t)
+    >>> q3.is_positive
+    True
     >>> diff(q1, Symbol('t'))
     Derivative(q1(t), t)
 
     """
-    esses = symbols(names, cls=Function)
+    esses = symbols(names, cls=Function,**assumptions)
     t = dynamicsymbols._t
     if iterable(esses):
         esses = [reduce(diff, [t] * level, e(t)) for e in esses]
diff --git a/sympy/physics/vector/tests/test_functions.py b/sympy/physics/vector/tests/test_functions.py
index cf8294b4b560..7c47c530c140 100644
--- a/sympy/physics/vector/tests/test_functions.py
+++ b/sympy/physics/vector/tests/test_functions.py
@@ -488,3 +488,12 @@ def test_partial_velocity():
 
     raises(TypeError, lambda: partial_velocity(Dmc.vel(N), u_list, N))
     raises(TypeError, lambda: partial_velocity(vel_list, u1, N))
+
+def test_dynamicsymbols():
+    #tests to check the assumptions applied to dynamicsymbols
+    f1=dynamicsymbols('f1')
+    f2=dynamicsymbols('f2',real=True)
+    f3=dynamicsymbols('f3',positive=True)
+    assert f1.is_real==None
+    assert f2.is_real
+    assert f3.is_positive


Code review comments:
diff_hunk: @@ -488,3 +488,12 @@ def test_partial_velocity():
 
     raises(TypeError, lambda: partial_velocity(Dmc.vel(N), u_list, N))
     raises(TypeError, lambda: partial_velocity(vel_list, u1, N))
+
+def test_dynamicsymbols():
+    #tests to check the assumptions applied to dynamicsymbols
+    f1=dynamicsymbols('f1')
+    f2=dynamicsymbols('f2',real=True)
+    f3=dynamicsymbols('f3',positive=True)
+    assert f1.is_real==None
path: sympy/physics/vector/tests/test_functions.py
text: @user1:
Should be `is None`.