Mathematica Reduce/Solve: Best way to ask for non-repeating values - wolfram-mathematica

A few times I found I had a system and I need to specify that all variables get different values (ie non-repeating).
I usually do things like this:
k = {a, b, c, d, e, f, g};
Reduce[
a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And ### {0 < # < 8 & /# k}] &&
Times#(Sequence ## (Subsets[k, {2}] /. {x_, y_} -> (x - y))) != 0,
k, Integers]
Where the last part of the Reduce equation
Times#(Sequence ## (Subsets[k, {2}] /. {x_, y_} -> (x - y))) != 0
asks for different values.
Are there better ways to do this? (I mean, not the product equal zero, but to specify I need all variables different)

From the speed viewpoint, you are inducing a large overhead with that product condition. If your solutions are always numbers, you can produce all solutions with Reduce and then filter them - it may be faster in some cases. For example, in the case at hand:
k = {a, b, c, d, e, f, g};
sl = Reduce[ a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And ### {0 < # < 8 & /# k}], k, Integers]
You can do the post-processing, for example like this (perhaps not the best way):
In[21]:= Select[{#, First[k /. Solve[#, k]]} & /# List ## sl,
MatchQ[Tally[#[[2]], Equal][[All, 2]], {1 ..}] &][[All, 1]]
Out[21]= {a == 3 && b == 2 && c == 7 && d == 6 && e == 4 && f == 5 && g == 1}
At least for this particular case, it was much faster.

For smallish problems, post=processing to remove unwanted solutions might be best. For larger problems there are at least two useful approaches.
(1) If the allowed values are say contiguous, or nearly so, could create 0-1 variables for the grid of each original variable and possible value. For example, if your variables are intended to fill out a standard Sudoku array, then x[i,j,k]=1 could be used to indicate that the value in row i, col j, is k. The constraints that e.g. no value in row 1 is repeated would be
Sum[x[1,j,1]==1, {j,9}]
...
Sum[x[1,j,9]==1, {j,9}]
If not all values need to be used in all places (e.g. rows) then these could be made into inequalities instead.
(2) Another approach is to use 0-1 variables for each pair if values that needs to be distinct. We assume there is at least a known upper and lower bound on value ranges. Call it m. So for any pair of variables x and y we know that the difference is between -m and m (could add/subtract ones there, but not essential).
For the pair x[i] and x[j] that need to be distinct, add a new variable 0-1 k[i,j]. The idea is it will need to be 1 if x[i]>x[j] and 0 if x[j]>x[i].*
For this pair we add two equations. I will show them in non-expanded form as that might be slightly easier to understand.
x[i]-x[j] >= k[i,j] + m*(k[i,j]-1)
x[j]-x[i] >= (1-k[i,j]) + m*(-k[i,j])
If x[i]>x[j] then both are satisfied only for k[i,j]==1. Vice versa for x[j]>x[i] and k[i.j]==0.
This might be the preferred method when variables can span a range of values substantially larger than the number of variables, or when far fewer that all pairs are constrained to be distinct values.
Daniel Lichtblau
*It's late Saturday night, so reverse anything I got backwards. Also please fix all typos while you are at it.

Why not supply a uniqueness constraint directly?
k = {a, b, c, d, e, f, g};
uniqueness = {a != b != e};
sl = Reduce[
a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And ### {0 < # < 8 & /# k}] && First#uniqueness , k,
Integers]//Timing
Out[1]= {0.046791, a == 3 && b == 2 && c == 7 && d == 6 && e == 4 && f == 5 && g == 1}
From a cursory glance at your constraints above, most of the uniqueness requirements are self satisfied by the other constraints and setting a≠b≠e fixes all the remaining. There is no need to test for everything. For e.g.,
f = a + b ⇒ f ≠ a & f ≠ b
f = e + g ⇒ f ≠ e & f ≠ g
2f = d + e ⇒ f ≠ d ∵ f ≠ e ⇒ g ≠ d
c = g + d ⇒ c ≠ g & c ≠ d
and so on... You can probably work that out in detail.
I understand this is probably just a test example, and I don't have a smart and fast one stop answer that you can use without thinking about the problem.

Related

Algorithm to precisely compare two exponentiations for very large integers (order of 1 billion)

We want to compare a^b to c^d, and tell if the first is smaller, greater, or equal (where ^ denotes exponentiation).
Obviously, for very large numbers, we cannot explicitely compute these values.
The most common approach in this situation is to apply log on both sides and compare b * log(a) to d * log(c). The issue here is that logs are floating-point operations, and as such we cannot trust our answer with 100% confidence (there might be some values which are incredibly close, and because of floating-point error we get a wrong answer).
Is there an algorithm for solving this problem? I've been scouring the intrernet for this, but I can only find solutions which work for particular cases only (e.g. in which one exponent is a multiple of another), or which use floating point in some way (logarithms, division) etc.
This is sort of two questions in one:
Are they equal?
If not, which one is greater?
As Peter O. observes, it's easiest to build in a language that provides an arbitrary-precision fraction type. I'll use Python 3.
Let's assume without loss of generality that a ≤ c (swap if necessary) and b is relatively prime to d (divide both by the greatest common divisor).
To get at the core of the question, I'm going to assume that a, c > 0 and b, d ≥ 0. Removing this assumption is tedious but not difficult.
Equality test
There are some easy cases where a = 1 or b = 0 or c = 1 or d = 0.
Separately, necessary conditions for a^b = c^d are
i. b ≥ d, since otherwise b < d, which together with a ≤ c implies a^b < c^d;
ii. a is a divisor of c, since we know from (i) that a^b = c^d is a divisor of c^b = c^(b−d) c^d.
When these conditions hold, we can divide through by a^d to reduce the problem to testing whether a^(b−d) = (c/a)^d.
In Python 3:
def equal_powers(a, b, c, d):
while True:
lhs_is_one = a == 1 or b == 0
rhs_is_one = c == 1 or d == 0
if lhs_is_one or rhs_is_one:
return lhs_is_one and rhs_is_one
if a > c:
a, b, c, d = c, d, a, b
if b < d:
return False
q, r = divmod(c, a)
if r != 0:
return False
b -= d
c = q
def test_equal_powers():
for a in range(1, 25):
for b in range(25):
for c in range(1, 25):
for d in range(25):
assert equal_powers(a, b, c, d) == (a ** b == c ** d)
test_equal_powers()
Inequality test
Once we've established that the two quantities are not equal, it's time to figure out which one is greater. (Without the equality test, the code here could run forever.)
If you're doing this for real, you should consult an actual reference on computing elementary functions. I'm just going to try to do the simplest thing that works.
Time for a calculus refresher. We have the Taylor series
−log x = (1−x) + (1−x)^2/2 + (1−x)^3/3 + (1−x)^4/4 + ...
To get a lower bound, truncate the series. To get an upper bound, we can truncate but replace the final term (1−x)^n/n with (1−x)^n/n (1/x), since
(1−x)^n/n (1/x)
= (1−x)^n/n (1 + (1−x) + (1−x)^2 + ...)
= (1−x)^n/n + (1−x)^(n+1)/n + (1−x)^(n+2)/n + ...
> (1−x)^n/n + (1−x)^(n+1)/(n+1) + (1−x)^(n+2)/(n+2) + ...
To get a good convergence rate, we're going to want 0.5 ≤ x < 1, which we can achieve by dividing x by a power of two.
In Python, we'll represent a real number as an infinite generator of shrinking intervals that contain the true value. Once the intervals for b log a and d log c are disjoint, we can determine how they compare.
import fractions
def minus(x, y):
while True:
x_lo, x_hi = next(x)
y_lo, y_hi = next(y)
yield x_lo - y_hi, x_hi - y_lo
def times(b, x):
for lo, hi in x:
yield b * lo, b * hi
def restricted_log(a):
series = 0
n = 0
numerator = 1
while True:
n += 1
numerator *= 1 - a
series += fractions.Fraction(numerator, n)
yield -(series + fractions.Fraction(numerator * (1 - a), (n + 1) * a)), -series
def log(a):
n = 0
while a >= 1:
a = fractions.Fraction(a, 2)
n += 1
return minus(restricted_log(a), times(n, restricted_log(fractions.Fraction(1, 2))))
def less_powers(a, b, c, d):
lhs = times(b, log(a))
rhs = times(d, log(c))
while True:
lhs_lo, lhs_hi = next(lhs)
rhs_lo, rhs_hi = next(rhs)
if lhs_hi < rhs_lo:
return True
if rhs_hi < lhs_lo:
return False
def test_less_powers():
for a in range(1, 10):
for b in range(10):
for c in range(1, 10):
for d in range(10):
if a ** b != c ** d:
assert less_powers(a, b, c, d) == (a ** b < c ** d)
test_less_powers()

highest product of 3 implementation in haskell

I'd like the algorithm for highest product of 3 problem implemented in haskell. Here's the problem statement:
Given an array of integers, find the highest product you can get from
three of the integers.
For example given [1, 2, 3, 4], the algorithm should return 24. And given [-10, -10, 5, 1, 6], the highest product of 3 would be 600 = -10*-10*6.
My attempt (assumed no negatives for the first try):
sol2' a b c [] = a*b*c
sol2' a b c (x:xs) = sol2' a' b' c' xs
where
a' = if (x > a) then x else a
b' = if (x > a && a > b) then a else b
c' = if (x > a && a > b && b > c) then b else c
sol2 li = sol2' a b c li
where a = 0
b = 0
c = 0
I tested the implementation with [3, 5, 1, 2, 4, 10, 0, 4, 8, 11] but the return value is 550, which is supposed to be 880.
Positive numbers
You are on the right track in the sense that you look for the highest numbers. The problem is however that a, b and c are not always ordered.
Indeed say for instance that we have the numbers [6,2,4]. Then the way (a,b,c) will evolve through the recursion is:
(0,0,0) -> (6,0,0) -> (2,6,0) -> (4,2,6)
But now a=4, so that means that if we now encounter 3, we will not replace that value, whereas we can do this since we can remove the 2.
Although there are many ways to solve this, probably the best way to do this is to maintain order: ensure that a <= b <= c.
So we can use:
sol1 = sol2' (0,0,0)
sol2' (a,b,c) [] = a*b*c
sol2' t#(a,b,c) (x:xs) = sol2' f xs
where f | x >= c = (b,c,x)
| x >= b = (b,x,c)
| x > a = (x,b,c)
| otherwise = t
this produces the expected:
Prelude> sol1 [1,2,3,4]
24
Prelude> sol1 [3, 5, 1, 2, 4, 10, 0, 4, 8, 11]
880
Intermezzo: keep track of numbers if negative are present
Your program first takes (0,0,0) as the first three values. But in case for instance the list contains only negative numbers (i.e. [-1,-2,-3]) we of course want to keep track of these first. We can do this for instance by initializing our tuple with elements from the list:
import Data.List(sort)
sol1 (xa:xb:xc:xs) = sol2' (a,b,c) xs
where [a,b,c] = sort [xa,xb,xc]
So now we take the first three elements, sort these, and use these as the first tuple. The remaining of the list is processed. This function will error in case sol1 is not given a list with at least three elements, but in that case there probably is no answer. We can use a Maybe to handle the fact that the function is non-total.
all numbers
Of course we also want to deal with negative numbers. Multiplying two negative numbers results in a positive number. So by keeping track of the two smallest numbers as well, we can then do the math properly. So first we will use another argument (d,e) to keep track of the smallest numbers with d <= e:
sol1_all = sol2_all' (0,0,0) (0,0)
sol2_all' (a,b,c) (d,e) [] = -- ...
sol2_all' t#(a,b,c) u#(d,e) (x:xs) = sol2_all' f g xs
where f | x >= c = (b,c,x)
| x >= b = (b,x,c)
| x > a = (x,b,c)
| otherwise = t
g | x <= d = (x,d)
| x <= e = (d,x)
| otherwise = u
So now we have obtained the greatest numbers (a,b,c) and the smallest numbers (d,e). If d and e are indeed negative, then the only way to produce a large . So now we have the following possibilities to consider a*b*c and c*d*e. So we can write it as:
sol2_all' (a,b,c) (d,e) [] = max (a*b*c) (c*d*e)
sol2_all' t#(a,b,c) u#(d,e) (x:xs) = sol2_all' f g xs
where f | x >= c = (b,c,x)
| x >= b = (b,x,c)
| x > a = (x,b,c)
| otherwise = t
g | x <= d = (x,d)
| x <= e = (d,x)
| otherwise = u
Note however that this will not always produce the correct result here because we can count two numbers in both tuples. We can solve this by properly initializing the tuples:
import Data.List(sort)
sol1_all (xa:xb:xc:xs) = sol2_all' (a,b,c) (a,b) xs
where [a,b,c] = sort [xa,xb,xc]
sol2_all' (a,b,c) (d,e) [] = max (a*b*c) (c*d*e)
sol2_all' t#(a,b,c) u#(d,e) (x:xs) = sol2_all' f g xs
where f | x >= c = (b,c,x)
| x >= b = (b,x,c)
| x > a = (x,b,c)
| otherwise = t
g | x <= d = (x,d)
| x <= e = (d,x)
| otherwise = u
Rationale behind picking different (possibly equivalent) elements
How do we know that we will not use an element twice? Since we only use a*b*c or c*d*e this will - in the case of a list with three element - boils down to max(a*b*c,a*b*c) (a, b, and c here the result of sort). So uniqueness is guaranteed. Since we will only add elements in the first tuple if these are at least greater than a, and less than b, we know that in order for an x to be added in both tuples, it should be a <= x <= b. In that case we will obtain tuples (x,b,c) and (a,x). But since we evaluate in that case x*b*c and a*x*c, x will thus not occur in any expression twice.
Leetcode challenge
I submitted a Python version of this code to the Leetcode Challenge and it was accepted:
class Solution:
def maximumProduct(self, nums):
a,b,c = d,e,_ = sorted(nums[:3])
for x in nums[3:]:
if x >= c:
a,b,c = b,c,x
elif x >= b:
a,b = b,x
elif x >= a:
a = x
if x <= d:
d,e = x,d
elif x < e:
e = x
return max(a*b*c,c*d*e)
There are somewhat more efficient solutions, but I would lean toward something more straightforward like:
import Data.List (subsequences)
f :: (Num a, Ord a) => [a] -> a
f = maximum . map product . filter ((==3) . length) . subsequences
Thinking about functional algorithms as sequences of transformations on collections makes them much more idiomatic than transforming imperative loops into recursive functions.
Note if you are doing this with really long lists where efficiency is a concern, you can sort the list first, then take the lowest two and the highest three, and the algorithm will still work:
takeFirstLast xs = (take 2 sorted) ++ (drop (length sorted - 3) sorted)
where sorted = sort xs
However, my original way is plenty fast up to lists of size 100 or so, and is a lot easier to understand. I don't believe in sacrificing readability for speed until I'm told it's an actual requirement.

Write an algorithm that tells me if two and only two numbers in three are the same

Deceptively simple algorithm question I came across. I'm trying to pull it off in 3 or less operations, and I'm reasonably convinced it can be solved with math, but I can't figure it out (and the source for the question didn't have an answer).
EDIT:
(a[0] == a[1] + a[0] == a[2] + a[1] == a[2]) == 1
is what I originally thought, but I'd like to see if it can be done in less operations (1 comparison being an operation).
Assuming the 3 numbers are a, b and c,
(b == c) ? (a != c) : (a == b || a == c)
If (a, b, c) = (1, 1, 1), then we will call b == c (true) and then a != c (false) and done.
If (a, b, c) = (1, 1, 2), then we will call b == c (false) and then a == b (true) and done.
If (a, b, c) = (1, 2, 1), then we will call b == c (false) and then a == b (false) and a == c (true) and done.
If (a, b, c) = (2, 1, 1), then we will call b == c (true) and then a != c (true) and done.
If (a, b, c) = (1, 2, 3), then we will call b == c (false) and then a == b (false) and a == c (false) and done.
So at most 3 comparison are performed.
There are also 2 conditional branching points at ?: and || but OP does not count it.
Depending on what you consider to be an "operation"...
The following uses only 3 comparisons out of the array. There is a forth comparison though, the == 1 to ensure that there is exactly one match. I believe you could use a ton of branching to conditionally eliminate some of the comparisons, but if this is an optimization, the branching would probably make it perform worse.
There are exactly 3 outcomes:
none of the values will be the same (sum is zero)
two will be the same (sum is one)
all three are the same (sum is three)
if (((array[0] == array[1]) +
(array[1] == array[2]) +
(array[0] == array[2])) == 1)
{
// stuff
}
This trades comparisons with branching to achieve a maximum of 3 comparisons and a routes that only requires 2:
if (array[0] == array[1]) // if these are equal
return !(array[1] == array[2]); // and these are not equal, return true
else
return (array[0] == array[2]) || (array[1] == array[2]); // otherwise, if these are equal, we already know the others are not equal because we already tested them so return true
You can write the expression:
((b == a) | (b == c)) ^ (a == c)
which has constant cost, always performs three comparisons and two logic operations. Having no branches, it ought to go easy on the processor.
Depending on the architecture,
((b == a) || (b == c)) ^ (a == c)
might be faster (this one performs two or three comparisons, one logic operation and one branch).
My try...
return (ab ? (!ac) : (ac ? true : bc));
Where:
ab = (a==b)
ac = (a==c)
bc = (b==c)
This uses 2 or 3 comparisons, at the expense of conditional jumps sometimes. Let us check the number of operations on each case:
a == c == b: (a==b) + jump + (a==c) + negation [returns a!=c] 4 operations
a == b != c: the same as above, 4 operations
a != b == c: (a==b) + jump + (a==c) + jump + (b==c) [returns this value] 5 operations
a == c != b: (a==b) + jump + (a==c) + jump [returns true] 4 operations
a != c != b: the same as above, 4 operations
Of course, this depends on your concept of operation... If jumps are not considered...

Converting vector equation to a list of equations in Mathematica

Due to DSolve syntax, systems of differential equations have to be given as lists of equations and not as a vector equation (Unlike Solve, which accepts both).
So my simple question is how to convert a vector equation such as:
{f'[t],g'[t]}=={{a,b},{c,d}}.{f[t],g[t]}
To list of equations:
{f'[t]==a*f[t]+b*g[t],g'[t]==c*f[t]+d*g[t]}
I think I knew once the answer, but I can't find it now and I think it could benefit others as well.
Try using Thread:
Thread[{f'[t], g'[t]} == {{a, b}, {c, d}}.{f[t], g[t]}]
(* {f'[t] == a f[t] + b g[t], g'[t] == c f[t] + d g[t] *)
It takes the equality operator == and applies it to each item within a list with the same Head.
The standard answer to this question is that which Brett presented,
i.e., using Thread.
However, I find that for use in DSolve, NDSolve, etc... the command LogicalExpand is better.
eqn = {f'[t], g'[t]} == {{a, b}, {c, d}}.{f[t], g[t]};
LogicalExpand[eqn]
(* f'[t] == a f[t] + b g[t] && g'[t] == c f[t] + d g[t] *)
It doesn't convert a vector equation to a list, but it is more useful since it automatically flattens out matrix/tensor equations and combinations of vector equations.
For example, if you wanted to add initial conditions to the above differential equation, you'd use
init = {f[0], g[0]} == {f0, g0};
LogicalExpand[eqn && init]
(* f[0] == f0 && g[0] == g0 &&
f'[t] == a f[t] + b g[t] && g'[t] == c f[t] + d g[t] *)
An example of a matrix equation is
mEqn = Array[a, {2, 2}] == Partition[Range[4], 2];
Using Thread here is awkward, you need to apply it multiple times and Flatten the result. Using LogicalExpand is easy
LogicalExpand[mEqn]
(* a[1, 1] == 1 && a[1, 2] == 2 && a[2, 1] == 3 && a[2, 2] == 4 *)

FullSimply Inequalities and then rearranging them in Mathematica 7

I am using Mathematica 7 in the notebook interface and I want to rearrange an inequality so that I get a certain variable on one side. For eg.
FullSimplify[x^3+L+r>3x^3+2r]
Gives
L > r + 2 x^3
However, I want :
r < L-2x^3
Is there anyway we can instruct FullSimplify to order variables in a particular way? I am using Mathematica for presentation as well so, the way I arrange the variables is important to me.
Thanks
SR
Edit: I tried Reduce, while that works for this example, it does not work for the actual expression I have, I get an error saying,
This system cannot be solved with the methods available to Reduce.
Edit: here is the actual expression:
{L - (m^2 ((-2 + e)^2 \[Delta] + (5 +
2 e (-7 + 4 e)) \[Tau]) \[Omega])/(36 (2 - 3 e + e^2)^2)} > {0}
I want this to be displayed in the form of \[delta]< *something*
Thanks!
First of all, getting Mathematica to output something exactly as you would like it is something of a black art, and requires a lot of patience. That said, if you apply Reduce to your original expression, as per Belisarius, you'd get
In[1]:=Reduce[x^3 + L + r > 3 x^3 + 2 r, r, Reals]
Out[1]:= r < L - 2 x^3
However, as you pointed out, this isn't the full expression, and Reduce produces what can only be described as a less than helpful answer when applied to it. It is at this point where patience and a lot of extra processing is required. I'd start with
In[2]:=Reduce[ <full expression>, Delta, Reals] // LogicalExpand // Simplify
While this doesn't give you a clean answer, it is better than before and reveals more of the structure of your solution. (I would not use FullSimplify as that mixes Delta in with the other terms.) At this point, we need to know more about the terms themselves, and the output from In[2] is not quite as useful as we want.
I'd re-expand this with LogicalExpand which gives you twelve terms that are significantly simpler than the what Reduce alone gives. (You'll note that only the last six terms actually involve Delta, so I'd check that the variable conditions actually match those.) Selecting those last six terms only,
In[3]:=%2[[-6;;]] // Simplify
Out[3]:= m != 0
&& ((Omega > 0 && Delta < something) || (Omega > 0 && Delta < something else)
&& (1 < e < 2 || e < 1 || e > 2)
The third term is tautological, but Simplify nor FullSimplify can't seem to remove it. And we're really only interested in the middle term anyway. If Omega > 0 your expression can then be extracted via %[[2,1,2]].
Putting this all together in one expression:
In[4]:=Simplify[LogicalExpand[Reduce[<expression>, Delta, Reals]]][[-6;;]] //
Simplify // #[[2,1,2]]&
Out[4]:= Delta < something
After writing that out, I realized that there is a much simpler way to approach this. I'd redo line 2, above, as follows:
In[5]:= Reduce[ <full expression>, Delta, Reals] // LogicalExpand // Simplify //
Cases[#, ___ && Delta < _ && ___, Infinity]&
Out[5]:= {Omega > 0 && Delta < something}
Or, provided you really do know that m != 0 and Omega > 0 you can do
In[6]:= Reduce[ <expr> && m!=0 && Omega > 0, Delta, Reals ] // LogicalExpand //
Simplify // #[[2]]&
Reduce[x^3 + L + r > 3 x^3 + 2 r, r, Reals]
Will do.
As I don't use Mathematica for editing or presentation, perhaps someone else may come with some extra advice.
Edit
based on your comment, you may try:
Reduce[{L - (m^2 ((-2 + e)^2 Delta + (5 +
2 e (-7 + 4 e)) Tau) Omega)/(36 (2 - 3 e + e^2)^2) > 0}, Delta, Reals]
Where I corrected some syntax errors. But you'll find that the resulting expression is rather unpleasant. To simplify it further you need to know the valid ranges for your vars. Please post that info if you have it.
HTH!
Inspect the output of
r=Simplify[Reduce[L-(m^2((-2+e)^2\\[Delta]+(5+2e(-7+4e))\\[Tau])\\[Omega])/(36(2-3e+e^2)^2)>0,\\[Delta],Reals]]
to see that
r[[2,1,1,1]] gives \\[Delta]>expr,
but
r[[2, 1, 2, 2]] gives \\[Delta]< expr,
because the sign of \[Omega] in the denominator of expr. All this ignores the other conditions on the values of L, e, m and \[Omega] that will change the result and different versions of Mathematica may change the form of the result from Simplify[Reduce[]] which will invalidate all of this.
Part of the difficulty in reducing the expressions returned by Reduce[] and LogicalExpand[] is that the supplied expression involves division by zero when e=1 or =2.
I get something bearably compact with
Assuming[{
(L | m | e | Tau | Omega | Delta) \[Element] Reals
},
FullSimplify[
LogicalExpand[
Reduce[{L - (m^2 ((-2 + e)^2 Delta + (5 +
2 e (-7 + 4 e)) Tau) Omega)/(36 (2 - 3 e + e^2)^2) >
0}, Delta, Reals]
]
]
]
Out[]:= (L > 0 && (1 < e < 2 || e < 1 || e > 2) && (m == 0 || Omega == 0)) ||
(m != 0 && (
(Omega > 0 &&
Delta < (36 (-1 + e)^2 L)/(m^2 Omega) + ((-5 + 2 (7 - 4 e) e) Tau)/(-2 + e)^2) ||
(Delta > (36 (-1 + e)^2 L)/(m^2 Omega) + ((-5 + 2 (7 - 4 e) e) Tau)/(-2 + e)^2 &&
Omega < 0)) &&
(e > 2 || e < 1 || 1 < e < 2))
where I've expended no effort to replace symbol names with symbols.
(Why Assuming[...]? Because I'm too lazy to remember to get the same assumptions jammed into each simplification step.)

Resources