Kolokwium I - poprawa

Zadanie 1 (5 pkt)

Napisz iterator

def wystapienia(tekst,baza):
który wypisze wszystkie wystapienia słów z kolekcji (np. listy) baza w napisie tekst.

Wystąpienia powinny być wypisane jako tuple: (wystąpienie, indeks początku w tekst).

Uwaga: Wielkość liter nie powinna mieć znaczenia (Wskazówka: str.[TAB] w ipython).

In [2]:
#u'napis' koduje napis w unicode, który zachowuje się bardzo podobnie do str
list(wystapienia(u'Ale To Już byŁo',[u'aLe',u'był',u'o']))
Out[2]:
[(u'aLe', 0), (u'o', 5), (u'by\u0142', 11), (u'o', 14)]
In [1]:
def wystapienia(tekst,baza):
    for i in range(len(tekst)):
        for b in baza:
            if tekst[i:i+len(b)].lower()==b.lower():
                yield (b,i)
            

Zadanie 2 (6+1 pkt)

Całkowanie numeryczne metodą trapezu w $N-1$ punktach na przedziale $[a,b]$ wyraża się wzorem:

$$ \int_{a}^{b} f(x) dx \approx \frac{1}{2} \sum_{k=0}^{N-2} \left( x_{k+1} - x_{k} \right) \left( f(x_{k+1}) + f(x_{k}) \right). $$


Napisz funkcję

def calka(f,a,b,N):
która wykona takie całkowanie. Można założyć, że $a \lt b$.

Twoja funkcja powinna:

  1. Utworzyć wektor $\\{x_k\\}$ składający się z $N$ równo odległych punktów pomiędzy $[a,b]$ włącznie (Wsk.: np.linspace)
  2. Utworzyć wektor $\\{f(x_k)\\}$
  3. Wykonać całkowanie metodą trapezu

Napisz 2 wersje tej funkcji:

  1. $\textrm{def calka}$ "zwykła", działającą na listach i dowolnym $f$
  2. $\textrm{def calka_numpy}$ wykonującą operacje wektorowo przy założeniu, że $f$ jest funkcją wektorową
In [10]:
def fun(x):
    return (x-3)*(x-5)*(x-7)+85

#Uzyskane wyniki mogą różnić się nieznacznie w zależnośći od implementacji
print calka(fun,1,5,10)
print calka_numpy(fun,1,5,50)
307.209876543
307.97334444

Dodatkowy 1 punkt: porównaj(wypisz) absolutną rożnicę wyników $calka$ oraz całkowania funkcją scipy.integrate.quad dla $N \in 5,10,15,20,25$

In [6]:
from scipy.integrate import quad
Ns = (5,10,15,20,25) 
In [7]:
def calka(f,a,b,N):
    x = linspace(a, b, N)
    y = [f(xi) for xi in x]
    s = 0
    for k in range(len(x)-1):
        s+=(x[k+1]-x[k])*(y[k+1]+y[k])
    return s/2
In [8]:
def calka_numpy(f,a,b,N):
    x = linspace(a, b, N)
    y = f(x)
    return np.sum((x[1:]-x[:-1])*(y[1:]+y[:-1]))/2
In [9]:
from scipy.integrate import quad
a,b = 1,5
abs(np.array([calka(fun,a,b,N) for N in Ns])-quad(fun,a,b)[0])
Out[9]:
array([ 4.        ,  0.79012346,  0.32653061,  0.17728532,  0.11111111])
In [11]:
#Dodatkowy kod z obrazkiem, to nie jest część rozwiązania
from pylab import *
a, b = 1, 5
x = linspace(0,10,1000)
y = fun(x)
xint = numpy.append(x[logical_and(x>=a, x<=b)][::150],b)
yint =  numpy.append(y[logical_and(x>=a, x<=b)][::150],fun(b))

plot(x, y, lw=2)
axis([0, 8, 0, 140])
fill_between(xint, 0, yint, facecolor='gray', alpha=0.4)
text(0.5 * (a + b), 30,r"$\int_a^b f(x)dx$", horizontalalignment='center', fontsize=20);

Zadanie 3 (6 pkt)

Napisz funkcję

 def podzielne_stat(nlst,dzielniki):
która dla listy liczb naturalnych nlst oraz listy naturalnych dzielników dzielniki wypisze:

  1. procent liczb z nlst podzielnych przez $d$ dla każdego $d \in \textrm{dzielniki}$
  2. maksymalną resztę z dzielenia przez $d$ dla każdego $d \in \textrm{dzielniki}$
    (reszta = n%d)

W rozwiązaniu użyj słownika(ów) dict, lub collections.Counter.

In [2]:
podzielne_stat([5,8,10,15],[2,3,5])
Procent podzielnych: {2: 50, 3: 25, 5: 75}
Maks. reszta: {2: 1, 3: 2, 5: 3}
In [1]:
def podzielne_stat(nlst,dzielniki):
    ile=dict()
    maxr=dict()
    for d in dzielniki: 
        ile[d]=0
        maxr[d]=0
    for n in nlst:
        for d in dzielniki:
            r=n%d
            if r==0: ile[d]+=1
            if r>maxr[d]: maxr[d]=r
    for d in ile.keys():
        ile[d]=ile[d]*100/len(nlst)
    print 'Procent podzielnych:',ile
    print 'Maks. reszta:',maxr

Zadanie 4 (7 pkt)

a) Napisz defincję klasy Zdarzenia

class Zdarzenia(object):
która ma następujący interfejs:

  • __init__(self, \wagi)
    Konstruktor, który przyjmuje dowolną liczbę argumentów będących wagami
    (liczby rzeczywiste - patrz przykład), następnie
    1. odrzuca wszystkie wagi $w_i<=0$
    2. zapamiętuje wewnątrz klasy ciąg $p_i = \frac{w_i}{\sum w_i}$ jako wektor
    np.array* (jest to ciąg prawdopodobieństw sumujących się do 1)

  • prob
    property zwracające wektor prawdopodobieństw $p_i$

  • entropia(self)
    zwraca entropię policzoną ze wzoru ($H$ to entropia):
    $ H = -\sum^N_{i=1}p_i \log(p_i)$
    Użyj funkcji np.sum i np.log (logarytm naturalny)

In [3]:
import numpy as np
from numpy import sum, log, log2

b) Napisz podklasę Zdarzenia_lg2 , która do liczenia entropii używa logarytmu o podstawie 2 (np.log2)

Przykład:

In [5]:
zd=Zdarzenia(1.,3.,11.,4.,-1.)
print "Prob1 =",zd.prob
print "H1 =",   zd.entropia()

zd2=Zdarzenia_lg2(1.,3.,11.,4.,-1.)
print "Prob2 =",zd2.prob
print "H2 =",   zd2.entropia()
Prob1 = [ 0.05263158  0.15789474  0.57894737  0.21052632]
H1 = 1.09086727857
Prob2 = [ 0.05263158  0.15789474  0.57894737  0.21052632]
H2 = 1.57378881307
In [4]:
import numpy as np
from numpy import sum, log, log2

class Zdarzenia(object):
    def __init__(self,*wagi):
        wagi = [w for w in wagi if w>0]
        sw = sum(wagi)
        self._p = np.array([float(w)/sw for w in wagi])
    
    @property
    def prob(self):
        return self._p
        
    def entropia(self):
        return -sum(self._p*log(self._p))
    
class Zdarzenia_lg2(Zdarzenia):
    def entropia(self):
        return -sum(self._p*log2(self._p))

Zadanie 5 (4 pkt)

Przeanalizuj przykładowy kod poniżej, oraz wynikowy wykres.

In [1]:
"""
Compute the coherence of two signals
"""
import numpy as np
import matplotlib.pyplot as plt

# make a little extra space between the subplots
plt.subplots_adjust(wspace=0.5)

dt = 0.01
t = np.arange(0, 30, dt)
nse1 = np.random.randn(len(t))                 # white noise 1
nse2 = np.random.randn(len(t))                 # white noise 2
r = np.exp(-t/0.05)

cnse1 = np.convolve(nse1, r, mode='same')*dt   # colored noise 1
cnse2 = np.convolve(nse2, r, mode='same')*dt   # colored noise 2

# two signals with a coherent part and a random part
s1 = 0.01*np.sin(2*np.pi*10*t) + cnse1
s2 = 0.01*np.sin(2*np.pi*10*t) + cnse2

plt.figure(figsize=(8,6),facecolor='w')
plt.subplot(211)
plt.plot(t, s1, 'b-', t, s2, 'g-')
plt.xlim(0,5)
plt.xlabel('time')
plt.ylabel('s1 and s2')
plt.grid(True)

plt.subplot(212)
cxy, f = plt.cohere(s1, s2, 256, 1./dt)
plt.ylabel('coherence')
plt.show()

Napisz funkcję

def coherence3(s1,s2,s3):
która wykona wykres, taki jak poniżej.

  • Na pierwszym wykresie powinny znaleźć się wszystkie 3 sygnały,
  • na drugim wykresie powinna być koherencja sygnałów s1,s2
  • na trzecim wykresie powinna być koherencja sygnałów s2,s3
In [3]:
#s1, s2 wzięte z przykładu powyżej
coherence3(s1,s2,s1+s2)
In [2]:
def coherence3(s1,s2,s3):
    # make a little extra space between the subplots
    plt.figure(figsize=(10,8),facecolor='w') 
    plt.subplots_adjust(wspace=0.5)
    plt.subplot(311)
    plt.plot(t, s1, 'b-', t, s2, 'g-',t, s3, 'r-')
    plt.xlim(0,5)
    plt.xlabel('time')
    plt.ylabel('s1 and s2 and s3')
    plt.grid(True)

    plt.subplot(312)
    cxy, f = plt.cohere(s1, s2, 256, 1./dt)
    plt.ylabel('coherence')
    
    plt.subplot(313)
    cxy, f = plt.cohere(s2, s3, 256, 1./dt)
    plt.ylabel('coherence')
       
    plt.show()
       
In [ ]: