Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have the following function

lFreqPhylo[a_, Q_, b_, p_] :=  Sum[Log[freqFunction[r[[p]][[i]], L[[p]][[i]], a, Q, b, {i, 1, nbranches[[p]]}];

The objects L, r and nbranches are simply lists of data, and the argument p tells the function which dataset to refer to.

I'd like to define a function which sums all of the datasets (here n=2) and uses a different argument a and b for each dataset, so to write it our by hand,

lFreqPhylo[a1, Q, b1, 1] + lFreqPhylo[a2, Q, b2, 2]

To this end, I defined two lists,

A = {a1,a2}

and

B = {b1,b2}

(This list has more elements but I'm giving the example of 2 elements to keep it simple.) What this means is that I'd need to pass the lists A, B and the index to each list (p in lFreqPhylo) to a new function lFreq. The following approach however failed:

lFreq[A__, B__, Q_] := Sum[lFreqPhylo[A[[p]], Q, B[[p]], p], {p, 1, 2}]; (*Doesn't work!*)

How can I pass the two lists, A and B, to the function lFreqPhylo such that I can (a) use the 'Sum[...]' expression on the right hand side, (b) use the list elements, a1, a2, b1 and b2, as arguments of the function?

Thanks in advance, Rafal

share|improve this question
    
Kuba, Well, problem is I have two lists and need to pass an index of the list as an argument. So following your advice, having defined two lists, A = {a1,a2}; B = {b1,b2}; I did f1[a_, b_, Q_] := (a b)^2/Q; f2[Q_, a__, b__] := Total[MapThread[f1[#1, #2, Q] &, {A, B}]]; and now it works. But what if I have f1[a_, b_, Q_,i_] := (a b)^2/Q i where i is the index of the element of the list (1 or 2)? How do I define f2 then? –  Rafal May 27 at 13:36
    
You're absolutely right, I've now edited it. –  Rafal May 27 at 14:09
    
Change the LHS of your definition to lFreq[A_, B_, Q_] and it works as expected; no? –  kguler May 27 at 22:10

2 Answers 2

Edit

The definition you make

lFreq[A__, B__, Q_] := [...]

is not very nice. There is an ambiguity here and Mathematica will not know how many elements to match to A and how many to match to B. We can check this by defining

lFreqTest[A__,B__]:= {A}

Then

lFreqTest[1, 2, 3, 4]

gives

{1}

So that we see that Mathematica tries to make B__ as long as possible. There is a terrible way around this

Clear@tester
tester[PatternSequence[a__, b__] /; (Length@{a} == Length@{b})] := "ok"

which gives

tester[1,2]
"ok"
tester[1,2,3]
tester[1,2,3]

But this will be very slow. You should look to alternatives.

Original

How about this?

A = {1, 2};
B = {2, 3};
Q = 6;

The actual functions

f1[a_, b_, Q_, i_] := (a b)^2/Q;

lFreq[listA_, listB_, Q_] :=

lFreq[listA_, listB_, Q_] :=
 Total@
  MapThread[
   f1[#1, #2, Q, #3] &
   ,
   {listA, listB, Range[Length@listA]}
   ]

Now we have

lFreq[A, B, Q]
20/3
share|improve this answer
    
Jacob, I have now changed the original question such that it contains all the sub-questions I had. Sorry for the confusion. –  Rafal May 27 at 14:10
    
Thanks Jacob. I've written the following and it seems to work. Do you think this is better or do you think it will be slow too and should I find another way? lFreqPhylo[a_, Q_, b_, p_] := Sum[Log[freqFunction[r[[p]][[i]], L[[p]][[i]], a, Q, b]], {i, 1, nbranches[[p]]}]; lFreqPhylo2[listA_, listB_, Q_] := Total@MapThread[ lFreqPhylo[#1, Q, #2, #3] &, {listA, listB, Range[Length@listA]}]; lFreq[A_, B_, Q_] := Evaluate[lFreqPhylo2[A, B, Q]]; –  Rafal May 27 at 15:26
    
@Rafal that looks quite reasonable. Just so you know, you can write r[[p]][[i]] as r[[p, i]]. Furthermore your definition for lFreq may be a bit tricky. Either Q A and B are already set, and it is misleading to have them as function arguments. Or they are not set, and MapThread will probably fail. Maybe it works if you define this function before you define lFreqPhylo2, A, B and Q. –  Jacob Akkerboom May 27 at 15:44
    
Longest can help here. –  Alexey Popkov May 27 at 16:49

What about the following approach:

lFreq[A_List, B_List, Q_]:=Sum[Function[i, lFreqPhylo[A[[i]], Q, B[[i]], i][j], {j, 1, 2}]

This produces the correct output for the given example of 2 elements:

lFreqPhylo[a1, Q, b1, 1] + lFreqPhylo[a2, Q, b2, 2]
share|improve this answer

Your Answer

 
discard

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.