trigsimp, assumptions, and vector magnitudes

93 views
Skip to first unread message

Conrad Schiff

unread,
Jan 21, 2025, 8:56:48 AM1/21/25
to sy...@googlegroups.com
I am writing a textbook on orbital mechanics and I would like to use sympy for certain calculations (e.g., deriving expressions for certain vectors in terms of Keplerian orbital elements) so that the readers realize the power of sympy.  I have a specific problem I am hoping this group could help me with as I am also fairly new to sympy.  Here is a minimum working example:

********************************
from sympy import *

A, INC = symbols('A INC')
zxh = Matrix([[-sin(A)*sin(INC)], [cos(A)*sin(INC)], [0]])
********************************

At this point, I want to unitize 'zxh' so that the sin(INC) divides out.  This is a legitimate step since the range of INC is restricted to 0 to \pi and the sin(INC) is always non-negative (I am ignoring the singularities on the boundaries of 0 and \pi).  I tried the following but I get the errors below.  Some help in coaxing sympy to do what I know can be done would be appreciated.

********************************
mag2_zxh = trigsimp(zxh.dot(zxh))
-> gives sin**2(INC)

mag_zxh = sqrt(mag2_zxh)
   -> gives  sqrt(sin(INC)**2)

zxh/mag_zxh
   -> gives Matrix([[-sin(A)*sin(INC)/sqrt(sin(INC)**2)], [sin(INC)*cos(A)/sqrt(sin(INC)**2)], [0]])

********************************
How can I coax sympy into recognizing that "sin(INC)/sqrt(sin(INC)**2) = 1"?

Thanks for any help,
Conrad Schiff, PhD
Professor of Physics
Capitol Technology University

peter.st...@gmail.com

unread,
Jan 21, 2025, 9:39:30 AM1/21/25
to sy...@googlegroups.com

I guess sympy does not know that INC is real and sin(INC) > 0.

I just tried:

INC = sm.symbols(‘INC’, real=True)

test = sympy.Abs(sympy.sin(INC)) / sympy.sqrt(sympy.sin**2(INC))

 

test = 1 was the result, as expected

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/sympy/CH3PR12MB943223CD74108121BFEDA1D9CFE62%40CH3PR12MB9432.namprd12.prod.outlook.com.

Conrad Schiff

unread,
Jan 21, 2025, 8:27:49 PM1/21/25
to sy...@googlegroups.com
Thank you, Peter but there is not quite what I was looking for.  

Technically your result simply proves that the square root of the square of a real number x is the absolute value of x (\sqrt{x^2} = |x| for x \in reals).  Or in your terms:

    test = |sin(INC)|/\sqrt{sin(INC)^2}  for INC real 

is always, identically, equal to 1.

For my case, sin(INC)/|sin(INC)| is what I am looking at (i.e., the numerator has no absolute value), and it is equal to 1 for my assumptions but how can sympy know that without knowing that I've restricted INC to the range [0,\pi]?  If, for example,  INC were in the range [\pi,2\pi] then sin(INC)/|sin(INC)| = -1.

If there is a way to say something like:

    INC = sm.symbols(‘INC’, real=True,range=[0,pi])

then I say that the result is proved.  But I can't anything like this in the documentation (perhaps I simply don't know where to look).

Conrad
















From: sy...@googlegroups.com <sy...@googlegroups.com> on behalf of peter.st...@gmail.com <peter.st...@gmail.com>
Sent: Tuesday, January 21, 2025 9:39 AM
To: sy...@googlegroups.com <sy...@googlegroups.com>
Subject: RE: [sympy] trigsimp, assumptions, and vector magnitudes
 

peter.st...@gmail.com

unread,
Jan 22, 2025, 2:22:26 AM1/22/25
to sy...@googlegroups.com

Dear Conrad,

 

I have never seen this range restriction – but then again I use mostly a sub library of sympy, called sympy.physics.mechanics (to set up symbolic equations of motion of multibody systems), so I am no sympy expert at all!

 

Maybe you could ask your question here, too:

https://github.com/sympy/sympy

 

Peter

Conrad Schiff

unread,
Jan 22, 2025, 5:28:07 AM1/22/25
to sy...@googlegroups.com
Thank you, Peter, for both your interest and for pointing me to another place to ask the question.  I certainly would like to see what you are doing with the mechanics module so perhaps you can also point me to your work.

Conrad


Sent: Wednesday, January 22, 2025 2:22 AM

Peter Stahlecker

unread,
Jan 22, 2025, 5:57:11 AM1/22/25
to sy...@googlegroups.com
Dear Conrad,

sympy.physics.mechanics is a package to get symbolic equations of motion of multibody systems of arbitrary complexity. It uses Kane's method.
In github there is a repository called pst-notebooks where I deposited some of the stuff I did. Some examples may be o.k.

I am a retired guy and do all these simulations for fun, no other purpose.

Take care,

Peter


peter.st...@gmail.com

unread,
Jan 22, 2025, 11:30:08 AM1/22/25
to sy...@googlegroups.com

Sangyub Lee

unread,
Jan 23, 2025, 8:05:50 PM1/23/25
to sympy
I’m not sure if this fully addresses your question, but I wanted to share an idea about working with Sympy’s assumptions system when you need something like a (0,1] range.

Sympy’s default assumptions (e.g., positive, real) can feel inflexible, and there isn’t a direct way to specify an interval like (0,1]. However, one possible workaround is to use a known function that naturally stays in the interval (0,1). A classic choice is the logistic sigmoid function:

```python
x = Symbol('x', real=True)
sigmoid = 1 / (1 + exp(-x))
```

The sigmoid has a range of (0,1) for all real x. If you need something that stays in (0,1) symbolically, you can substitute the sigmoid in place of expressions that you want to treat as (0,1)-valued.

For instance, the derivative of the sigmoid function,

```python
dsigmoid = sigmoid.diff(x)
```

has a range of (0, 1/4]. If you want it to go up to 1 instead of 1/4, you can normalize it:

```python
dsigmoid_normalized = dsigmoid / dsigmoid.subs(x, 0)
```

That way, `dsigmoid_normalized` will lie in (0,1].

Suppose you have:

```python

A, INC = symbols('A INC')
zxh = Matrix([[-sin(A)*sin(INC)], [cos(A)*sin(INC)], [0]])
```

If you only need a symbolic expression with a value in (0,1] rather than specifically sin(INC), you can do a direct substitution with the normalized sigmoid derivative:

```python
zxh_sub = zxh.subs(sin(INC), dsigmoid_normalized)
```

Now, if you also want to normalize the resulting vector or matrix:

```python
zxh_normalized = zxh_sub.normalized()
```

and then simplify:

```python
result = simplify(zxh_normalized)
print(result)
```

You might see absolute values in the denominator, but that often simplifies if you add further assumptions (you may be missing the variable A can be real)

Another area of interest is whether Sympy can automatically prove statements like  dsigmoid_normalized <= 1 by simplification.
If it is possible, then even with restricted supply of assumptions like real, positive, we can possibly extend the system to handle more broader set of assumptions like interval assumption.
Reply all
Reply to author
Forward
0 new messages