Trouble with calling methods - python

import math
class Vector():
vA = [3.183, 7.627]
def magnitude(vector):
sum = 0
i = 0
while i < len(vector):
sum += vector[i]
i += 1
return math.sqrt(sum)
def unitVector(vector):
print( 1 / (magnitude(vA) * vA))
I'm attempting to code some linear algebra and calculate the unit vectors for the vector 'vA' stated above. When I run the code I get NameError: global name 'magnitude' is not defined. I do not understand why I am having an issue with simply calling one function from another.
I'm a beginner with python and I'm assuming I have a misunderstanding about classes and functions, but I have looked through the documentation and cannot find the answer I am looking for.

You have several errors in your code:
def magnitude(vector) should be def magnitude(self, vector)
def unitVector(vector) should be def unitVector(self, vector)
magnitude(vA) should be self.magnitude(vA)
EDIT:
A better way of writing your class would be to use OOP concepts in Python, so you do not have to pass vector as a function argument if you make it an instance variable.
Your class can be rewrote like this:
import math
class Vector():
def __init__(self, vector):
self.vector = vector
def magnitude(self):
sum = 0
i = 0
while i < len(self.vector):
sum += self.vector[i]
i += 1
return math.sqrt(sum)
def unitVector(self):
print( 1 / (self.magnitude() * self.vector))
vA = [3.183, 7.627]
vec = Vector(vA)
vec.unitVector()
Be aware that it does not work. Because in unitVector, Python doesn't know how to multiply a float by a list (self.magnitude() returns a float and self.vector is a list). You probably want to rework this part.

Related

How to define toString method?

I have just almost finished my assignment and now the only thing I have left is to define the tostring method shown here.
import math
class RegularPolygon:
def __init__(self, n = 1, l = 1):
self.__n = n
self.__l = l
def set_n(self, n):
self.__n = n
def get_n(self):
return self.__n
def addSides(self, x):
self.__n = self.__n + x
def setLength(self, l ):
self.__l = l
def getLength(self):
return self.__l
def setPerimeter(self):
return (self.__n * self.__l )
def getArea(self):
return (self.__l ** 2 / 4 * math.tan(math.radians(180/self.__n)))
def toString(self):
return
x = 3
demo_object = RegularPolygon (3, 1)
print(demo_object.get_n() , demo_object.getLength())
demo_object.addSides(x)
print(demo_object.get_n(), demo_object.getLength())
print(demo_object.getArea())
print(demo_object.setPerimeter())
Basically the tostring on what it does is return a string that has the values of the internal variables included in it. I also need help on the getArea portion too.
Assignment instructions
The assignment says
... printing a string representation of a RegularPolygon object.
So I would expect you get to choose a suitable "representation". You could go for something like this:
return f'{self.__n+2} sided regular polygon of side length {self.__l}'
or as suggested by #Roy Cohen
return f'{self.__class__.__name__}({self.__n}, {self.__l})'
However, as #Klaus D. wrote in the comments, Python is not Java, and as such has its own standards and magic methods to use instead.
I would recommend reading this answer for an explanation between the differences between the two built-in string representation magic-methods: __repr__ and __str__. By implementing these methods, they will automatically be called whenever using print() or something similar, instead of you calling .toString() every time.
Now to address the getters and setters. Typically in Python you avoid these and prefer using properties instead. See this answer for more information, but to summarise you either directly use an objects properties, or use the #property decorator to turn a method into a property.
Edit
Your area formula is likely an error with order-of-operations. Make sure you are explicit with which operation you're performing first:
return self.__l ** 2 / (4 * math.tan(math.radians(180/self.__n)) )
This may be correct :)

Markov Chain montecarlo integration and infinite while loop

I'm implementing a Markov Chain Montecarlo with metropolis and barkes alphas for numerical integration. I've created a class called MCMCIntegrator(). I've loaded it with some attributes, one of then is the pdf of the function (a lambda) we're trying to integrate called g.
import numpy as np
import scipy.stats as st
class MCMCIntegrator:
def __init__(self):
self.g = lambda x: st.gamma.pdf(x, 0, 1, scale=1 / 1.23452676)*np.abs(np.cos(1.123454156))
self.size = 10000
self.std = 0.6
self.real_int = 0.06496359
There are other methods in this class, the size is the size of the sample that the class must generate, std is the standard deviation of the Normal Kernel, which you will see in a few seconds. The real_int is the value of the integral from 1 to 2 of the function we're integrating. I've generated it with a R script. Now, to the problem.
def _chain(self, method=None):
"""
Markov chain heat-up with burn-in
:param method: Metrpolis or barker alpha
:return: np.array containing the sample
"""
old = 0
sample = np.zeros(int(self.size * 1.5))
i = 0
if method:
def alpha(a, b): return min(1, self.g(b) / self.g(a))
else:
def alpha(a, b): return self.g(b) / (self.g(a) + self.g(b))
while i != len(sample):
new = st.norm(loc=old, scale=self.std).rvs()
new = abs(new)
al = alpha(old, new)
u = st.uniform.rvs()
if al > u:
sample[i] = new
old = new
i += 1
return np.array(sample)
Below this method is an integrate() method that calculates the proportion of numbers in the [1, 2] interval:
def integrate(self, method=None):
"""
Integration step
"""
sample = self._chain(method=method)
# discarding 30% of the sample for the burn-in
ind = int(len(sample)*0.3)
sample = sample[ind:]
setattr(self, "sample", sample)
sample = [1 if 1 < v < 2 else 0 for v in sample]
return np.mean(sample)
This is the main function:
def main():
print("-- RESULTS --".center(20), end='\n')
mcmc = MCMCIntegrator()
print(f"\t{mcmc.integrate()}", end='\n')
print(f"\t{np.abs(mcmc.integrate() - mcmc.real_int) / mcmc.real_int}")
if __name__ == "__main__":
main()
I'm stuck in an infinity while loop and I have no idea why this is happening.
Couple things... You are hung up in the chain method because the alpha computation is returning NaN, because g() is returning NaN. Take a look at the print statements I inserted into your code and run it...
tips:
Make g() a class function just like chain.
Test g() on some test values, something is clearly amiss
Don't conditionally define a function like alpha. Wayyy confusing and error prone/tough to troubleshoot. Just pass alpha what it needs and you also can make it a class function alpha(a, b, method=None)
Take a look at where you are updating i in the `_chain' function.... You realize you are risking a long looping process because you only update i conditionally!
You are set up for disaster with your use of numpy array. You may have a bunch of trailing zeros after your actual data because you are over-writing the large zeros list. You do NOT need numpy array here, just use a python empty list and append new values to it, either zero or one...based on whatever.
Add a couple print statements in when you are troubleshooting (or unit test your functions). Try my adds to your function below... it is what I used to figure out what was going on
def _chain(self, method=None, verbose=True):
"""
Markov chain heat-up with burn-in
:param method: Metrpolis or barker alpha
:return: np.array containing the sample
"""
old = 0
sample = np.zeros(int(self.size * 1.5))
i = 0
if method:
def alpha(a, b): return min(1, self.g(b) / self.g(a))
else:
def alpha(a, b):
if verbose: print(f'g(a): {self.g(a)}, g(b): {self.g(b)}')
return self.g(b) / (self.g(a) + self.g(b))
while i != len(sample):
new = st.norm(loc=old, scale=self.std).rvs()
new = abs(new)
al = alpha(old, new)
u = st.uniform.rvs()
if verbose: print(f'old: {old:.3f} new: {new:.3f} alpha: {al:.3f} u: {u:.3f}')
if al > u:
sample[i] = new
old = new
i += 1 # do you really want to conditionally update i?
sys.exit(-1) # to breakout of infinite loop...
return np.array(sample)

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)

Guidance needed with 'class' task (beginner)

It looks daunting, but please bear with me, it's not as difficult as it looks. I have a code here about beam deflection. It's just some maths and numbers at this point. Only the last part requires attention.
class beam(object):
"""This class is models the deflection of a simply supported beam under
multiple point loads, following Euler-Bernoulli theory and the principle of
superposition.
"""
def __init__(self, E, I, L):
"""The class costructor.
"""
self.E = 8.0E9 # Young's modulus of the beam in N/m^2
self.I = 1.333E-4 # Second moment of area of the beam in m^4
self.L = 5.0 # Length of the beam in m
self.Loads = [(0.0, 0.0)] # the list of loads applied to the beam
self.name = "beam"
def setLoads(self, Loads):
'''This function allows multiple point loads to be applied to the beam
using a list of tuples of the form (load, position)
'''
self.Loads = Loads
The "def __ init __" and "def setLoads" were given, so the above doesn't need changing. I inputted values for self.E, I and L since I thought I needed them there, but those numbers can be replaced back to the letters that they were before.
def beamDeflection(self, Load, x):
"""Just a simple calculation, really.
"""
E = 8.09 * (10 ** 9)
I = 1.333 * (10 ** -4)
L = 5
a = 2.5
b = a + (x - a)
(P1, a) = Load
if 0 <= x <= 2.5:
beamDeflection = ((P1*b*x)/(6*L*E*I))*((L**2)-(x**2)-(b**2))
else:
if 2.5 < x <= 5:
beamDeflection = ((P1*b)/(6*L*E*I)) / (((L/b)*((x-a)**3)) -
(x**3) + (x*((L**2) -
(b**2))))
return beamDeflection
The above "beamDeflection" is the simple code I typed up that just calculates deflection in a beam using a formula that's already been given. Essentially, if a weight is put on the left side of the beam, it'll calculate a number out and the same for the other side.
def getTotalDeflection(self, x):
"""The function getTotalDeflection(self, x) should go through each load tuple in the
list.Loads and calculate the beam deflection at point x (Hint: the function you just
created could be handy here!). getTotalDeflection should return the total deflection at x,
which is the sum over each of the individual deflections.
"""
My understanding is that I need to a "for" loop to go through each load tuple while involving the self.load. I'm not sure on how to go about combining both of those things together. If anyone can help me out, I'd really, really appreciate it.
What you are looking for is probably this (else please clarify):
def getTotalDeflection(self, x):
return sum(self.beamDeflection(loadval, x) for loadval in self.Loads)
I think this is what you want:
def getTotalDeflection(self, x):
total = 0
# For every load in `Loads`
for load in self.Loads:
# Compute the deflection and add it to the total
total += self.beamDeflection(load, x):
return total

Calculate nth term of Fibonacci sequence in 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

Categories