0
$\begingroup$

I have two sets of functions which I want to implement them in a single function with an option indicating which set of functions should be used.

Suppose that I have two lists like:(updated example)

b = {-1, 1, 0, 2}}
u = {{1, 1, 1, 1}, {1, 0, 0, 1}, {1, 0, 1, 1}, {0, 1, 1, 0}, {1, 0, 1,
1}, {0, 1, 0, 1}, {1, 0, 1, 0}, {1, 0, 1, 1}, {0, 1, 1, 1}, {1, 1,
0, 0}}

and I have this function:

 AbEst[b0_, u0_, method_] := 
 Module[{t, b = b0, u = u0, l, a, pos, theta, dif, se},
  t = Table[i, {i, -4, 4, .01}];
  L[b_, t_, u_] := 
   Product[p[b[[i]], t]^u[[i]]*(1 - p[b[[i]], t])^(1 - u[[i]]), {i, 
     1, Length[u]}];
  p[b_, t_] := 1/(1 + Exp[-1.7*(t - b)]);
  l = L[b, t, #] & /@ u;
  a = PDF[NormalDistribution[0, 1], t];
  pos = Table[a, {Dimensions[u][[1]]}]*l;
  Which[method == "ML",
   theta = 
    t[[Position[l[[#]], Max[l[[#]]]][[1, 1]] & /@ 
      Range[Dimensions[u][[1]]]]],
   method == "MAP",
   theta = 
    t[[Position[pos[[#]], Max[pos[[#]]]][[1, 1]] & /@ 
      Range[Dimensions[u][[1]]]]],
   method == "EAP",
   theta = pos.t/Total[Transpose[pos]]];
  dif = (Table[t, {Dimensions[u][[1]]}] - 
      Partition[Flatten[Table[theta, {Length[t]}]], Length[t]])^2;
  Which[method == "ML",
   se = Sqrt[Total[Transpose[l*dif]]/Total[Transpose[l]]],
   method == "MAP",
   se = Sqrt[Total[Transpose[pos*dif]]/Total[Transpose[pos]]],
   method == "EAP",
   se = Sqrt[Total[Transpose[pos*dif]]/Total[Transpose[pos]]]];
  Return[Transpose[{theta, se}]]]

Now it returns {theta,se} for given method. I want to change it such that it returns theta by default (i.e. without computing se) and computes and returns {theta,se} if it was requested.

1) How can I do that?

2) How can I re-write more efficient function in which fits my purpose?

$\endgroup$
3
  • $\begingroup$ I deleted my previous post because is not appropriate after your update. $\endgroup$
    – Kuba
    Jul 16, 2013 at 6:17
  • $\begingroup$ Amin, your code example seems excessively long and only obfuscates the real issue under discussion. Please consider giving a shorter example. $\endgroup$
    – Mr.Wizard
    Aug 3, 2013 at 6:49
  • $\begingroup$ @Mr.Wizard I chose the right solution and I'm done with this problem.I posted the whole code just to make it clear what I mean. $\endgroup$
    – Amin
    Aug 3, 2013 at 14:34

1 Answer 1

4
$\begingroup$

One possible way is using Switch as follows:

f[a_,b_,opts___?OptionQ]:=
    With[{t=method/.{opts}/.{method->1}},
        Switch[t,
        1,{a+b,a-b},
        2,{a*b,a/b}]]

In this definition, the default option is 1. Is this what you want?

In[7]:= f[a,b,method->2]

Out[7]={{10,30,60,100,150},{1/10,2/15,3/20,4/25,1/6}}

Updated:

You can combine the two Whichs together and add If condition to control whether the output includes se or not. For your case of different behaviors at different methods, I prefer Switch to Which in this case. The following is the outline of the code:

myAbEst[b0_, u0_, method_, opts___?OptionQ] :=
  Module[{t, b = b0, u = u0, l, a, pos, theta, dif, se, L, p, 
         op = Se /. {opts} /. {Se -> False}}, 
(*op is the option that can control whether se should be output.The default is not.*)
  ...(*Your code about the assignments and definitions*)
  Switch[method,
   "ML", theta=(*your code*);If[op,dif=(*your code*);se=(*your code*)],
   "MAP", theta=(*your code*);If[op,dif=(*your code*);se=(*your code*)],
   "EAP", theta=(*your code*);If[op,dif=(*your code*);se=(*your code*)]];
  If[op,Transpose[{theta, se}], theta]]

By the way, functional program always returns the value of the last expression. You don't need to use Return to return values.

myAbEst[b,u,"ML"](*This is the default case, which won't return se.*)
myAbEst[b,u,"ML",Se->True](*This is the case that returns se.*)
$\endgroup$
8
  • $\begingroup$ I think this might work. Please take a look at updated example.It's more clear. $\endgroup$
    – Amin
    Jul 16, 2013 at 1:20
  • $\begingroup$ @Amin Please see the updates. $\endgroup$
    – Z-Y.L
    Jul 16, 2013 at 5:17
  • $\begingroup$ that's wonderful!it works well except that in default mode it returns theta's with a Null` attached to them but it's solved by adding ; after Swich $\endgroup$
    – Amin
    Jul 16, 2013 at 16:45
  • $\begingroup$ I also saved the whole function as a package but the option for Se doesn't work there, why?? $\endgroup$
    – Amin
    Jul 16, 2013 at 16:47
  • $\begingroup$ @Amin You're right! I forgot to add ; at the end. I have corrected it. By the way ,can I have a look at how you wrote your package? You can't just save as Mathematica package. You have to create a new package document by File->New->Package.Or if the format style of the code that you want to write to a package in your notebook is Code(the shortcut is Alt+8), then you can save as a Mathematica package. $\endgroup$
    – Z-Y.L
    Jul 17, 2013 at 9:56

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.