Might be useful if it was stated at the start of the post exactly what the ^ operator is supposed to do - it does different things in different programming languages.
As is pointed out further down, it does effectively invent tetration, which is cool, but that's not Knuth's arrow notation.
Edited: I've removed the original and replaced it with the above because clearly my original comment wasn't being understood the way it was intended. Possibly this is no better, but it's worth a try.
To provide context, the comment by elil17 is in response to my original, in which I asked what this had to do with Knuth's arrow notation.
Except the essence of Knuth's up-arrow notation is the recursive nature. This is going one step, and while I agree that it's a first step, it doesn't actually get the recursive nature. So this is a notation for a single thing, not a general thing. It's good, but i's missing the generalisation step that is what makes Knuth's notation particularly special.
Maybe I know too much about the field, maybe I don't know enough, but I've looked over this many times and it doesn't seem to me to be making "the step."
Maybe I'm just expecting too much, but it feels like the heart of Knuth's notation is missing.
<fx: shrug /> I'll leave it at that. Feel free to disagree, perhaps it's an interesting talking point.
I find it hard to focus on this stuff, but is there really any ultimate generalization? Like, you always can recurse once more - once you define up arrows, then why not iterate them?
↑n means n up arrows, so why not have an operator that applies up arrows a number of times defined with up arrows?
It seems like it's just dipping your toe into large numbers, no matter how far you go.
> why not have an operator that applies up arrows a number of times defined with up arrows?
That is exactly what up arrows do, isn’t it? Up arrows are iterated up arrows. I learned this in college but still didn’t fully understand up arrows for a long time, they grow unimaginably bigger and faster than I first thought. This video explains it pretty well: https://youtu.be/GuigptwlVHo
I don’t know about ‘ultimate’ but there are some generalizations of up arrows:
Since ordinals are the ultimate recursion tool, any such function will ultimately grow faster than whatever recursive definition you can cook up by hand.
For instance even the slow growing hierarchy g_alpha, which grows very very slowly catches up to the fast hierarchy at extremely large ordinals.
Some examples:
- f_0 behaves like addition, f_1 like multiplication, f_2 like exponentiation, f_3 like tetration, f_w like Ackerman
- Graham number is bounded by f_{w+1}(64)
- Goodstein function behaves like f_{epsilon_0} (this show how much faster it grows than Ackerman). Similar for the Kirby-Paris Hydra
- n-Iterated goodstein behaves live f_{\phi(n-2,0)} where \phi is Veblen's function
- the tree function from Kruskal's tree theorem
behaves like f_{\psi(Omega^Omega^omega}, ie by the small Veblen ordinal. And the graph function from the Robertson-Seymour theorem behaves like \psi(Omega_omega).
By contrast the slow growing hierarchy grows extremely slowly, for instance g_{epsilon_0} only grows like tetration. But it still catches up to the fast growing hierarchy at very large ordinals.
Like I said, I can't really follow this stuff, but maybe the ultimate would be the Busy Beaver function? Is there such a thing as a proof of how many functions can be between something computable and Busy Beaver, given some sort of constraints?
Yes, the Busy Beaver function grows faster than the functions I gave, basically it behaves like f_{w^1_CK} (although this does not really make sense because w^1_CK, the Church Kleen ordinal, is not recursive).
By "ultimate generalisation" I was speaking about a family of computable functions that ultimately grow faster than other functions you could cook up by hand: you put all the recursivity in the ordinals, they are there for that, and logicians are very good at constructing very large (recursive) ordinals.
If you just want a very very fast growing function (but that is still computable, unlike busy beaver), you can do the a light busy beaver version: Beaver(N)=the maximal output of all turing machines T with N state where there is a proof in ZFC of length <=N that T terminates.
This function grows much faster than the other functions I described (basically it is a f_{ordinal consistency of ZFC}.
If you are interested in this kind of ideas, there is this reddit post that develops these ideas:
https://www.reddit.com/r/math/comments/283298/how_to_compute...
You're not supposed to discuss voting...but I've noticed a couple times that sometimes when I make two related comments on the same thread expressing basically the same opinion, one gets upvoted a lot and one gets downvoted a lot, and that's just weird. Maybe the exact timing determines if the upvoters see it.
One thing that has got me thinking in the past was another kind of formula,`f(f(x)) = g(x)`, where `g` is given. It bothered me that far from a general algorithm being known, individual cases were stumping (e.g., `f(f(x)) = e^x`). Any insights/references from HN folks about this?
In mathematics, a functional square root (sometimes called a
half iterate) is a square root of a function with respect to
the operation of function composition. In other words, a
functional square root of a function g is a function f
satisfying f(f(x)) = g(x) for all x.
Problems like these (typically restricted to integers/natural numbers) come up in competitions from time to time. Sometimes there are some tricks required that are very hard to find on the spot. Here is a related problem you may enjoy:
Find all increasing functions f : N -> N such that f(f(x)) = 3x
If we discard the requirement to be an increasing function, one recursively defined solution takes f(3x + 1) = 3x + 2, f(3x + 2) = 3 * (3x + 1), and f(3x) = 3f(x), with f(0) = 0.
Or analogously for any way of splitting the positive integers not divisible by 3 into ordered pairs (a, b). Then define f(3^n a) = 3^n b and f(3^n b) = 3^(n + 1) a. This is the general form of the solutions.
> Well then, f(x + 1) > f(x). I don't know where you're getting this x < f(x) as "increasing".
Headdesk Yes, that's correct; I misparsed "increasing functions f" as "functions f that increase [the value passed through them]" and then got distracted by the discrete vs continuous confusion.
The definition of an increasing function is a function f such that for all x and y, x < y implies f(x) <= f(y).
For a strictly increasing function change <= to <.
Your argument fails because you drop the antecedent in: x < f(x) => f(x) < f(f(x)). If f(0) = 0, you don’t have 0 < f(0) so can’t require that f(f(0))<f(0).
Note however that it is easy to show that f must be strictly increasing if it is increasing for if x is not y and f(x) = f(y) then 3x = f(f(x)) = f(f(y)) = 3y which cannot be the case.
I really like this answer on Quora [1], about the precise example you mention. The author is worth following for his insights, and the clear way he talks about math.
> As you probably saw, the solution of x^x = y is x = Log(y) / W[Log(y)]. Now you take us in a highly philosophical debate. What is the limit of elementary functions ? Thanks for this question. Cheers. – Claude Leibovici
That comment references the worked examples that used to be on the Lambert W wiki page, including this exact problem, x^x=y. Here's the last version before it was deleted if anyone wants to see it:
I'm glad to see that this problem bugged other high schoolers. I spent a lot of time learning about the lambert W function and real analysis in general due to this problem in high school.
First, let me break this down, in the interest of sharing the joys of J.
The thing in parenthesis is our inverse operation of x^x; we then evaluate that at 5. The first ^ is exponentiation and the following ~ makes binary operators into unary ones by evaluating on the diagonal. In other words it turns f(x,y) into f(x) = f(x,x), which for x^y corresponds to x^x.
Next we have the ^: modifier. This is function iteration, i.e. exponentiation over function composition. The function is on the left (here ^~) and the count on the right (here _1). So f ^: 2 means f(f(x)). In fact, this function exponentiation is extended to negative integers as well! In J, negative numbers are prefixed with _ (underscore), and f^:_1 actually gives us the inverse of f (if it exists)!
Anyway, we can see inspect the definition for an operation's inverse using the b. verb. From the jconsole:
The part we are interested in is in single quotes. Pulling this one apart would involve introducing the various operator combinators in J, so suffice it to say that the ^:_ part numerically approximates a fixed point of the part in parenthesis, which essentially is a straightforward transcription of the recursive relation in Newton's method.
The ratio of right triangle legs is "easily solved" by tan(x). But that's magical/cheating to someone who hasn't studied trigonometry.
Lambert-W is a well known function with known approximation methods; once you reduce your problem to it (in this case, trivially), you can lean on that knowledge from others.
That's true for almost any nontrivial transcendental algebraic or differential equation. Special functions to solve special cases are the norm.
We could repeat the same discussion at a lower level. Suppose you tell a bright middle schooler about the basics of integration, and the power rule. Then they ask,
"So what's the integral of 1/x? It can't be x^0/0..."
"That's a special case. It's a function called "natural logarithm", ln(x)."
"But what's the definition of that weird function?"
Seems to this series converges to 1 for the interval between 0 and 1, and nothing else converges. Is that correct?
EDIT: actually I guess it's more complicated than that. If I'm understanding the order of operations correctly, there's an alternating parity (where n is the number of exponentiations) thing going on with the values between 0 and 1
I think what the original author meant by "centers" of addition and multiplication is closer to "empty sum" and "empty product" respectively. From what they wrote, it seems that they wanted more than just neutrality. In any case I don't think we should retroactively label their novel and necessarily unique concept with a familiar name.
64 comments
[ 2.5 ms ] story [ 132 ms ] threadBut I get the reading of double-asterisk as 'multiplication of multiplication' as well, either is fairly transparent really.
edit: actually meant https://en.wikipedia.org/wiki/Tetration
https://en.wikipedia.org/wiki/Knuth%27s_up-arrow_notation
Edited: I've removed the original and replaced it with the above because clearly my original comment wasn't being understood the way it was intended. Possibly this is no better, but it's worth a try.
To provide context, the comment by elil17 is in response to my original, in which I asked what this had to do with Knuth's arrow notation.
Maybe I know too much about the field, maybe I don't know enough, but I've looked over this many times and it doesn't seem to me to be making "the step."
Maybe I'm just expecting too much, but it feels like the heart of Knuth's notation is missing.
<fx: shrug /> I'll leave it at that. Feel free to disagree, perhaps it's an interesting talking point.
https://en.wikipedia.org/wiki/Tetration
↑n means n up arrows, so why not have an operator that applies up arrows a number of times defined with up arrows?
It seems like it's just dipping your toe into large numbers, no matter how far you go.
That is exactly what up arrows do, isn’t it? Up arrows are iterated up arrows. I learned this in college but still didn’t fully understand up arrows for a long time, they grow unimaginably bigger and faster than I first thought. This video explains it pretty well: https://youtu.be/GuigptwlVHo
I don’t know about ‘ultimate’ but there are some generalizations of up arrows:
https://en.m.wikipedia.org/wiki/Hyperoperation
https://en.m.wikipedia.org/wiki/Conway_chained_arrow_notatio...
Since ordinals are the ultimate recursion tool, any such function will ultimately grow faster than whatever recursive definition you can cook up by hand.
For instance even the slow growing hierarchy g_alpha, which grows very very slowly catches up to the fast hierarchy at extremely large ordinals.
Some examples:
- f_0 behaves like addition, f_1 like multiplication, f_2 like exponentiation, f_3 like tetration, f_w like Ackerman
- Graham number is bounded by f_{w+1}(64)
- Goodstein function behaves like f_{epsilon_0} (this show how much faster it grows than Ackerman). Similar for the Kirby-Paris Hydra
- n-Iterated goodstein behaves live f_{\phi(n-2,0)} where \phi is Veblen's function
- the tree function from Kruskal's tree theorem behaves like f_{\psi(Omega^Omega^omega}, ie by the small Veblen ordinal. And the graph function from the Robertson-Seymour theorem behaves like \psi(Omega_omega).
By contrast the slow growing hierarchy grows extremely slowly, for instance g_{epsilon_0} only grows like tetration. But it still catches up to the fast growing hierarchy at very large ordinals.
By "ultimate generalisation" I was speaking about a family of computable functions that ultimately grow faster than other functions you could cook up by hand: you put all the recursivity in the ordinals, they are there for that, and logicians are very good at constructing very large (recursive) ordinals.
If you just want a very very fast growing function (but that is still computable, unlike busy beaver), you can do the a light busy beaver version: Beaver(N)=the maximal output of all turing machines T with N state where there is a proof in ZFC of length <=N that T terminates.
This function grows much faster than the other functions I described (basically it is a f_{ordinal consistency of ZFC}. If you are interested in this kind of ideas, there is this reddit post that develops these ideas: https://www.reddit.com/r/math/comments/283298/how_to_compute...
Tetration delves past exponentiation into hyper-operations, whereas the Knuth arrow generalizes them. It is just a special case that x↑↑2=x@2.
We still need a new function, but at least Lambert-W comes up in other places as well- not much worse than introducing log.
If we discard the requirement to be an increasing function, one recursively defined solution takes f(3x + 1) = 3x + 2, f(3x + 2) = 3 * (3x + 1), and f(3x) = 3f(x), with f(0) = 0.
Or analogously for any way of splitting the positive integers not divisible by 3 into ordered pairs (a, b). Then define f(3^n a) = 3^n b and f(3^n b) = 3^(n + 1) a. This is the general form of the solutions.
assume f exists
increasing requires that x < f(x) < f(f(x))
f(f(0)) = 3*0 = 0 ≮ 0
therefore f does not exist, qed
So there is at least one solution.
The point about sqrt(3) not working for the naturals is a valid point, however.
Headdesk Yes, that's correct; I misparsed "increasing functions f" as "functions f that increase [the value passed through them]" and then got distracted by the discrete vs continuous confusion.
Edit: derp, it's ℕ, not ℤ⁺.
For a strictly increasing function change <= to <.
Your argument fails because you drop the antecedent in: x < f(x) => f(x) < f(f(x)). If f(0) = 0, you don’t have 0 < f(0) so can’t require that f(f(0))<f(0).
Note however that it is easy to show that f must be strictly increasing if it is increasing for if x is not y and f(x) = f(y) then 3x = f(f(x)) = f(f(y)) = 3y which cannot be the case.
[1] https://qr.ae/TaQ8y2
Interesting analysis of the problem :-) it has been bugging me since high school!
Might be worth linking to the Lambert W function https://en.wikipedia.org/wiki/Lambert_W_function
This was the best comment I'd reckon:
> As you probably saw, the solution of x^x = y is x = Log(y) / W[Log(y)]. Now you take us in a highly philosophical debate. What is the limit of elementary functions ? Thanks for this question. Cheers. – Claude Leibovici
https://en.wikipedia.org/w/index.php?title=Lambert_W_functio...
> (^~^:_1) 5
First, let me break this down, in the interest of sharing the joys of J.
The thing in parenthesis is our inverse operation of x^x; we then evaluate that at 5. The first ^ is exponentiation and the following ~ makes binary operators into unary ones by evaluating on the diagonal. In other words it turns f(x,y) into f(x) = f(x,x), which for x^y corresponds to x^x.
Next we have the ^: modifier. This is function iteration, i.e. exponentiation over function composition. The function is on the left (here ^~) and the count on the right (here _1). So f ^: 2 means f(f(x)). In fact, this function exponentiation is extended to negative integers as well! In J, negative numbers are prefixed with _ (underscore), and f^:_1 actually gives us the inverse of f (if it exists)!
Anyway, we can see inspect the definition for an operation's inverse using the b. verb. From the jconsole:
The part we are interested in is in single quotes. Pulling this one apart would involve introducing the various operator combinators in J, so suffice it to say that the ^:_ part numerically approximates a fixed point of the part in parenthesis, which essentially is a straightforward transcription of the recursive relation in Newton's method.Observe: W(x * e ^ x) = x
https://en.wikipedia.org/wiki/Lambert_W_functionBefore anyone jumps on me: I'm perfectly familiar and comfortable with functions that aren't defined in closed form.
The ratio of right triangle legs is "easily solved" by tan(x). But that's magical/cheating to someone who hasn't studied trigonometry.
Lambert-W is a well known function with known approximation methods; once you reduce your problem to it (in this case, trivially), you can lean on that knowledge from others.
We could repeat the same discussion at a lower level. Suppose you tell a bright middle schooler about the basics of integration, and the power rule. Then they ask,
"So what's the integral of 1/x? It can't be x^0/0..."
"That's a special case. It's a function called "natural logarithm", ln(x)."
"But what's the definition of that weird function?"
"It's defined to be the integral of 1/x." [0]
"That's pretty asinine..."
[0] https://en.wikipedia.org/wiki/Natural_logarithm#Definitions
x^x^x^... (infinite power tower) = 2.
If you solved it, try the general case of
x^x^x^... = y, for some arbitrary constant y.
{x, x^x, x^x^x, ...}
However, don't you have to prove that the series converges? Is the approach even valid if it doesn't?
EDIT: actually I guess it's more complicated than that. If I'm understanding the order of operations correctly, there's an alternating parity (where n is the number of exponentiations) thing going on with the values between 0 and 1
• for 1/e ≤ y ≤ e: x = y^(1/y)
• no solutions elsewhere
Can anyone prove the above? :-)
It's about an infinite chain of operations where each is to the last as multiplication is to addition.