Calculate nth term of Fibonacci sequence in Python - python

The following code is to calculate nth term og fibonacci sequence in python using matrix exponentiation for various test cases t.But the program gives absurd output.Please tell me where i am wrong.when i ran the code in C++ it runs perfectly.
class matrix:
def __init__(self):
self.a=self.b=self.c=1
self.d=0
def mul(self,e,f):
ret = matrix()
ret.a=(e.a*f.a)+(e.b+f.c)
ret.b=(e.a*f.b)+(e.b+f.d)
ret.c=(e.c*f.a)+(e.d+f.c)
ret.d=(e.c*f.b)+(e.d+f.d)
return ret
def exp(self,a,p):
if(p==0):
temp=matrix()
temp.a=temp.b=temp.c=temp.d=1
return temp
if(p==1):
return a
if(p%2==0):
return self.exp(self.mul(a,a),p/2)
else:
return self.mul(a,self.exp(self.mul(a,a),(p-1)/2))
def fib(self,n):
if (n==0):
return 0
if (n==1):
return 1
s=matrix()
s=self.exp(s,n)
return s.d
t=int(raw_input())
while(t>0):
v=matrix()
n=int(raw_input())
print v.fib(n)
t=t-1

The problem lies in your __init__ function. In python the so-called variables are just 'tags' to data in the memory. To compare with C/C++, these can be thought of as pointers. when you assign self.a = self.b = self.c, you are basically assigning three different names to the same data in the memory. Any change you make in a will be reflected back in b and c and so on.
For your problem where you need three separate variables, one way to change the __init__ function is like:
self.a, self.b, self.c = 1, 1, 1
or you can use copy. copy() tells python to assign a new memory location and then assign the tag on the right hand side to that location. For more read the official documentation on this http://docs.python.org/2/library/copy.html. You can also read a short walk-through on this in Python Tutorial: Shallow and Deep-copy

There are several issues, in order of importance:
1) Your multiplication is wrong. Note the multiplications at the right where you have sums):
def mul(self,e,f):
ret = matrix()
ret.a=(e.a*f.a)+(e.b*f.c)
ret.b=(e.a*f.b)+(e.b*f.d)
ret.c=(e.c*f.a)+(e.d*f.c)
ret.d=(e.c*f.b)+(e.d*f.d)
return ret
2) In the last line, you do return s.d but you should return s.b or s.c or you will get one less fibonacci.
3) The line temp.a=temp.b=temp.c=temp.d=1 is not necessary because the constructor does the work. Besides it is wrong, because d should be 0.
4) Why are mul and exp class functions if they don't use self. It does no harm but they should be #staticmethod
5) Again, it does no harm but your second recursive call is unnecessarily complex. Just write:
return matrix.mul(a,matrix.exp(a, p-1))

I'm not sure if it is required for you to use matrix exponentiation for this problem. Unfortunately, I do not know much about Python classes quite yet. However, the following code does what the question heading wants: to find the n-th Fibonacci number. Below I describe this as F_n. Note the initial conditions for low values of n.
def fibN( n ):
"""
fibonacci: int -> int
Returns F_n.
Note: F_1 = 0, F_2 = 1, F_3 = 1, F_4 = 2
"""
n = abs( int( n ))
if n == 0:
fib = 0
elif n == 1:
fib = 1
else:
counter = 2
f0 = 0
f1 = 1
fib = f0 + f1
while counter <= n:
fib = f0 + f1
f0 = f1
f1 = fib
counter += 1
return fib

Related

Making a class process A 2 by 2 Matrix and having issues return it through __str__

so I have to process a 2 by 2 matrix through a class and return print the output with str. I can't really create new functions and I'm pretty sure the math is good with the matrices, I'm just having some output issues. I marked the area, specifically really the output that I cannot modify, but I can modify the class to support it.
Here's my code.
# This code aims to take a 2 by 2 matrix and add, subtract, and multiply it by another matrix, as well as inverse and power it.
# ----------------------------------------------------------------------------------------------------------------------
# This is how we'll use math.nan and only math.nan
import math
# Your classes should go here
class Matrix2x2: # Just initializing as needed.
def __init__(self,a,b,c,d):
self.a = a
self.b = b
self.c = c
self.d = d
def __add__(self,second):
return(Matrix2x2(self.a+second.a,self.b+second.b,self.c+second.c,self.d+second.d))
def __sub__(self, second): # Just subtracting instead of adding
return(Matrix2x2(self.a - second.a,self.b-second.b,self.c-second.c,self.d-second.d))
def __mul__(self, second): # Multiplying them based on the according spot and some addition.
return(Matrix2x2(self.a*second.a+self.b*second.c,self.a*second.b+self.b*second.d,self.c*second.a+self.d*second.c,self.c*second.b+self.d*second.d))
def __pow__(self, power): # Process varies based on what we work with.
StoredMatrix = Matrix2x2(self.a, self.b, self.c, self.d) # The variables just save information and make the math more clean.
determinant = 1/((self.a*self.d)-(self.b*self.c)) # Used to simplify inversing and determine if there is an inverse.
InverseMatrix = Matrix2x2(self.d*determinant,-self.b*determinant,-self.c*determinant, self.a*determinant)
if power > 0:
count = 1
while count < power: # The original matrix is repeatedly multiplied and stored until it matches the power value.
count+=1
StoredMatrix *= Matrix2x2(self.a, self.b, self.c, self.d)
return StoredMatrix
elif power < 0:
count = 0
while count < power:
count+=1
InverseMatrix *= Matrix2x2(self.d*determinant,-self.b*determinant,-self.c*determinant,self.a*determinant)
return InverseMatrix
if determinant == 0 or power == 0: # This means that there is no inverse, or the power value is 0 and invalid.
return(Matrix2x2(math.nan, math.nan, math.nan, math.nan))
def __str__(self):
return print('[',str(self.a) ,str(self.b) ,']\n' ,'\b[' ,str(self.c) ,str(self.d),']')
# Do NOT use any pre-built packages to perform the below operations, each should
# be coded using regular mathematics operation (+,-,*,/), no numpy or math functions other
# than math.nan
# Code below cannot be modified
A = Matrix2x2(1,2,3,4)
B = Matrix2x2(4,3,2,1)
print('Addition: A+B')
print(A,"+\n",B,"=\n",A+B,sep="")
input(),print('Subtraction: A-B')
print(A,"-\n",B,"=\n",A-B,sep="")
input(),print('Multiplication: A*B')
print(A,"*\n",B,"=\n",A*B,sep="")
input(),print('Multiplication: B*A')
print(B,"*\n",A,"=\n",B*A,sep="")
input(),print('Powers: A^3 ')
print(A,"^3","\n=\n",A**3,sep="")
input(),print('Inverse: A^-1 ')
print(A,"^-1","\n=\n",A**(-1),sep="")
input(),print('Inverse with powers: A^-3 = (A^-1)^3')
print(A,"^-3","\n=\n",A**(-3),sep="")
# code above cannot be modified
# Just for testing, below.
print(A.__add__(B))
print(A.__sub__(B))
print(A.__mul__(B))
print(A.__pow__(3))
print(A.__pow__(-1))
print(A.__pow__(0))
print(A.__pow(-3))
I usually get an error due a NoneType with the add function. This doesn't allow me to see what errors I'd get. I tried just converting them to strings individually using str() and got the same error. I don't think it's the math.nan's either.
Here is an example:
Addition: A+B
[ 1 2 ]
[ 3 4 ]
Traceback (most recent call last):
File "ThisWasPurposelyCensored", line 51, in <module>
print(A,"+\n",B,"=\n",A+B,sep="")
TypeError: __str__ returned non-string (type NoneType)
Process finished with exit code 1
Anyways, how do I avoid that NoneType issue or get this to be compatible with str, without interfering with the math and required input too much? I'll provide anymore information you might need to help me solve this.
Rewrite your __str__ method to be like this
def __str__(self):
return '[ {} {} ]\n[ {} {} ]'.format(self.a, self.b, self.c, self.d)
A bit shorter
def __str__(self):
return '[ {x.a} {x.b} ]\n[ {x.c} {x.d} ]'.format(x=self)

Replacing global vars

Below, I came up with artificially passing the reference var n2 from f2() to g2(x) instead of the global var n in f() and the nested g(). Any other better ways to replace global vars in this case?
from random import randint
# global value var
def f():
global n
n=0
def g():
global n
if randint(1,100)>50: n+=1
for _ in range(100): g()
print(n)
# local reference var
def f2():
n2=[0]
for _ in range(100): g2(n2)
print(n2[0])
def g2(x):
if randint(1,100)>50: x[0]+=1
Short answer: You are trying to pass by reference an immutable value (integer) and want to update it. Wrapping that in a tiny class, or list, or dict like you're doing is the way to go. But there are other ways if you are able to slightly modify your code.
Longer answer: (Note: This might not be a direct answer to your question.)
I understand this is an artificial example. But think about your real problem --Does g2() need to know that there is a variable that is supposed to update as a part of its invocation? Is there a way that the responsibility of updating a variable belongs to that which defines it? How about f2() is the one that defines the variables and also updates it? That way you can limit all the changes to that variable to a very small perimeter (f2()).
My approach in that case would be something like:
def f2():
n2 = 0
for _ in range(100):
n2 += g2()
print(n2)
def g2():
return 1 if randint(1,100)>50 else 0
From working with functional languages, and from trying to write reproducible tests, I've generally tried to adopt a rule that a function should declare all of its inputs as parameters, and produce all of its outputs as return values: to the maximum extent possible a function should never have side effects. Using the global keyword probably indicates you're breaking this rule.
For example, your "g" function takes the current state variable and either increments it or doesn't. You don't need a global for that (and you don't need it to be a nested function either):
from random import randint
def g(n):
"""Returns either n or n+1, with 50% probability."""
if randint(1,100)>50:
return n+1
else:
return n
Then the iterating function can call that a bunch of times:
def f():
"""Produces a number between 0 and 100 with $DISTRIBUTION."""
n = 0
for _ in range(100):
n = g(n)
return n
And finally at the top level:
if __name__ == '__main__':
print(f())
Since we're never totally sure about our code, we can write some tests.
def test_f():
n = f()
assert n >= 0 and n < 100
def test_g():
n = g(0)
assert n == 0 or n == 1
def test_g_dist():
count = 100
ns = [g(0) for _ in range(count)]
assert(all(n == 0 or n == 1) for n in ns)
zeros = len([n for n in ns if n == 0])
ones = len([n for n in ns if n == 1])
assert zeros + ones == count
# won't always pass; probability of failure left as an exercise
assert zeros > 0.45 * count and zeros < 0.55 * count
Notice that I can call f() and g(n) as many times as I want and they'll never interfere with anything else. Running my own unit tests at startup time would be a little unusual, but I'm free to if that's what I want to do.

if Python doesn't support method overloading, then why does this method overload work while this other does not?

If Python does not support method overloading (besides *args and **kwargs or PEP 3124), then why does this overload work?
# the sum from 1 to n
def sum(n):
if n > 0:
return n + sum(n - 1)
else:
return 0
print(sum(3))
# the sum from n to m, inclusive
def sum(n, m):
if n <= m:
return n + sum(n + 1, m)
else:
return 0
print(sum(3,5))
... while more baffling, this one does not:
# the sum of elements in an array
def sumArray(A):
return sumArray(A, len(A)-1)
# a helper for the above
def sumArray(A, i):
if i < 0:
return 0
else:
return A[i] + sumArray(A, i-1)
print(sumArray([1,2,3]))
You aren't overloading. You're hiding one thing behind another by using the same name for different objects. Try
sum = 42
and see how print(sum(3, 5)) ceases to work.
Function definitions are variable assignments. They create a function and assign it to the variable matching the name you used. You're seeing the ordinary effects of reassigning a variable.
def sum(n):
...
This assigns a function of 1 argument to the variable sum.
print(sum(3))
This uses the function assigned to that variable.
def sum(n, m):
...
This assigns a new function to the variable sum, replacing the first function.
print(sum(3,5))
This uses the new function. If you had tried to use the old function, you wouldn't find it.
# the sum of elements in an array
def sumArray(A):
return sumArray(A, len(A)-1)
# a helper for the above
def sumArray(A, i):
if i < 0:
return 0
else:
return A[i] + sumArray(A, i-1)
print(sumArray([1,2,3]))
This assigns a function to sumArray, then assigns a different function to sumArray, then tries to use the value from the first assignment. It finds the second function, and fails.
In your first example, you define function and use it, then overwrite it with another, and use the new one, just like with regular variables:
a = 1
print(a)
a = 2
print(a)

calculating current value based on previous value

i would like to perform a calculation using python, where the current value (i) of the equation is based on the previous value of the equation (i-1), which is really easy to do in a spreadsheet but i would rather learn to code it
i have noticed that there is loads of information on finding the previous value from a list, but i don't have a list i need to create it! my equation is shown below.
h=(2*b)-h[i-1]
can anyone give me tell me a method to do this ?
i tried this sort of thing, but that will not work as when i try to do the equation i'm calling a value i haven't created yet, if i set h=0 then i get an error that i am out of index range
i = 1
for i in range(1, len(b)):
h=[]
h=(2*b)-h[i-1]
x+=1
h = [b[0]]
for val in b[1:]:
h.append(2 * val - h[-1]) # As you add to h, you keep up with its tail
for large b list (brr, one-letter identifier), to avoid creating large slice
from itertools import islice # For big list it will keep code less wasteful
for val in islice(b, 1, None):
....
As pointed out by #pad, you simply need to handle the base case of receiving the first sample.
However, your equation makes no use of i other than to retrieve the previous result. It's looking more like a running filter than something which needs to maintain a list of past values (with an array which might never stop growing).
If that is the case, and you only ever want the most recent value,then you might want to go with a generator instead.
def gen():
def eqn(b):
eqn.h = 2*b - eqn.h
return eqn.h
eqn.h = 0
return eqn
And then use thus
>>> f = gen()
>>> f(2)
4
>>> f(3)
2
>>> f(2)
0
>>>
The same effect could be acheived with a true generator using yield and send.
First of, do you need all the intermediate values? That is, do you want a list h from 0 to i? Or do you just want h[i]?
If you just need the i-th value you could us recursion:
def get_h(i):
if i>0:
return (2*b) - get_h(i-1)
else:
return h_0
But be aware that this will not work for large i, as it will exceed the maximum recursion depth. (Thanks for pointing this out kdopen) In that case a simple for-loop or a generator is better.
Even better is to use a (mathematically) closed form of the equation (for your example that is possible, it might not be in other cases):
def get_h(i):
if i%2 == 0:
return h_0
else:
return (2*b)-h_0
In both cases h_0 is the initial value that you start out with.
h = []
for i in range(len(b)):
if i>0:
h.append(2*b - h[i-1])
else:
# handle i=0 case here
You are successively applying a function (equation) to the result of a previous application of that function - the process needs a seed to start it. Your result looks like this [seed, f(seed), f(f(seed)), f(f(f(seed)), ...]. This concept is function composition. You can create a generalized function that will do this for any sequence of functions, in Python functions are first class objects and can be passed around just like any other object. If you need to preserve the intermediate results use a generator.
def composition(functions, x):
""" yields f(x), f(f(x)), f(f(f(x)) ....
for each f in functions
functions is an iterable of callables taking one argument
"""
for f in functions:
x = f(x)
yield x
Your specs require a seed and a constant,
seed = 0
b = 10
The equation/function,
def f(x, b = b):
return 2*b - x
f is applied b times.
functions = [f]*b
Usage
print list(composition(functions, seed))
If the intermediate results are not needed composition can be redefined as
def composition(functions, x):
""" Returns f(x), g(f(x)), h(g(f(x)) ....
for each function in functions
functions is an iterable of callables taking one argument
"""
for f in functions:
x = f(x)
return x
print composition(functions, seed)
Or more generally, with no limitations on call signature:
def compose(funcs):
'''Return a callable composed of successive application of functions
funcs is an iterable producing callables
for [f, g, h] returns f(g(h(*args, **kwargs)))
'''
def outer(f, g):
def inner(*args, **kwargs):
return f(g(*args, **kwargs))
return inner
return reduce(outer, funcs)
def plus2(x):
return x + 2
def times2(x):
return x * 2
def mod16(x):
return x % 16
funcs = (mod16, plus2, times2)
eq = compose(funcs) # mod16(plus2(times2(x)))
print eq(15)
While the process definition appears to be recursive, I resisted the temptation so I could stay out of maximum recursion depth hades.
I got curious, searched SO for function composition and, of course, there are numerous relavent Q&A's.

How can I pass functions or operators as arguments to a function in Python?

...while still leaving it executable within the function.
The idea behind this is I want to create a summation function. Here's what I have so far:
def summation(n, bound, operation):
if operation is None and upper != 'inf':
g = 0
for num in range(n, limit + 1):
g += num
return g
else:
pass
But summations are most often about infinite convergent series (for which I use 'inf'), with operations applied to each term. Ideally, I'd like to be able to write print summation(0, 'inf', 1 / factorial(n)) and get the mathematical constant e, or def W(x): return summation(1, 'inf', ((-n) ** (n - 1)) / factorial(n)) to get the Lambert W function.
All that comes to my mind is passing the appropriate arithmetic as a string and then using the exec statement to execute it. But I don't think that would accomplish the whole thing, and it's obviously dangerous to use exec with possibly user-entered code.
In Python, functions are first-class, which is to say they can be used and passed around like any other values, so you can take a function:
def example(f):
return f(1) + f(2)
To run it, you could define a function like this:
def square(n):
return n * n
And then pass it to your other function:
example(square) # = square(1) + square(2) = 1 + 4 = 5
You can also use lambda to avoid having to define a new function if it's a simple expression:
example(lambda n: n * n)

Categories