1
$\begingroup$

I am trying to bracket the roots of a function with the variable p. The assumptions are: the root exist between 0 and 1, the value of the function is positive at p = 0.

The code That I have written is as follows:

bracketRoot[funL_] := 
  Module[{i, p, dp = 0.1, Nfun},
    For[i = 0, i <= 1, i = i + dp,
      Nfun = funL /. p -> i;
      If[Im[Nfun] == 0,
         If[Nfun < 0, Print[Nfun]; Return[{i - dp, i}];];,
         Print["encountered a complex value for the function before bracketing the root!"];
         Print["Returning the p value for which the function is real..."];
         Return[{i - 2 dp, i - dp}];];];
     Print["Could not bracket the root ...."];
     Return[{0, 1}];];

When the function is called in my notebook, I am able to get the proper answer. But If I call this function from another function, the function is returning {0, 1} with a print message.

It appears that the replacement rules are not effective in the module for p. This problem appears similar to Q1. But I could not understand. A similar question is asked Q2. I tried this solution also. But this also could not solve the problem.

Kindly throw some light on the problem by analyzing it.


Edit:

My functions are complicated in p. The function is tested with a simple expressions like: from a note book:

bracketRoot[(p-1)(p-4.5)]

declaring p as local variable in bracketRoot, the function is called from a module (a sample code):

fun1[]:=Module[{initset},
initset=bracketRoot[(p-1)(p-4.5)];
Print[initset]; (*to know output*)
];
fun1[]

@m_goldberg answer is helpful for the problem. Thank you.

$\endgroup$
  • 2
    $\begingroup$ We need a minimal working example to help you. You've given a function definition, but how would you use the function? What inputs would I give it, and what would I expect to get in return? $\endgroup$ – Jason B. Jul 10 '17 at 18:51
1
$\begingroup$

Alternative solution 1: Don't localize p (i.e, leave it off the list of Module variables). You're treating p as a global variable by just assuming the function is a function of p, so don't declare it as a local variable.

Alternative solution 2: Pass the name of the variable as a second argument:

bracketRoot[funL_, p_] := Module[{i, dp = 0.1, Nfun}, ...]

Now this will work for functions in any variable, not just p.

$\endgroup$
  • $\begingroup$ Thank you @Itai Seggev. Your alternate solution 2 is really simple and nice. $\endgroup$ – Rajendra prasad Jul 11 '17 at 6:30
1
$\begingroup$

For your scoping problem with p the solution is to scope with Block not Module. This is because Block dynamically localizes symbols (locally shadows bindings made at higher scoping levels) while Module lexically localizes symbols (changes their names).

Minimal working example

 f[expr_] := Module[{p}, expr /. p -> 42] 
 f[p]

p

 f[expr_] := Block[{p}, expr /. p -> 42] 
 f[p]

42

So we really didn't need to see all your code, most of which is irrelevant to the scoping issue. But we did, and it horrified me. Mathematica has much better tools for doing what you want to do than the ones you used. I will demonstrate a few of them. This is not optimal code. I am striving here more for code that is easy to understand than for code that is highly optimized.

bracketRoot::y0neg = "function non-postive at zero";
bracketRoot::nobrkt = "function positive at all mesh intervals";
bracketRoot[f_, dx_: .1] :=
  Module[{mesh, vals, signs, indx},
    mesh = Subdivide[1., Round[1/dx]];
    vals = f /@ mesh;
    signs = Sign[vals];
    indx = Position[signs, -1, 1, 1] // Flatten;
    Switch[indx,
      {}, Message[bracketRoot::nobrkt]; $Failed, 
      {1}, Message[bracketRoot::y0neg]; $Failed,
      {_}, mesh[[indx[[1]] - 1 ;; indx[[1]]]]]]

Tests

bracketRoot[Cos[2 π #] &]

{0.2, 0.3}

bracketRoot[Cos[2 π #] &, .02]

{0.24, 0.26}

Cos[2 π x] has a root at 1/4, so the bracketing is correct.

bracketRoot[# + 1 &]

mesg1

$Failed

bracketRoot[# - 1 &]

mesg2

$Failed

$\endgroup$
  • $\begingroup$ Thank you @mgoldberg Could you please suggest some references from where one can write codes in a better way. $\endgroup$ – Rajendra prasad Jul 11 '17 at 4:46
  • $\begingroup$ @Rajendraprasad. Here are three links. They will keep you busy for quite awhile, but there is enough info available through the linked pages to make you a Mathematica expert if you are willing to put enough effort into it. advanced-intro, pitfalls, good-coding $\endgroup$ – m_goldberg Jul 11 '17 at 9:39

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.