6

I'm new to python and trying to do a HW assignment and it keeps throwing this error back at me (in iPython Notebook):

"TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'float'"

Here's the formula i'm trying to imitate: h(x)=(1/√2π)*e^−(1/2)^x^2

import numpy as np
import math
from math import *


def h_scalar(x):
    return (1 / sqrt(2 * pi)) * exp(-.50** x ** 2.00)

I'm trying to get the same out put as my teacher.

l = [-10.0, -1.0, 0.0, 1.0, 10.0] #
print h_scalar(l)
>>> [1.4867195147342977e-06, 0.24197072451914337, 0.3989422804014327,
0.24197072451914337, 1.4867195147342977e-06]

Here's the teachers question btw:

First of all, write a function called h_scalar. The function should expect a list (or in general an item that is iterable). It will expect that the list contains floating point values. It should return a new list of floats that are the h(x) for each x value in the input list. You should name your function h_scalar()

Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
user2839099
  • 61
  • 1
  • 1
  • 2
  • 2
    1.) Your exponential should be `-.50 * x ** 2.00`. 2.) You cannot broadcast an operation like `**2.00` across a standard python array. To do this, convert `x` to a `np.array`. 3.) If you don't want to use numpy, consider using a `for` loop to compute the formula for each element in `x`. Store these values in another array, which you then return. Alternatively, use a list comprehension. – wflynny Oct 02 '13 at 14:54

6 Answers6

8

You will achieve a better performance using numpy's sqrt and exp, which will operate elementwise:

import numpy as np
from numpy import sqrt, exp, pi
def h_scalar(x):
    x = np.array(x)
    return (1/sqrt(2*pi)) * exp(-0.50*x**2)

You can use it like:

x = [-10.0, -1.0, 0.0, 1.0, 10.0]
h_scalar(x)
Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
  • 1
    +1 this is the only solution so far that gains a proper performance advantage from vectorization – ali_m Oct 02 '13 at 16:53
  • 1
    To meet the requirements of the input being a list (or any iterable) you should insert `x=np.array(x, copy=False)` as the first line of the function `h_scalar`. – Dave Oct 03 '13 at 15:37
  • @Dave, thank you! I haven't paid enough attention to that requirement! In this case I think you cannot avoid the copy... – Saullo G. P. Castro Oct 03 '13 at 16:18
6

If you want to use numpy.vectorize this is one option:

>>> import numpy as np
>>> h_scalar = np.vectorize(lambda x: (1 / np.sqrt(2 * np.pi)) * np.exp( -.50** x ** 2.00 ))
>>> l = np.array([-10.0, -1.0, 0.0, 1.0, 10.0])
>>> h_scalar(l)
jabaldonedo
  • 25,822
  • 8
  • 77
  • 77
  • 4
    Bear in mind that `np.vectorize` doesn't really give any performance benefit over a plain list comprehension - you'll still end up looping in Python rather than C – ali_m Oct 02 '13 at 16:45
0

To perform an operation on all items in a list (or another iterable object), creating a new list from the return values of the operation, you can do something like this:

>>> l = [1,2,3,4,5]
>>> l2 = [ 2 * x for x in l ]
>>> print l2
[2, 4, 6, 8, 10]

The Python language feature used on the second line here is called a list comprehension, and it's very well suited to the homework task you've been given.

svk
  • 5,854
  • 17
  • 22
0

What you want is list comprehension.

Like this:

def h_scalar(sca):
    return [(1 / sqrt(2 * pi)) * exp(-.50** x ** 2.00) for x in sca]
Piotr Lopusiewicz
  • 2,514
  • 2
  • 27
  • 38
0

you are trying to use power on a list instead of a list item. I may have the exact function wrong here, but try something like this to take a list and return a list.

def h_scalar(x):
    return [(1/sqrt(2*pi))*exp(-.50 ** i ** 2.0) for i in x]

I'm not sure you have the right equation though, could you re-format it?

In [14]: h_scalar(l)                                              
Out[14]: 
[0.3989422804014327,                                              
 0.24197072451914337,                                             
 0.14676266317373993,                                             
 0.24197072451914337,                                             
 0.3989422804014327]
Garth5689
  • 622
  • 4
  • 15
  • Thank you, i didn't know i was doing that. I can now receive output, but it's not matching my teachers. My output is now "[0.3989422804014327, 0.24197072451914337, 0.14676266317373993, 0.24197072451914337, 0.3989422804014327]" whereas my instructor's is "[1.4867195147342977e-06, 0.24197072451914337, 0.3989422804014327, 0.24197072451914337, 1.4867195147342977e-06]" Am i calculating something wrong still? – user2839099 Oct 02 '13 at 15:08
  • [list comprehension](http://docs.python.org/2/tutorial/datastructures.html) like svk and Piotr pointed out is one way to go. Like I said, you'll want to double check your equation, but I can't tell from your formatting what you're trying to get. – Garth5689 Oct 02 '13 at 15:12
  • Does this look like your original equation: [link](http://latex.codecogs.com/gif.latex?h(x)=\frac{1}{\sqrt{2\pi}}e^{-\frac{1}{2}^{x^{2}}}) – Garth5689 Oct 02 '13 at 15:16
0

import numpy as np import math from math import *

def h_scalar(x): return (1 / sqrt(2 * pi)) * exp(-.50** x ** 2.00)

l = [-10.0, -1.0, 0.0, 1.0, 10.0]

h_scalar = np.vectorize(h_scalar) ## you are missing this line in your code

print h_scalar(l)

user3067175
  • 160
  • 1
  • 7