Python function to solve Ax = b by back substitution - python

Okay, for my numerical methods class I have the following question:
Write a Python function to solve Ax = b by back substitution, where A is an upper triangular nonsingular matrix. MATLAB code for this is on page 190 which you can use as a pseudocode guide if you wish. The function should take as input A and b and return x. Your function need not check that A is nonsingular. That is, assume that only nonsingular A will be passed to your function.
The MATLAB code that it refers to is:
x(n) = c(u)/U(n,n)
for i = n-1 : -1 : 1
x(i) = c(i);
for j = i+1 : n
x(i) = x(i) - U(i,j)*x(j);
end
x(i) = x(i)/U(i,i);
end
My Python code, which I wrote using the MATLAB code snippet, is with an upper triangular test matrix(not sure if its nonsingular! How do I test for singularity?):
from scipy import mat
c=[3,2,1]
U=([[6,5,1],[0,1,7],[0,0,2]])
a=0
x=[]
while a<3:
x.append(1)
a=a+1
n=3
i=n-1
x[n-1]=c[n-1]/U[n-1][n-1]
while i>1:
x[i]=c[i]
j=i+1
while j<n-1:
x[i]=x[i]-U[i][j]*x[j];
x[i]=x[i]/U[i][i]
i=i-1
print mat(x)
The answer I am getting is [[1 1 0]] for x. I not sure if I am doing this correctly. I assume it is wrong and can't figure out what to do next. Any clues?

j=i+1
while j<n-1:
x[i]=x[i]-U[i][j]*x[j];
is infinite ... and never gets executed
your indexing is fubared:
for i in range(n-2,-1,-1):
....
for j in range(i+1,n):
notice, range is half open unlike matlab

One problem I see is that your input consists of integers, which means that Python is going to do integer division on them, which will turn 3/4 into 0 when what you want is floating point division. You can tell python to do floating point division by default by adding
from __future__ import division
To the top of your code. From the use of scipy, I'm assuming you're using Python 2.x here.

You ask how to test for singularity of an upper triangular matrix?
Please don't compute the determinant!
Simply look at the diagonal elements. Which ones are zero? Are any zero?
How about effective numerical singularity? Compare the smallest absolute value to the largest in absolute value. If that ratio is smaller than something on the order of eps, it is effectively singular.

Related

How to get numpy.exp to work with an array as well as a scalar?

I am working on an assignment that asks me to code the sigmoid function in Python. I'm very new to this so I sort of understand how the Sigmoid function works.
The assignment asks that I code it so that the function will work whether z is an array or a scalar. I know what an array is but I have no clue what a scalar is. And searches for it have only yielded math terms I don't understand. The assignment also suggests I use numpy.exp to solve the problem. Anyway, this is what I wrote and it clearly doesn't work. I am not sure if I got the logic wrong or if it's just because I am not considering the scalar vs array thing. Could anyone help me understan what that is or where to find that information?
This is the code:
def sigmoid(z):
'''
Input:
z: is the input (can be a scalar or an array)
Output:
h: the sigmoid of z
'''
### START CODE HERE (REPLACE INSTANCES OF 'None' with your code) ###
# calculate the sigmoid of z
h = 1/1+np.exp(-z)
### END CODE HERE ###
return h
# Testing your function
if (sigmoid(0) == 0.5):
print('SUCCESS!')
else:
print('Oops!')
if (sigmoid(4.92) == 0.9927537604041685):
print('CORRECT!')
else:
print('Oops again!')
You have to encapsulate the denominator of your fraction with parenthesis, like this:
h = 1/(1+np.exp(-z))
When you forget the parenthesis, you are actually evaluating 1 divided by 1 and then adding np.exp(0). This will lead you to 2, that's why your sum does not match with your 0.5 goal.
And scalars are regular numbers, in opposition to matrices or arrays.

if statement syntax Matlab

I'm trying to translate some Matlab code into Python. Unfortunately I don't have Matlab so I can't try out the syntax.
I'm confused about an if statement below
for i = 1:200
if mod(i,10) == 0
i
end
The for loop then carries on to calculate some values which depend on i. What does the if statement do?
Can I also ask what the difference between a sparse matrix and one made with zeros eg
A = sparse(n,m)
B = zeros(n,m)
Thanks!
It is usually better to create seperate questions, but I will try to address both:
1) The mod function performes the modulo operation, i.e. the remainder after division. mod(i,10) == 0 will be 1 if a number is divisible by 10, and 0 otherwise. The if statement will therefore be executed when the number i is a multiple of 10.
As there is no elsepart, nothing happens if the condition isn't true.
By just writing i (without semicolon), the current value of i is printed to the command window. The output of your example code will therefore be 10, 20, ..., 200.
2) The zeros command creates a "normal" matrix of (of course) zeros of dimension n x m. MATLAB also has a special sparse memory organization. As sparse matrices consist mostly of zeros, you don't need to fill the memory with all those zeros, but you can save the non-zero values and where they are. This is automatically done using the sparse function. To convert a sparse matrix to the "normal" format, you can use the full function.
The if statement checks whether the modulus (remainder after division) of i divided by 10 is 0 or not.
When it is evaluated true, it prints the number i to the command window.
The naive Python translation would be
for i in range(1, 201):
if not i % 10:
print(i)
but we can save some work by specifying a step value,
for i in range(10, 201, 10):
print(i)
See the documentation for mod. mod(i,10) returns the remainder after division of i by 10, where i is the dividend and 10 is the divisor. The if statement checks whether that remainder is equal to 0 or not.

Numpy - Creating a function whose inputs are two matrices and whose output is a binary matrix in Python

I am trying to write a function that take two m x n matrices as input and gives a binary matrix output, where 0 is returned if an element m,n is less than zero and returns 1 if else. I want these binary values to replace the values that were evaluated as negative or else in an array or matrix format. Here is my code that has produced errors thus far:
def rdMatrix(mat1, mat2):
mat3 = np.dot(mat1,mat2)
arr = [[]]
k = mat3(m,n)
for k in mat3:
if k < 0:
arr.append[0]
else:
arr.append[1]
I am having difficulty in telling the function to map a new value to each element in the matrix and then store it in an array. I'm also having trouble defining what a specific element of m x n is in the for loop. I am new to programming, so please forgive me for any obvious mistakes or errors that will easily fix this function. Also, please let me know if there is anything that needs clarification.
Any help is greatly appreciated, thank you!
This is NumPy, so you can obtain binary matrices using comparison operators.
For example, your code can be implemented very simply as
mat3 = np.dot(mat1, mat2)
return mat3 >= 0

Why am I getting errors using the Lambda function?

I am messing around with the lambda function and I understand what I can do with it in a simple fashion, but when I try something more advanced I am running into errors and I don't see why.
Here is what I am trying if you can tell me where I am going wrong it would be appricated.
import math
C = lambda n,k: math.factorial(n)/(math.factorial(k))(math.factorial(n-k))
print C(10,5)
I should note that I am running into errors trying to run the code on Codepad. I do not have access to Idle.
Try this:
from math import factorial
from __future__ import division
C = lambda n, k : factorial(n) / factorial(k) * factorial(n-k)
print C(10,5)
> 3628800.0
You were missing a *, and also it's possible that the division should take in consideration decimals, so the old division operator / won't do. That's why I'm importing the new / operator, which performs decimal division.
UPDATE:
Well, after all it seems like it's Codepad's fault - it supports Python 2.5.1, and factorial was added in Python 2.6. Just implement your own factorial function and be done with it, or even better start using a real Python interpreter.
def factorial(n):
fac = 1
for i in xrange(1, n+1):
fac *= i
return fac
I think you're missing a * between the second 2 factorial clauses. You're getting an error because you're trying to run (math.factorial(k))(math.factorial(n-k)), which turns into something like 10(math.factorial(n-k), which makes no sense.
Presumably the value you wish to compute is “n-choose-k”, the number of combinations of n things taken k at a time. The formula for that is n!/(k! * (n-k)!). When the missing * is added to your calculation, it produces n!/k! * (n-k)!, which equals (n!/k!)*(n-k)!. (Note, k! evenly divides n!.) For example, with n=10 and k=5, C(10,5) should be 3628800/(120*120) = 252, but your calculation would give 3628800/120*120 = 3628800, which is incorrect by a factor of 14400.
You can of course fix the parenthesization:
>>> C = lambda n,k: math.factorial(n)/(math.factorial(k)*math.factorial(n-k))
>>> C(10,5)
252
But note that if math.factorial(j) takes j-1 multiplications to calculate, then C(n,k) takes n-1+k-1+n-k-1+1 = 2*n-2 multiplications and one division. That's about four times as many multiply operations as necessary. The code shown below uses j multiplies and j divides, where j is the smaller of k and n-k, so j is at most n/2. On some machines division is much slower than multiplication, but on most machines j multiplies and j divides will run a lot faster than 2*n-2 multiplications and one division.
More importantly, C(n,k) is far smaller than n!. Computing via the n!/(k!*(n-k)!) formula requires more than 64-bit precision whenever n exceeds 20. For example, C(21,1) returns the value 21L. By contrast, the code below computes up to D(61,30)=232714176627630544 before requiring more than 64 bits to compute D(62,31)=465428353255261088L. (I named the function below “D” instead of “C” to avoid name clash.)
For small computations on big fast machines, the extra multiplies and extra precision requirements are unimportant. However, for big computations on small machines, they become important.
In short, the order of multiplications and divisions in D() keeps the maximum intermediate values that appear minimal. The largest values appear in the last pass of the for loop. Also note that in the for loop, i is always an exact divisor of c*j and no truncation occurs. This is a fairly standard algorithm for computing “n-choose-k”.
def D(n, k):
c, j, k = 1, n, min(k,n-k)
for i in range(1,k+1):
c, j = c*j/i, j-1
return c
Results from interpreter:
>>> D(10,5)
252
>>> D(61,30)
232714176627630544
>>> D(62,31)
465428353255261088L

Calculate poisson probability percentage

When you use the POISSON function in Excel (or in OpenOffice Calc), it takes two arguments:
an integer
an 'average' number
and returns a float.
In Python (I tried RandomArray and NumPy) it returns an array of random poisson numbers.
What I really want is the percentage that this event will occur (it is a constant number and the array has every time different numbers - so is it an average?).
for example:
print poisson(2.6,6)
returns [1 3 3 0 1 3] (and every time I run it, it's different).
The number I get from calc/excel is 3.19 (POISSON(6,2.16,0)*100).
Am I using the python's poisson wrong (no pun!) or am I missing something?
scipy has what you want
>>> scipy.stats.distributions
<module 'scipy.stats.distributions' from '/home/coventry/lib/python2.5/site-packages/scipy/stats/distributions.pyc'>
>>> scipy.stats.distributions.poisson.pmf(6, 2.6)
array(0.031867055625524499)
It's worth noting that it's pretty easy to calculate by hand, too.
It is easy to do by hand, but you can overflow doing it that way. You can do the exponent and factorial in a loop to avoid the overflow:
def poisson_probability(actual, mean):
# naive: math.exp(-mean) * mean**actual / factorial(actual)
# iterative, to keep the components from getting too large or small:
p = math.exp(-mean)
for i in xrange(actual):
p *= mean
p /= i+1
return p
This page explains why you get an array, and the meaning of the numbers in it, at least.

Categories