Skip to main content
added 376 characters in body
Source Link
Simon Rochester
  • 6.3k
  • 1
  • 30
  • 42

Removing the pattern test, i.e.Because Mathematica prioritizes specific function definitions over general ones, simply making the definition f[x_] := -f[-x], or adding a corresponding definition with ?Positive

M[i_, j_] := -M[j, i] 

will work as long as you only try to evaluate fM with values for xi forand j for which either f[x]M[i, j] or f[-x]M[j, i] have been explicitly defined. Otherwise you get infinite recursion:

f[x_]M[1, 2] := -f[-x]a f[-1]M[4, 3] := 2;b f[2] M[1, =2] (* 4;a *) f[1]M[2, 1] (* -2a *) f[-2]M[3, 4] (* -4b *) f[3]M[1, 3] (* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of f[-3]M[3,1]. *) (* Hold[-f[-3]]M[3, 1]] *) Clear[f]Clear[M] 

To avoid this, we can make a definition for fM that only allows itself to be recursed twice, like so:

Module[{in = 0}, f[x_]M[i_, j_] /; in < 2 := Block[{in = in + 1}, -f[-x]];M[j, i]] ] 

The variable in counts the number of times that thethis definition of f[x]M has been called recursively. If in is less than two, the definition applies, and the sign of xi is flippedand j are swapped. When in is equal to two, the definition doesn't apply, and evaluation terminates. Since at this point the definition has been applied twice, the original expression is returned.

Now we have

f[-1] =M[1, 2; f[2]2] := 4; a M[4, 3] := b f[1]M[1, 2] (* -2a *) f[-2]M[2, 1] (* -4a *) f[3]M[3, 4] (* f[3]-b *) f[f[f[1]]]M[1, 3] (* f[-4]M[1, 3] *) 

(Side note: Mathematica colors the n in the Block expression red, because it thinks that we've created a naming conflict between the Module and the Block, but in fact it works just how we want.)

Removing the pattern test, i.e., making the definition f[x_] := -f[-x], or adding a corresponding definition with ?Positive will work as long as you only try to evaluate f with values for x for which either f[x] or f[-x] have been explicitly defined. Otherwise you get infinite recursion:

f[x_] := -f[-x] f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of f[-3]. *) (* Hold[-f[-3]] *) Clear[f] 

To avoid this, we can make a definition for f that only allows itself to be recursed twice, like so:

Module[{i = 0}, f[x_] /; i < 2 := Block[{i = i + 1}, -f[-x]]; ] 

The variable i counts the number of times that the definition of f[x] has been called recursively. If i is less than two, the definition applies, and the sign of x is flipped. When i is equal to two, the definition doesn't apply, and evaluation terminates.

Now we have

f[-1] = 2; f[2] = 4;  f[1] (* -2 *) f[-2] (* -4 *) f[3] (* f[3] *) f[f[f[1]]] (* f[-4] *) 

Because Mathematica prioritizes specific function definitions over general ones, simply making the definition

M[i_, j_] := -M[j, i] 

will work as long as you only try to evaluate M with values for i and j for which either M[i, j] or M[j, i] have been explicitly defined. Otherwise you get infinite recursion:

M[1, 2] := a M[4, 3] := b  M[1, 2] (* a *) M[2, 1] (* -a *) M[3, 4] (* -b *) M[1, 3] (* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of M[3,1]. *) (* Hold[-M[3, 1]] *) Clear[M] 

To avoid this, we can make a definition for M that only allows itself to be recursed twice, like so:

Module[{n = 0}, M[i_, j_] /; n < 2 := Block[{n = n + 1}, -M[j, i]] ] 

The variable n counts the number of times that this definition of M has been called recursively. If n is less than two, the definition applies, and the i and j are swapped. When n is equal to two, the definition doesn't apply, and evaluation terminates. Since at this point the definition has been applied twice, the original expression is returned.

Now we have

M[1, 2] := a M[4, 3] := b M[1, 2] (* a *) M[2, 1] (* -a *) M[3, 4] (* -b *) M[1, 3] (* M[1, 3] *) 

(Side note: Mathematica colors the n in the Block expression red, because it thinks that we've created a naming conflict between the Module and the Block, but in fact it works just how we want.)

deleted 271 characters in body
Source Link
Simon Rochester
  • 6.3k
  • 1
  • 30
  • 42

Removing the pattern test, i.e., making the definition f[x_] := -f[-x], or adding a corresponding definition with ?Positive will work as long as you only try to evaluate f with values for x for which either f[x] or f[-x] have been explicitly defined. Otherwise you get infinite recursion:

f[x_] := -f[-x] f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of f[-3]. *) (* Hold[-f[-3]] *) Clear[f] 

To avoid this, we can make a definition for f that only allows itself to be recursed twice, like so:

Module[{done}, f[x_] /; ! BooleanQ[done] := Block[{donei = False0}, -f[-x]];   f[x_] /; !i done< 2 := Block[{donei = Truei + 1}, -f[-x]]; ] 

WhenThe variable f[x]i is evaluated, it satisfies the condition forcounts the first definition, becausenumber of times that the variable done is undefined. The first definition defines done to be False and flips the sign of xf[x] has been called recursively. If f[-x]i has no explicit definitionis less than two, it now satisfies the condition for the second definition in the Moduleapplies, since done is now False. It flipsand the sign of x again and setsis flipped. When donei is equal to be True. Now none of the conditions are satisfiedtwo, so the definition doesn't apply, and evaluation terminates.

Now we have

f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* f[3] *) f[f[f[1]]] (* f[-4] *) 

Removing the pattern test, i.e., making the definition f[x_] := -f[-x], or adding a corresponding definition with ?Positive will work as long as you only try to evaluate f with values for x for which either f[x] or f[-x] have been explicitly defined. Otherwise you get infinite recursion:

f[x_] := -f[-x] f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of f[-3]. *) (* Hold[-f[-3]] *) Clear[f] 

To avoid this, we can make a definition for f that only allows itself to be recursed twice, like so:

Module[{done}, f[x_] /; ! BooleanQ[done] := Block[{done = False}, -f[-x]]; f[x_] /; ! done := Block[{done = True}, -f[-x]]; ] 

When f[x] is evaluated, it satisfies the condition for the first definition, because the variable done is undefined. The first definition defines done to be False and flips the sign of x. If f[-x] has no explicit definition, it now satisfies the condition for the second definition in the Module, since done is now False. It flips the sign of x again and sets done to be True. Now none of the conditions are satisfied, so the evaluation terminates.

Now we have

f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* f[3] *) f[f[f[1]]] (* f[-4] *) 

Removing the pattern test, i.e., making the definition f[x_] := -f[-x], or adding a corresponding definition with ?Positive will work as long as you only try to evaluate f with values for x for which either f[x] or f[-x] have been explicitly defined. Otherwise you get infinite recursion:

f[x_] := -f[-x] f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of f[-3]. *) (* Hold[-f[-3]] *) Clear[f] 

To avoid this, we can make a definition for f that only allows itself to be recursed twice, like so:

Module[{i = 0},   f[x_] /; i < 2 := Block[{i = i + 1}, -f[-x]]; ] 

The variable i counts the number of times that the definition of f[x] has been called recursively. If i is less than two, the definition applies, and the sign of x is flipped. When i is equal to two, the definition doesn't apply, and evaluation terminates.

Now we have

f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* f[3] *) f[f[f[1]]] (* f[-4] *) 
Source Link
Simon Rochester
  • 6.3k
  • 1
  • 30
  • 42

Removing the pattern test, i.e., making the definition f[x_] := -f[-x], or adding a corresponding definition with ?Positive will work as long as you only try to evaluate f with values for x for which either f[x] or f[-x] have been explicitly defined. Otherwise you get infinite recursion:

f[x_] := -f[-x] f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of f[-3]. *) (* Hold[-f[-3]] *) Clear[f] 

To avoid this, we can make a definition for f that only allows itself to be recursed twice, like so:

Module[{done}, f[x_] /; ! BooleanQ[done] := Block[{done = False}, -f[-x]]; f[x_] /; ! done := Block[{done = True}, -f[-x]]; ] 

When f[x] is evaluated, it satisfies the condition for the first definition, because the variable done is undefined. The first definition defines done to be False and flips the sign of x. If f[-x] has no explicit definition, it now satisfies the condition for the second definition in the Module, since done is now False. It flips the sign of x again and sets done to be True. Now none of the conditions are satisfied, so the evaluation terminates.

Now we have

f[-1] = 2; f[2] = 4; f[1] (* -2 *) f[-2] (* -4 *) f[3] (* f[3] *) f[f[f[1]]] (* f[-4] *)