0

If I have this Haskell function:

Consider the following Haskell function f :

f :: Int -> Int
f 0 = 1
f x = x * x * f (x - 1)

Then how can I calculate its fixpoint and the least fixpoint (in closed form)?

The answer to this question is :

enter image description here

How is this least fixpoint calculated? I am trying to understand this, but still no luck. It will be great if someone could explain this to me.

Community
  • 1
  • 1
Waqar Ahmed
  • 4,682
  • 1
  • 19
  • 38
  • 4
    As posted, it's bottom since the function is strict. But I guess you might actually want the least fixed point of the related functional `\f n -> case n of 0->1 ; x->x*x*f(x-1)` which has type `(Int -> Int) -> (Int -> Int)`, and has a non trivial least fixed point. – chi Aug 13 '16 at 16:57
  • @chi then what will be the least fixpoint?, like i understand how to define the type, but how to write LFP in closed form. – Waqar Ahmed Aug 13 '16 at 17:00
  • 3
    Isn't it 1 ? f 1 = 1 * 1 * f(0) = 1. On all other integers f x is different from x, so 1 is the only fixpoint. – V. Semeria Aug 13 '16 at 17:24
  • 1
    @WaqarAhmed Assuming you are working in a semantic domain that is a CPO you know that to find the least fixed point you can start from the bottom element and go upwards. So in chi's code put `f=undefined` and you end up with `\n -> case n of 0-> 1; x -> x*x*undefined (x-1)` which is the function that is `1` when `n=0` and undefined otherwise. Now put this function as `f` and you end up with a function that is `1` in both the `0` and `1` case etc. in the end the least fixed point is the limit: which is just the constant function `1` as noted by V. Semeria. – Bakuriu Aug 13 '16 at 18:03
  • @Bakuriu. Thank you for explaining it. I got this one, but the answer to this one is a little different notation that i am unable to grab. I have edited my question and added answer there, can you have a look please. Thank you. – Waqar Ahmed Aug 13 '16 at 18:11
  • 1
    @WaqarAhmed Indeed I was wrong. Consider the case when we have `f 0 = 1` and `f 1 = 1` while `f x = undefined`. Now we end up with `case n of 0 -> 1; x -> x*x*f(x-1)` which is `1` for `n=0, 1` but is `4` for `n=2` (because `2*2*f(1) = 2*2*1=4`) and undefined for `n>2`. In the next step you end up with `3*3*f(2) = 3*3*4 = 36` etc. Every iteration defines `f` for the next value of `n` as `n**2 * f(n-1)`. The `!` denotes *factorial* `5! = 5*4*3*2*1` and since we always multiply squares we end up with `(n!)**2 = (n*(n-1)*(n-2)*...*1) *(n*(n-1)*(n-2)*...*1) = n**2*(n-1)**2 * (n-2)**2*...*1**2` – Bakuriu Aug 13 '16 at 18:19
  • @Bakuriu Thank you again for this one. I have aquestion. The square is on n (n**2) but not on (f(n-1)), then why the factorial is getting squared? also how the answer is represented using this result(The one that i have added in the question) – Waqar Ahmed Aug 13 '16 at 18:33
  • @V.Semeria I have edited my question with the provided answer – Waqar Ahmed Aug 13 '16 at 18:35
  • @chi I have edited my question with the provided answer. – Waqar Ahmed Aug 13 '16 at 18:35
  • 2
    @V.Semeria It's true that `1` is a fixed-point; but it's not the _least_ fixed point in the standard ordering that puts bottom under `1` (and under all other fully-defined `Int`s, which are incomparable with each other). – Daniel Wagner Aug 13 '16 at 18:45
  • 1
    @WaqarAhmed A rough but intuitive explanation is that by unfolding the recursion many times we get `f n = n * n * (n-1) * (n-1) * (n-2) * (n-2) * .... * 1` This is like the factorial except that every factor appears twice, hence the factorial squared. If n is negative instead we diverge since we never reach the base case. In general, there's no simple recipe that can provide the closed form of a recursive function -- one has to "guess" it by observing some pattern, and then possibly prove it by induction. – chi Aug 13 '16 at 19:17
  • @chi I have a confusion that, if we see only question, n is applied twice but function is applied only once, then how come the factorial get squared – Waqar Ahmed Aug 13 '16 at 19:19
  • Because otherwise you square each factor more than once. You would get something like ` (((1^2 * 2)^2 * 3)^2 * 4)^2 ...` Note how e.g. 2 was squared each time we recurse. We don't want to square the recursive call since it is "already squared", roughly put. – chi Aug 13 '16 at 21:37

1 Answers1

0

It is easy to see that

f x = x * x * f (x-1)
    = x * x * ((x-1) * (x-1) * f (x-2))
    = x * x * ((x-1) * (x-1) * ((x-2) * (x-2) * f (x-3)))
    = ...
    = x * x * ((x-1) * (x-1) * ((x-2) * (x-2) * ... * 1)))

Now to answer your question in the comments about how this is equivalent to the given formula (x!)^2 when the recursive result f (x-1) is not squared, just rearrange the factors above, using associativity and commutativity of (*) over Int :

      x * x * ((x-1) * (x-1) * ((x-2) * (x-2) * ... * 1)))
    = x * x * (x-1) * (x-1) * (x-2) * (x-2) * ... * 1
    = (x * (x-1) * (x-2) * ... * 1) * (x * (x-1) * (x-2) * .. * 1)
    = x!                            * x!
    = (x!)^2
Cactus
  • 25,576
  • 9
  • 60
  • 130