Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have two sets of solutions for a and b. I'm plotting solution only if it is positive for both a and b.

 a = 2; b = 3;
 solutionsA[x_, a_, b_] = {a Sin[b*x], a Sin[b*x + Pi/2], a Sin[b*x + Pi]};
 solutionsB[x_, a_, b_] = {a Tan[b*x], a Tan[b*x + Pi/2], a Tan[b*x + Pi]};
      {solutionsA[x, a, b], solutionsB[x, a, b]}
   , (#[[1]] > 0 && #[[2]] > 0 ) &]
 , {x, 0, 10}, Exclusions -> {Cos[b*x] == 0, Sin[b*x] == 0}]

My output is very slow. Why?

share|improve this question
@Öskå Is it possible to do the same without Select ? – Филипп Цветков Nov 1 '13 at 11:20
@илипп Not that I know, but there must be different ways that others might know about. – Öskå Nov 1 '13 at 11:28
up vote 11 down vote accepted

You can get it about 5-6 times faster if you define a separate function (to do Transpose just once):

f[x_?NumericQ] = 
   # * UnitStep[First @ #] * UnitStep[Last @ #] & /@ 
       Transpose[{solutionsA[x, a, b], solutionsB[x, a, b]}], 

and the presence of UnitStep makes Select unnecessary, with visually the same output. You can then plot it as e.g.

Plot[f[x], {x, 0, 10}, Exclusions -> {Cos[b*x] == 0, Sin[b*x] == 0}, PlotRange -> {Automatic, {0, 7}}]

A cleaner way to do this is to have a function generator that would embed your parameters, so that you don't have a dependence on global variables a and b:

makeF[a_, b_] := 
      # * UnitStep[First @ #] * UnitStep[Last @ #] & /@ 
         Transpose[{solutionsA[x, a, b], solutionsB[x, a, b]}]

and then

f = makeF[a,b]

and then use f as before.

To get some further speed-up, you can compile this. Here is the corresponding function generator:

makeFC[a_, b_, opts___?OptionQ] :=
    Block[{x},Compile[x, Evaluate[makeF[a, b][x], opts]]]

Now you can do

fc = makeFC[a, b];

and then plot fc. I can't test now, but presumably by passing CompilationTarget -> "C" to makeFC, you can get the plotting faster still.

share|improve this answer

A solution which outperforms the currently given answers is the following: You build up the complete expression of your function using Which, so that you have in the end

  Positive[Sin[3 x]]&&Positive[Tan[3 x]],{2 Sin[3 x],2 Tan[3 x]},
  Positive[Cos[3 x]]&&Positive[-Cot[3 x]],{2 Cos[3 x],-2 Cot[3 x]},
  Positive[-Sin[3 x]]&&Positive[Tan[3 x]],{-2 Sin[3 x],2 Tan[3 x]},

This approach works even if you don't know specific values for a and b. To get the definition of tuned automatically from you two solutionsA and solutionsB the following injection code can be used:

With[{arg = Transpose[{solutionsA[x, a, b], solutionsB[x, a, b]}]},
 (tuned[x_] := #) & [
   Which @@ Sequence @@@ Append[{And @@ (Positive[#]), #} & /@ arg, {True, None}]]

Mathematica graphics

On my machine, creating the graphics 10x gives the following timings for the different answers (I'm on my desktop pc now, so timings are in general faster):

  • my approach 0.46 seconds. If I tweak it with Compile (see below) we can improve it to 0.21 seconds.
  • the original approach of the OP takes 7.71 seconds.
  • Leonid's compiled version 0.59 seconds and when you compile it to "C" then 0.55 seconds
  • chyaongs needs 0.61 seconds

For testing, I iterated your original Plot command and measured the AbsoluteTiming. Let me point out that all current answers use the same approach and the tweaking to improve from 0.6 to 0.2 seconds isn't really worth it.

Let me give the code of my compiled version for comparison

With[{arg = Transpose[{solutionsA[x, a, b], solutionsB[x, a, b]}]}, 
 tunedC = Compile[{{x, _Real}}, #] &[
   Which @@ 
    Sequence @@@ 
     Append[{And @@ (Positive[#]), #} & /@ arg, {True, {0., 0.}}]]]
share|improve this answer
Did you test my compiled approach? Particularly, compiled to C? – Leonid Shifrin Nov 1 '13 at 14:46
@LeonidShifrin I get for 10 runs (on my desktop PC now) for your compiled version 0.589 s, compiled to "C" 0.5604 and my version gives me 0.460. – halirutan Nov 1 '13 at 15:20
@LeonidShifrin When I create a compiled version from my Which code, giving back {0.0, 0.0} instead of None, it runs in only 0.21 sec. – halirutan Nov 1 '13 at 15:26
Thanks for the data. I already voted for your answer, in any case :) – Leonid Shifrin Nov 1 '13 at 16:20
a = 2; b = 3;
solutions[f_, a_: a, b_: b] = a {f[b*x], f[b*x + Pi/2], f[b*x + Pi]};
expr = If[#1 > 0 && #2 > 0, {##}] & @@@ Transpose[solutions /@ {Sin, Tan}]
Plot[expr, {x, 0, 10}, Exclusions -> {Cos[b*x] == 0, Sin[b*x] == 0}]

enter image description here

share|improve this answer

A nice compact one, using the two argument form of UnitStep and summing the solutions:

sol = Total @ MapThread[UnitStep[##] {##} &, {solutionsA[x, a, b], solutionsB[x, a, b]}]

Block[{a = 2, b = 3}, Plot[sol, {x, 0, 10}, Exclusions -> {Cos[b*x] == 0, Sin[b*x] == 0}]]

enter image description here

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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