3
$\begingroup$

I want to write a function MySimplify (like built-in Simplify) that takes a second argument to specify additional $Assumptions and that also has an overriding Assumptions option. Here's how I start:

MySimplify::usage = "MySimplify[expr] simplifies expr using QuantumDot's code.
MySimplify[expr, assum] does simplification using assumptions.";

Options[MySimplify] = {Assumptions :> $Assumptions};
SyntaxInformation[MySimplify] = {"ArgumentsPattern" -> {_, _., OptionsPattern[]}};

Question How do I write the boiler-plate code to mimic the behavior of built-in Simplify? Here's my attempt:

MySimplify[e_, o:OptionsPattern[]] := MySimplify[e, True, o];

MySimplify[e_, a_, OptionsPattern[]] :=
  Assuming[a,
    Block[{$Assumptions=OptionValue[Assumptions]},
      Null
     (*QuantumDot's code for simplification goes here*)
    ]
  ];

The outer Assuming appends any assumptions in the second argument to $Assumptions, and the inner Block uses $Assumptions, just like built-in Simplify.

Problem If I supply assumptions that are contradicting or false, it throws $Assumptions::cas instead of MySimplify::cas, or $Assumptions::fas instead of MySimplify::fas. How do I make the following cases

$Assumptions = True;
MySimplify[Sin[x], x > 0 && x < 0];

or

$Assumptions = a > 0;
MySimplify[Sin[x], x < 0]

or

MySimplify[Sin[x], Assumptions->False]

generate a MySimplify::cas and MySimplify::fas errors instead of a $Assumptions::cas and $Assumptions::fas error?

Is this the correct way to build a function that uses assumptions?

$\endgroup$
3
  • $\begingroup$ This seems like more of a message filtering issue. If that's the case use WithMessageHandler to catch messages and reemit them with the appropriate head or use a different handler built at the Internal`HandlerBlock level. $\endgroup$
    – b3m2a1
    Commented Aug 7, 2018 at 22:39
  • $\begingroup$ @b3m2a1 Those are two very interesting functions, where can I read to learn more about them? $\endgroup$
    – QuantumDot
    Commented Aug 7, 2018 at 23:00
  • $\begingroup$ I think they're only really documented here... Check this and WithMessageHandler... you can look here I guess, although that's a bit ugly and autobuilt. $\endgroup$
    – b3m2a1
    Commented Aug 7, 2018 at 23:04

1 Answer 1

3
$\begingroup$

You are already mimicking the behavior of MMA built-in functions. The following code prints a $Assumptions::cas message not a TensorDimensions::cas.

$Assumptions = A \[Element] Arrays[{2, 2, 2, 2}];
Assuming[A \[Element] Arrays[{2, 2}], Print["QD was here…"];TensorDimensions[A]]
(*error message before QD gets there*)

Note that the error is printed before the message. That suggests that Assuming processes the assumptions before moving on to the evaluation of the code in the second parameter. Checking the attributes further supports that suggestion:

Attributes[Assuming]
{HoldRest, Protected}

If one must have one's own message, one could try evaluating $Assumptions within a Quiet block.

Options[qdSimplify] = {Assumptions :> $Assumptions};

qdSimplify[e_, o : OptionsPattern[]] := qdSimplify[e, True, o];

qdSimplify[e_, a_, OptionsPattern[]] := 
  With[{qdAssumptions = 
     Quiet[Check[
       Assuming[a && OptionValue[Assumptions], $Assumptions], 
       Print["Your ad here"]; True], {$Assumptions::cas}]}, 
   Print["Bleached assumptions: ", qdAssumptions]; 
   Assuming[qdAssumptions, Print[qdAssumptions]; 
    Print[$Assumptions];]];

$Assumptions = True;
qdSimplify[Sin[x], x > 0 && x < 0];

Of course, one would have to determine what to do in case of contradiction (perhaps devising some preference semantics) … but that is the subject for another question.


Update

I am not sure that I understand your request.

If it about suppressing the message $Assumptions::fas, you could just add it to the list that contains $Assumptions::cas.

If it is about printing your own message, you can replace Print["Your ad here"] with your own Message[blah].

If you want to reproduce the fact that Simplify with contradictory assumptions evaluates to True, you can do it by changing the True after Print with a flag that you check in the body.

Maybe you want all of the above.

Options[qdSimplify] = {Assumptions :> $Assumptions};

(*As pointed out by b3m2a1, the next two lines are not necessary*)
(*
qdSimplify::fas="Warning: one or more assumptions evaluated to False";
qdSimplify::cas="Warning: contradictory assumption(s) encountered: `1`."*)
qdSimplifyContr::usage = "This is a flag indicating contradictory assumptions.";
qdSimplifyFalse::usage = "This is a flag indicating false assumptions.";

qdSimplify[e_, o : OptionsPattern[]] := qdSimplify[e, True, o];

qdSimplify[e_, a_, OptionsPattern[]] := With[{qdAssumptions = Quiet[
      Check[
       Check[
        Assuming[a && OptionValue[Assumptions], $Assumptions], 
        Message[qdSimplify::cas, a && OptionValue[Assumptions]]; qdSimplifyContr,
        {$Assumptions::cas}],
       Message[qdSimplify::fas]; qdSimplifyFalse,
       {$Assumptions::fas}],
      {$Assumptions::cas, $Assumptions::fas}]}, 
   Print["Bleached assumptions: ", qdAssumptions];
   Which[
    (*A*)! FreeQ[qdAssumptions, qdSimplifyContr], True,
    (*B*)! FreeQ[qdAssumptions, qdSimplifyFalse], "Handled false assumptions",
    (*C*)True, 
    Assuming[qdAssumptions, Print[qdAssumptions]; Print[$Assumptions];
      "Normal code"]]];

A. Simulates the fact that Simplify with contradictory assumptions evaluates to True. B. This is where you would handle the situation with false assumptions. C. This is where you would put the body of the function.

$\endgroup$
6
  • $\begingroup$ Thanks, but, how about mimicking all other aspects, like for $Assumptions::fas (see edit)? $\endgroup$
    – QuantumDot
    Commented Aug 8, 2018 at 0:19
  • $\begingroup$ ::fas and ::cas are already attached to General. You don't need to redefine them. $\endgroup$
    – b3m2a1
    Commented Aug 8, 2018 at 7:05
  • $\begingroup$ @b3m2a1 Are you suggesting that, instead of qdSimplify::fas = "blah", the code should have qdSimplify::fas = General::fas? If so, I concur with you. $\endgroup$
    – Hector
    Commented Aug 8, 2018 at 8:04
  • $\begingroup$ @Hector no I'm saying never assign to qdSimplify::fas. Literally just try a raw Message[bleb::fas] without attaching a message to bleb. That's the real point of General. $\endgroup$
    – b3m2a1
    Commented Aug 8, 2018 at 8:06
  • $\begingroup$ @b3m2a1 Huh ... I just learned something new! $\endgroup$
    – Hector
    Commented Aug 8, 2018 at 8:09

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.