3
$\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$
5
  • 2
    $\begingroup$ Does DeleteCases[..., _Unequal] do the job? $\endgroup$
    – ybeltukov
    Sep 29, 2014 at 20:29
  • 1
    $\begingroup$ And try DeleteCases[cond, _Unequal, {0, -1}] if not. $\endgroup$
    – Mr.Wizard
    Sep 29, 2014 at 20:32
  • $\begingroup$ Or DeleteCases[cond, HoldPattern[Unequal[__]]] $\endgroup$
    – Bill
    Sep 29, 2014 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, 2014 at 20:38
  • $\begingroup$ All of these work! Thanks, everyone. I wish I had enough "reputation" to upvote comments! $\endgroup$
    – Michael
    Sep 30, 2014 at 15:09

3 Answers 3

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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