0
$\begingroup$

This is similar to a problem I had earlier.

I have a variable Gj that is related to the nj, for example:

Clear[nj]
Gj = If[nj[1] == 0, 0, nj[1] Log[nj[1]/(nj[1] + nj[2] + nj[3])]]

I would like to have a way of defining a function getGj for a given Gj. For the above example, the function would be defined by:

getGj[{a_,b_,c_}] := If[a == 0, 0,a Log[a/(a+b+c)]]

The closest I have come (thanks, Kuba) is:

Gj := If[nj[[1]]==0,0,nj[[1]] Log[nj[[1]]/(nj[[1]]+nj[[2]]+nj[[3]])]];
Unevaluated[getGj[nj_] := Gj;] /. OwnValues[Gj]

which works well for an input list with numeric values, but

ClearAll[xx,x]
xx=Array[x,3];
getGj[xx]

returns

If[x[1] == 0, 0, 
{x[1],x[2],x[3]}[[1]] Log[{x[1],x[2],x[3]}[[1]]/({x[1],x[2],x[3]}[[1]] + {x[1],x[2],x[3]}[[2]]+{x[1],x[2],x[3]}[[3]])]]

rather than

If[x[1] == 0, 0, x[1] Log[x[1]/(x[1]+x[2]+x[3])]]
$\endgroup$
  • $\begingroup$ Restating the question makes answers out of sync which will confuse future readers... About the question, why do you need to have a variable Gj = If[nj[1] == 0, 0, nj[1] Log[nj[1]/(nj[1] + nj[2] + nj[3])]], where does it come from? $\endgroup$ – Kuba Jan 4 at 7:14
  • $\begingroup$ It comes from a thermodynamics program that I am trying to write, and I need to calculate the product of the concentration nj[1] and the log of the activity which is n[1]/(n[1]+n[2]+n[3]), even when n[1] equals zero, in which case the product is zero. (Should I have started a new question?) $\endgroup$ – Paul R. Jan 4 at 11:39
1
$\begingroup$

The first element from a list is nj[[1]], not nj[1].

Additionally notice that Gj can accidentally evaluate to something you don't expect, here nj[[1]] == 0 will remain and keep If unevaluated but e.g. TrueQ@nj will not wait till you provide a value for nj.

That is why this is not the best way to create functions.

You could do:

ClearAll[getGj, nj, Gj];

Gj := If[ (* := !!!*)
  nj[[1]] == 0, 0, nj[[1]] Log[nj[[1]]/(nj[[1]] + nj[[2]] + nj[[3]])]
];

Unevaluated[getGj[nj_] := Gj;] /. OwnValues[Gj]

getGj[{1, 2, 3}]
-Log[6]

It is hard to suggest something more handy without a broader context of the question.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Hello - That works great for numerical values, but I was hoping to also be able to input : xx=Array[x,3];getGj[xx] and obtain If[x[1]==0,0,etc.]. In other words, to have it work for symbolic arrays as well. $\endgroup$ – Paul R. Jan 3 at 17:19
  • $\begingroup$ The function I am trying to build is getGj[{a_, b_, c_}] := If[a == 0, 0, a Log[a/(a + b + c)]]; but for general Gj as a function of the nj $\endgroup$ – Paul R. Jan 3 at 18:24
1
$\begingroup$

I may be missing some subtlety in your code, or outright misunderstanding your intent, but this appears to do the same thing more simply:

ClearAll[getGj, nj, Gj, zz, z];

Gj = If[nj[1] == 0, 0, nj[1] Log[nj[1]/(nj[1] + nj[2] + nj[3])]];

getGj[in_] := Block[{nj}, Gj /. nj[i__] :> RuleCondition @ in[[i]] ];

zz = Array[z, 3];
nj[1] = 22;

getGj[zz]
getGj[{1, 2, 3}]
If[z[1] == 0, 0, z[1] Log[z[1]/(z[1] + z[2] + z[3])]]

-Log[6]

Reference:

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Another test I use is to set some nj to a numerical value, say nj[1]=22. In the above case, getGj[zz] and getGj[{1,2,3}] do not return the proper value. $\endgroup$ – Paul R. Jan 4 at 11:32
  • $\begingroup$ PS - I add the nj[1]=22 after the function definition. $\endgroup$ – Paul R. Jan 4 at 11:43
  • $\begingroup$ @Paul Please see and test the update. $\endgroup$ – Mr.Wizard Jan 4 at 12:49
0
$\begingroup$

This appears to work:

ClearAll[getGj, nj, Gj, zz, z, a, b, c, x, xx];
Gj = If[nj[1] == 0, 0, nj[1] Log[nj[1]/(nj[1] + nj[2] + nj[3])]];
rul = Table[nj[j] -> Slot[j], {j, 1, 3}]
getGjx = Evaluate[Gj /. rul] &;
xx = Array[x, 3];
getGj[xx_] := Apply[getGjx, xx]
ClearAll[xx]

as a test:

ClearAll[z]
zz = Array[z, 3];
nj[1]=22;
getGj[zz]
getGj[{1, 2, 3}]

yields

If[z[1] == 0, 0, z[1] Log[z[1]/(z[1] + z[2] + z[3])]]
-Log[6]

as hoped for. Any improvements would be welcome.

(P.S. I don't understand why I cant substitute the expression for getGjx into the definition of getGj.)

| improve this answer | |
$\endgroup$

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.