Group Abstract Group Abstract

Message Boards Message Boards

Solve with ConditionalExpression at boundary?

Posted 9 years ago

Hello,

Please look into attached file. I’m using Mathematica Solve function to solve some simple equations from physics. One of the equations is an If function which defines function value when a condition is met. Solve finds almost correct solution which itself is a ConditionalExpression. For independent variable ? = 90° the answer given by Solve is in error. It seems that Solve forgets the case when Cos equals 0. Why? Thanks.

Regards/Mikael

Attachments:
POSTED BY: Mikael Hakman
11 Replies
Posted 9 years ago

I received an answer from Chris Degen via Stackoverflow. He points out that specifying ? = 90.0 (note the decimal point) solves the problem. This is because Cos[90.0 Degrees] is 6.123233995736766E-17 whereas Cos[90 Degrees] is 0. The solution is the same but we are fooling it with finite machine precision. If I ask me, I would say that this is a bug in equation solver in Mathematica.

The solution produced by Solve[] should test for Cos[] >= 0. Now it tests for Cos[] > 0 which is not true for Cos[90°].

Thanks

POSTED BY: Mikael Hakman
Posted 9 years ago

I received an answer from Chris Degen via Stackoverflow. He points out that specifying ? = 90.0 (note the decimal point) solves the problem. This is because Cos[90.0 Degrees] is 6.123233995736766E-17 whereas Cos[90 Degrees] is 0. The solution is the same but we are fooling it with finite machine precision. If I ask me, I would say that this is a bug in equation solver in Mathematica.

The solution produced by Solve[] should test for Cos[] >= 0. Now it tests for Cos[] > 0 which is not true for Cos[90°].

Thanks

POSTED BY: Mikael Hakman
Posted 9 years ago

Just to make things clearer.

If you look at the original solution from Solve[] in the attached file then you can clearly see that Cos[] is tested whether it is > 0. It should be tested whether it is >= 0. The Reduce[] solution produces error at ? = 0 but not at ? = 90 instead.

Thanks

POSTED BY: Mikael Hakman
Posted 9 years ago

No, you are using wrong condition! My condition says that the friction force must be >= 0. This is what physics says. Your condition says that the vertical component of F must be >= -1 which is something different and there is no such limit in physics.

If I use Reduce[] as you propose then I get error when ? = 0 but right when ? = 90. There is a problem somewhere when Mathematica computes functions at a boundary (0 or 90 in this case).

The original question is not answered and original problem is not solved.

Thanks.

POSTED BY: Mikael Hakman

My example is non-physical. It's just a simpler version of your same math problem.

If we use your full example with reduce and set theta = 0, we can only deduce that F <= -1500. That seems reasonable. What should it be giving? If we follow it's logic, you're asking Reduce to look at this:

0 == If[(2 (1500 + F))/5 >= 0, 2/5 (1500 + F Cos[0]), 0]

Which is just this:

Reduce[0 == If[F >= -1500, 2/5 (1500 + F ), 0], F]

Or more simply:

Reduce[0 == If[F >= -1500, (1500 + F ), 0], F]

It seems reasonable that the answer to this is F <= -1500. What would you expect it to be?

POSTED BY: Sean Clarke
Posted 9 years ago

If you use my full example, then using Reduce[] the answer should be False for 0 <= ? <= ArcTan[2/5]. It Should be a positive number otherwise. If you use Solve[] then the answer should be Undefined for the same range and positive number otherwise.

Thanks

POSTED BY: Mikael Hakman

The above result walks thru the case for when theta is 0 and demonstrates that result should be F <= -1500. This is also the result Reduce returns.

If this isn't the result you want, then the problem probably isn't being specified correctly. For example, if negative values of F are unphysical, you might need to add that as a condition.

But either way, Reduce and Solve aren't doing anything incorrect. Even if (and I'd agree) it'd be preferable that Cos[theta] == 0 wasn't a separate case in Reduce's output and Solve handled that case.

Using a floating point value for input is probably inadvisable. But you can intentionally insert small amounts of error into your calculations and that will usually prevent you from hitting spots where Solve's generic inequality is problematic.

POSTED BY: Sean Clarke
Posted 9 years ago

I’m not sure that you understand the problem. Physics don’t limit the value of F. It can be whatever the experimenter chooses it to be, >0, =0, <0, in any direction.

Please refer to the bookshelf figure below.

Bookshelf

Computed F value is actually an advice to experimenter that with given choice of ? he should apply at least force F if he wants the bookshelf to start gliding over the floor. Therefore F = {Undefined} for 0 <= ? <= ArcTan[Subscript[[Mu], S] – the bookshelf will newer glide in this ? range. F should be Subscript[[Mu], S] Subscript[F, N] for ArcTan[Subscript[[Mu], S] < ? <= 90°.

Physics do limit value of Subscript[F, F]. It must be non-negative. It is the friction force and as such it cannot be negative. The lowest value it can have is 0. The condition is:

Subscript[F, F] := If[Subscript[\[Mu], S] Subscript[F, N] >= 0, Subscript[\[Mu], S] Subscript[F, N], 0] 

where Subscript[[Mu], S] is friction coefficient and Subscript[F, N] is normal force:

Subscript[F, N] := Subscript[F, V] + W := 1500 + F Cos[\[Degree] \[Theta]]

in this particular experiment. Whenever Subscript[F, N] gets negative because of Cos[?] or because of F (the bookshelf could be pushed instead of dragged) then Subscript[F, F] shall be 0 and F should be {Undefined}

If you look at the solution produced by Solve[] in my original post then you can see the condition for F to be computed:

(Sin[?] > 2/5 Cos[?] && Cos[?] > 0) || 
(Sin[?] < 0 && Cos[?] > 0) || 
(Sin[?] < 2/5 Cos[?] && Cos[?] < 0) || 
(Cos[?] < 0 && Sin[?] > 0)

The first and the second test should test for Cos[?] >= 0 then the solution would be flawless.

In my opinion there is a bug somewhere in Mathematica.

Thanks

POSTED BY: Mikael Hakman
Posted 9 years ago

Thanks Sean, I changed the code according to your comment.

The results are the same as before – ConditionalExpression[] produced by Solve[] doesn’t include case Cos[90 Degree] = 0. It tests whether Cos is > 0 but not if it is = 0. So the problem remains.

POSTED BY: Mikael Hakman

tl;dr Try using Reduce.


Consider the equation:

3(x-1)/(x-1) 

Is this equal to 3? We'd normally say so, but there is a difference between the two. They don't agree at a certain point (x->1). So we say that they are "generically equal". This means you can expect them to agree except at specific points. Normally, humans don't worry about the difference when we're doing math on a chalkboard because we're very co-operative and anticipate what is needed. But algorithms can't do this. They obey very strict rules instead of being co-operative while doing algebra.

Generic equality produces all sorts of confusion. It's not a topic taught in Math classes. There's a short tutorial on it: https://reference.wolfram.com/language/tutorial/GenericAndNonGenericSolutions.html

But the moral of the story is that you shouldn't be too surprised when there are specific points at which two "equal" equations don't agree.


Now to look at your specific example, let's first create a simplified version of your problem:

Solve[F Sin[theta] == Piecewise[{{1, F*Cos[theta] >= -1}}, 0], F, Reals]

ConditionalExpression[
Csc[theta], 
(Cos[theta] > 0 && Sin[theta] > 0) || (Cos[theta] > 0 && 
Cos[theta] + Sin[theta] < 0) || (Cos[theta] < 0 && 
Sin[theta] < 0) || (Cos[theta] < 0 && 
Cos[theta] + Sin[theta] > 0)]

Anytime you see a problem like this, please try to create a simpler version of the problem like the one above. It's often very instructive.

If we check this ConditionalExpression for when theta is equal to Pi/2, we'll see it's not defined. Just like in your example.

We can plot the values of theta when this has a solution using NumberLinePlot. It is clear then that this doesn't give a solution for plus or minus Pi/2 or 90 degrees. Some algebra happened where this part of the solution was ignored. That happens with Solve.

But according to the documentation we can use Reduce instead of Solve. Reduce doesn't use generic equality.

mySolution = 
 Reduce[F Sin[theta] == Piecewise[{{1, F*Cos[theta] >= -1}}, 0], F, Reals]

(Cos[theta] < 
    0 && ((Sin[theta] < 0 && F == Csc[theta]) || (Sin[theta] == 0 && 
       F > -Sec[theta]) || (Sin[theta] == -Cos[theta] && 
       F == -Sec[theta]) || (Sin[theta] > -Cos[theta] && 
       F == Csc[theta]))) || (Cos[theta] == 
    0 && ((Sin[theta] < 0 && F == Csc[theta]) || (Sin[theta] > 0 && 
       F == Csc[theta]))) || (Cos[theta] > 
    0 && ((Sin[theta] < -Cos[theta] && 
       F == Csc[theta]) || (Sin[theta] == -Cos[theta] && 
       F == -Sec[theta]) || (Sin[theta] == 0 && 
       F < -Sec[theta]) || (Sin[theta] > 0 && F == Csc[theta])))

That's some very complicated output, but let's see what happens when we set theta to Pi/2

mySolution /. theta -> Pi/2

F == 1

Which is what we were looking for.

POSTED BY: Sean Clarke

Two points to consider, not related to the answer:

  • You probably want to write 4/10 instead of 0.4. Use symbolic instead of floating point values when using Solve.

  • Use Piecewise instead of If statements when writing out equations. If statements are more for programming than for decribing an equation. You'll find the Piecewise is capable of doing a lot more.

       Piecewise[{{Subscript[\[Mu], S] Subscript[F, N], 2/5 (1500 + F Cos[\[Degree] \[Theta]]) >= 0}, {0, True}}]
    
POSTED BY: Sean Clarke
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard