2
$\begingroup$

I am banging my head against the following question: how can I have Mathematica take

cond = 2 a >= 3 b && 70 a >= 19 && 20 a != 13;

and eliminate all the "not equal" clauses, returning:

cond = 2 a >= 3 b && 70 a >= 19;

?


Some background to my question. I am manipulating expressions that are list of inequalities, e.g.

cond = 2 a > 3 b && 70 a > 19 && 20 a != 13;

I need to convert such expressions to weaker forms, which geometrically corresponds to closure of the region. Replacing strict inequalities by weak is easy:

cond = cond /.{Less -> LessEqual, Greater -> GreaterEqual};

But I also need to remove all the "not equal" clauses, and I can't understand how to do this, or how I could even search for this in the documentation. Would any kind soul around here be able to help me? I found that I can do:

Select[cond, Head[#] == Unequal &]

which returns "20 a != 13". But then I'm stuck. I want the rest of the expression, not the "not equal" clause itself!

Thank you!

$\endgroup$
  • 2
    $\begingroup$ Does DeleteCases[..., _Unequal] do the job? $\endgroup$ – ybeltukov Sep 29 '14 at 20:29
  • 1
    $\begingroup$ And try DeleteCases[cond, _Unequal, {0, -1}] if not. $\endgroup$ – Mr.Wizard Sep 29 '14 at 20:32
  • $\begingroup$ Or DeleteCases[cond, HoldPattern[Unequal[__]]] $\endgroup$ – Bill Sep 29 '14 at 20:33
  • 2
    $\begingroup$ A more meaningful substitution: /. _Unequal -> True. It should work in any boolean expression, e.g. a > 5 || a != b. $\endgroup$ – ybeltukov Sep 29 '14 at 20:38
  • $\begingroup$ All of these work! Thanks, everyone. I wish I had enough "reputation" to upvote comments! $\endgroup$ – Michael Sep 30 '14 at 15:09
2
$\begingroup$
cond = 2 a >= 3 b && 70 a >= 19 && 20 a != 13;

Replace the symbol Unequal with something else (which better be a function):

Replace[cond, Unequal -> (True &), {0, Infinity}, Heads -> True]
Replace[cond, Unequal -> (## &[] &), {0, Infinity}, Heads -> True]
cond /. Unequal -> (True &)
cond /. Unequal -> (## &[] &)
Block[{Unequal = (True &)}, cond]
Block[{Unequal = (## &[] &)}, cond]

Replace stuff with Head Unequal with something else:

Replace[cond, _Unequal :> (## &[]), {0, Infinity}] (* or _Unequal :> Sequence[] *)
cond /. _Unequal :> (## &[]) 
cond /. _Unequal :> (True)
DeleteCases[cond, _Unequal]

all give

2 a >= 3 b && 70 a >= 19
Replace[cond, {LessEqual -> Less, GreaterEqual -> Greater, Unequal -> (True &)}, 
       {0, Infinity}, Heads -> True]
cond /. {LessEqual -> Less, GreaterEqual -> Less, Unequal -> (True &)}
2 a<3 b&&70 a<19
$\endgroup$
  • $\begingroup$ Rule/RuleDelayed have SequenceHold, so no need to use ## &[]--you can just as well write Sequence[]. I do prefer replacing it with True, though, particularly as this cannot introduce problems when the expression is only subjected to partial evaluation. $\endgroup$ – Oleksandr R. Sep 29 '14 at 21:36
  • $\begingroup$ Thank you @Oleksansr. WFIW, while ##&[] and ##&[]& worked for _Unequal and Unequal, respectively, (similarly, for True and True&), i noticed Sequence[] and Sequence[]& did not. $\endgroup$ – kglr Sep 29 '14 at 22:18
  • $\begingroup$ Thanks! This is great. I can now not only solve my specific problem, but I have 10 slightly different ways of doing this, which gives me a much better understanding of what's happening behind the scenes in Mathematica's world. For someone like me who "grew up" on C/C++ and then MatLab, it's very confusing at first. $\endgroup$ – Michael Sep 30 '14 at 15:08
  • $\begingroup$ @Michael, thank you for the Accept. Welcome to mma.se. $\endgroup$ – kglr Sep 30 '14 at 15:09
1
$\begingroup$

I believe the rule you' want is

Unequal[a_, b_] -> Sequence[]

I tried Unequal[__] -> Sequence[] but it didn't seem to work.

When mathematica sees Sequence[args] inside of some other head, it knows to splice args in place into the arguments of that head. In this case, Sequence[] has no arguments, and so Mathematica replaces Unequal clauses with nothing, effectively deleting it.

$\endgroup$
  • 2
    $\begingroup$ This is because Unequal[__] evaluates to True. Try _Unequal or HoldPattern[_ != _] instead. $\endgroup$ – Mr.Wizard Sep 29 '14 at 20:34
  • $\begingroup$ Cool, thanks for the insight. I didn't know about this Sequence thing. $\endgroup$ – Michael Sep 30 '14 at 15:10
  • $\begingroup$ @Michael, sure thing! $\endgroup$ – evanb Sep 30 '14 at 17:42
  • $\begingroup$ @Mr.Wizard, aha! That explains a few pattern-matching mysteries I've experienced! +1. $\endgroup$ – evanb Sep 30 '14 at 17:43
0
$\begingroup$
Delete[cond, Position[cond, _Unequal]]
$\endgroup$
  • $\begingroup$ This works, too! Thanks! $\endgroup$ – Michael Sep 30 '14 at 15:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.