9.3 Avsluttende øvingseksamen 2 — mekanikk/nervecelle-innpakning med subklasse
Komplett avsluttende sett med et vanskeligere toppsjikt: ODESolver-subklasse med `scipy.optimize.root`, «finn feilen» og lister-vs-NumPy.
Dette settet er det andre av to avsluttende øvingssett, og det er bygd tyngre enn kap. 9.2 med vilje. Toppsjiktet her er de tre tingene som skiller mest på et reelt sett: en stykkvis funksjon som klasse, et ODE-system der høyresiden må bære parametere, og til slutt en ODESolver-subklasse med nullpunktsløser.
| Del | Oppgaver | Poeng | Andel | Tid |
|---|---|---|---|---|
| Flervalgsskall | 1–5 | 14 | 19 % | ~30 min |
| Kodeskriving | 6–14 | 61 | 81 % | ~210 min |
| Totalt | 14 + poengfelt | 75 | 100 % | 240 min |
Oppgave 15 skal ikke besvares. På hvert reelle sett er den siste «oppgaven» — nummerert 15, 16 eller 17, avhengig av året — bare feltet der sensor legger inn poengene dine fra midtveiseksamen, slik at de to eksamenene til sammen blir 100 poeng. Den er med her også, som påminnelse. Se helt nederst.
Tre sensorregler som gjelder hele settet:
1. Kort, idiomatisk kode. Ingen
main-program, ingen ekstra utskrift, ingen kommentarer for kommentarenes skyld.2. Rimelige antakelser er tillatt når oppgaveteksten er underspesifisert — men de skal dokumenteres i en kommentar.
3. Nødvendige import skal med når oppgaven ber om kjørbar kode.
Og den viktigste: delvis riktig kode gir uttelling. Riktig overordnet struktur — riktig løkke, riktig klasseoppsett, riktig ODE-oppsett — belønnes selv med feil i indekser eller detaljer. Deloppgaver kan løses uavhengig: du kan skrive testfunksjonen i oppgave 13 selv om klassen i oppgave 10 ikke ble ferdig.
Settet er nyskrevet av Skolesaga. Det er ikke et offisielt UiO-sett, og det forutsier ikke hva som kommer på din eksamen.
- kap. 1.3 og kap. 1.7 — nøstede løkker og løkketerminering (oppgave 1 og 3)
- kap. 2.2 — hvilken exception som utløses først (oppgave 4)
- kap. 4.1 og kap. 4.2 — lister mot NumPy, «med løkke / uten løkke» (oppgave 5 og 8)
- kap. 3.2 og kap. 3.3 — rekurrente rekker løst med løkke (oppgave 7)
- kap. 5.1, kap. 5.2 og kap. 5.4 — funksjonsklasse, __str__ og stykkvise funksjoner (oppgave 10)
- kap. 7.3 og kap. 7.5 — ODE-system med det utleverte hierarkiet (oppgave 11)
- kap. 6.1 og kap. 7.4 — nullpunktsløser og subklasse (oppgave 12)
Innpakningen i dette settet er medisin og fysiologi: en doseringsplan som stykkvis funksjon, en nervecelle som fyrer, og en rask enzymreaksjon som krever en implisitt metode.
Slik tar du settet
Sett av fire timer i ett stykke, og bruk minuttbudsjettet under som klokke. Skriv koden for hånd eller i en editor uten å kjøre den — i desember har du bare tekstfeltet i Inspera.
| Oppgave | Sjanger | Poeng | Tid |
|---|---|---|---|
| 1 | A — kodesporing, nøstede løkker | 3 | 6 min |
| 2 | A — kodesporing, klasse og ordbok | 3 | 6 min |
| 3 | D — terminerer løkken? | 3 | 7 min |
| 4 | C — exception-matche | 3 | 7 min |
| 5 | A og M — liste mot array | 2 | 4 min |
| Skall | 14 | 30 min | |
| 6 | O — finn feilen | 5 | 15 min |
| 7 | F — rekurrent rekke med testfunksjon | 6 | 22 min |
| 8 | M — med løkke / uten løkke | 5 | 18 min |
| 9 | A — skriv utskriften i fritekst | 4 | 12 min |
| 10 | G — stykkvis funksjon som klasse | 10 | 35 min |
| 11 | J — ODE-system med hierarkiet | 10 | 38 min |
| 12 | K — subklasse med nullpunktsløser | 8 | 30 min |
| 13 | F — testfunksjoner | 7 | 22 min |
| 14 | Tolkning og plott | 6 | 18 min |
| Kodedel | 61 | 210 min | |
| Sum | 75 | 240 min |
Disponering. Skallet er billige poeng: fem oppgaver, 14 poeng, en halvtime. Bruker du 45 minutter der, stjeler du fra oppgave 10, 11 og 12, som til sammen er verdt 28 poeng. Er du usikker på et flervalg, kryss av og gå videre — blankt og feil gir det samme, og fra 2024/2025 er negativ scoring fjernet.
Merk hvor du bør begynne i kodedelen. Oppgave 10 og 11 er de dyreste, og de bygger ikke på hverandre. Er du sterkere på klasser enn på ODE, ta 10 først. Oppgave 12 er den vanskeligste og skal tas sist — men skriv i det minste klasselinja og
def advance(self):, som gir poeng i seg selv.Etter oppgave 5 er det et naturlig pausepunkt. Tar du settet som lesetrening over flere kvelder, er skallet én økt, oppgave 6–9 en annen, og oppgave 10–14 en tredje.
Del 1 — flervalgsskallet
Oppgave 1–5 · 14 poeng · ~30 minutter.
Tre «select one» og to matche-tabeller. I matche-tabellene er hver rad 0,5 poeng og vurderes for seg.
Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
ord_liste = ['tre', 'is', 'sand']
sum_lengde = 0
for i in range(len(ord_liste)):
for j in range(i+1):
sum_lengde += len(ord_liste[j])
print(i, sum_lengde, end='; ')
print()a) 0 3; 1 8; 2 17;
b) 0 3; 1 5; 2 9;
c) 0 3; 1 8; 2 12;
d) 0 3; 1 8; 2 17;
Hva skriver programmet ut?
class Logg:
def __init__(self):
self.data = {}
def __call__(self, navn, verdi):
if navn not in self.data:
self.data[navn] = []
self.data[navn].append(verdi)
return len(self.data[navn])
logg = Logg()
print(logg('vest', 3), logg('aust', 5), logg('vest', 7))
print(logg.data)a) 1 2 3 og {'vest': [3, 7], 'aust': [5]}
b) 1 1 2 og {'vest': [7], 'aust': [5]}
c) 1 1 2 og {'vest': [3, 7], 'aust': [5]}
d) 3 5 7 og {'vest': [3, 7], 'aust': [5]}
Par hver løkke med utfallet. Alle variabler er satt rett før løkka.
| Rad | Løkke |
|---|---|
| 1 | n = 20 og while n != 1: n = n - 3 |
| 2 | n = 19 og while n != 1: n = n - 3 |
| 3 | x = 1.0 og while x > 0.01: x = x/2 |
| 4 | x = 5.0 og while x > 0.01: x = x - 0.5 |
| 5 | s = 0; k = 1 og while s < 10: s += 1/k; k += 1 |
| 6 | x = 0.5 og while x < 100: x = x*x |
Alternativer:
1. Terminerer etter 6 runder
2. Terminerer etter 7 runder
3. Terminerer etter 10 runder
4. Terminerer, men først etter mange tusen runder
5. Uendelig løkke
6. Terminerer aldri fordi verdien minker
Filen andel.py inneholder:
import sys
verdier = {'a': ['12', '4'], 'b': ['12', '0'], 'c': ['tolv', '4']}
nokkel = sys.argv[1]
par = verdier[nokkel]
x = int(par[0])
y = int(par[1])
print(100*x/y)Par hver kommandolinje med det som skjer.
| Rad | Kommandolinje |
|---|---|
| 1 | python andel.py a |
| 2 | python andel.py b |
| 3 | python andel.py c |
| 4 | python andel.py |
| 5 | python andel.py A |
| 6 | python andel.py a ekstra |
Alternativer:
1.
ValueError2.
IndexError3. Ingen feil — programmet skriver et tall
4.
KeyError5.
ZeroDivisionError6.
TypeErrorHva skriver programmet ut?
import numpy as np
a = [2, 4]
b = np.array([2, 4])
print(a + a)
print(b + b)
print(a * 2, b * 2)a) [4, 8], [4 8], [4, 8] [4 8]
b) [2, 4, 2, 4], [2 4 2 4], [2, 4, 2, 4] [2 4 2 4]
c) [4, 8], [4 8], [2, 4, 2, 4] [4 8]
d) [2, 4, 2, 4], [4 8], [2, 4, 2, 4] [4 8]
— naturlig pausepunkt —
Del 2 — kodeskriving
Oppgave 6–14 · 61 poeng · ~210 minutter.
Herfra er alt fritekst: du skriver kode i et tekstfelt. Skriv den ferdig uten å kjøre den, og skriv den kort. Deloppgavene kan løses uavhengig av hverandre.
Programmet skal lage en tabell over jevnt fordelte punkter fra start til stop, uten å bruke np.linspace. Det har tre feil.
import numpy as np
def tabell(start, stop, N):
x = np.zeros(N)
dx = (stop - start)/(N+1)
for i in range(N):
x[i] = start + i*dx
return xa) Nevn de tre feilene og si hva hver av dem fører til. (3 poeng)
b) Skriv den rettede koden og vis at tabell(0, 4, 4) gir de fem punktene 0, 1, 2, 3, 4. (2 poeng)
Laguerre-polynomene brukes i modeller for elektronets bane rundt en atomkjerne, og oppfyller
a) Skriv laguerre(n, x) med en løkke. (4 poeng)
b) Skriv en testfunksjon som sjekker mot de kjente formlene og for . (2 poeng)
En laboratoriemåling skal tabelleres for med 9 punkter i intervallet .
a) Skriv koden med løkke og lister. (2 poeng)
b) Skriv den samme tabellen vektorisert med NumPy, uten løkke. (2 poeng)
c) Vis at de to versjonene gir like mange punkter og samme siste verdi. (1 poeng)
Skriv nøyaktig hva programmet skriver ut, med mellomrom og desimaler slik terminalen viser det.
maalinger = {'N1': 4.25, 'N2': 11.5, 'N3': 0.75}
total = 0.0
for navn in maalinger:
total += maalinger[navn]
print(f'{navn:>5s}{maalinger[navn]:8.2f}{total:9.3f}')Et legemiddel doseres etter en plan som endrer seg over tid. Doseraten i milligram per time er
der er timer etter innleggelse.
a) (7 p) Skriv en klasse Doserate der __init__ tar en liste a med funksjonsverdiene og en liste b med grensene, og der __call__(self, t) returnerer riktig verdi. Klassen skal virke for et hvilket som helst antall nivåer, ikke bare fire.
b) (3 p) Utvid klassen med __str__ som gir en lesbar beskrivelse, lag instansen for planen over, og skriv ut doseraten ved , , , , , , og .
En nervecelle beskrives av membranpotensialet og en tilbakestillingsvariabel :
med , , og den ytre strømmen . Ved er og . Du har ODESolver-modulen med ForwardEuler og RungeKutta4 tilgjengelig.
a) (5 p) Skriv høyresiden som en klasse Nervecelle med __init__ som lagrer de fire parametrene og __call__(self, t, u) som returnerer de to deriverte. Forklar i én setning hvorfor parametrene ikke kan sendes som argumenter til høyresiden.
b) (3 p) Løs systemet fra til med 6000 skritt og RungeKutta4. Skriv ut formen på u og ytterverdiene for begge komponentene.
c) (2 p) Skriv plottekoden for begge kurvene mot tid, med forklaring, og beskriv figuren.
To former av et enzym veksler: den ene veien går svært raskt, den andre langsomt.
med og . Systemet er stivt, og en eksplisitt metode trenger urimelig små skritt.
a) (5 p) Skriv subklassen BaklengsEuler(ODESolver) med kun advance. Hvert skritt skal løse likningen med root fra scipy.optimize.
b) (2 p) Løs på med 30 skritt, og sammenlign med ForwardEuler på samme antall skritt.
c) (1 p) Regn ut likevekten for hånd og sjekk mot resultatet.
Denne oppgaven bruker Doserate fra oppgave 10 og laguerre fra oppgave 7. Du kan løse den selv om du ikke fikk dem til å virke: du vet hva de skal gjøre.
a) (4 p) Skriv test_doserate() som sjekker klassen i seks punkter, inkludert begge grensetilfellene og .
b) (3 p) Skriv test_laguerre_null() som utnytter at for alle , og sjekker det for .
a) (3 p) Bruk Doserate fra oppgave 10. Lag en tabell over doseraten for 121 punkter i timer, vektorisert der det er mulig, og skriv plottekoden. Beskriv figuren.
b) (2 p) Forklar hvorfor doseratefunksjonen ikke kan evalueres på et helt NumPy-array på én gang, slik np.sqrt kan.
c) (1 p) I oppgave 12 sprakk ForwardEuler mens BaklengsEuler ga et fornuftig svar. Var det en programmeringsfeil? Begrunn.
Oppgave 15 — skal ikke besvares
På det reelle settet står det til slutt en «oppgave» med et tomt svarfelt og en beskjed om at den ikke skal besvares. Nummeret varierer — 15, 16 eller 17, avhengig av hvor mange oppgaver settet har — men funksjonen er alltid den samme: det er feltet der sensor legger inn poengene dine fra midtveiseksamen.
Regnestykket er enkelt. Den avsluttende eksamenen gir maks 75 poeng, midtveiseksamen maks 25, og til sammen blir det 100. Ved å legge midtveispoengene inn i samme oppgavesett kan Inspera regne ut totalen automatisk.
Hva du skal gjøre med den: ingenting. La feltet stå tomt og gå videre.
Rett deg selv
| Oppgave | Sjanger | Riktig | Poeng |
|---|---|---|---|
| 1 | A | a | 3 |
| 2 | A | c | 3 |
| 3 | D | rad 1→5, 2→1, 3→2, 4→3, 5→4, 6→6 | 3 |
| 4 | C | rad 1→3, 2→5, 3→1, 4→2, 5→4, 6→3 | 3 |
| 5 | A og M | d | 2 |
| 6 | O | tre feil om punkter mot intervaller | 5 |
| 7 | F | rekurrent rekke med testfunksjon | 6 |
| 8 | M | to tabeller, samme antall punkter | 5 |
| 9 | A | tre linjer med riktige kolonner | 4 |
| 10 | G | stykkvis klasse med __call__ og __str__ | 10 |
| 11 | J | ODE-system med klasse som høyreside | 10 |
| 12 | K | subklasse med nullpunktsløser | 8 |
| 13 | F | to testfunksjoner | 7 |
| 14 | — | tolkning og plott | 6 |
| Sum | 75 |
Slik gir du deg selv poeng på kodeoppgavene. Gå gjennom «Dette gir uttelling»-listen i hver fasit og kryss av det du faktisk skrev. Regelen er mildere enn du tror: riktig struktur teller mest, og en indeksfeil i en ellers riktig løkke koster ett poeng, ikke hele oppgaven. Er du i tvil om noe er «riktig nok», er svaret nesten alltid ja — de offisielle løsningsforslagene i dette faget presenterer sin egen kode som ett eksempel på en besvarelse som ville fått full score, ikke som den eneste.
Selvdiagnose — kryss av:
- ☐ Skrev du utskriften tegn for tegn, med de avsluttende mellomrommene, i oppgave 1 og 9? (kap. 1.4)
- ☐ Sjekket du både retningen og om betingelsen kan bli usann i termineringsoppgaven? (kap. 1.3)
- ☐ Husket du at
sys.argv[0] er filnavnet? (kap. 2.1)- ☐ Holdt du liste-skjøting og array-addisjon fra hverandre? (kap. 4.1)
- ☐ Ga intervaller deg punkter i oppgave 6 og 8? (kap. 4.2)
- ☐ Brukte du løkkevariabelen — ikke funksjonsargumentet — i rekurrensens koeffisienter? (kap. 3.2)
- ☐ Sto
self både i metodesignaturene og foran attributtene? (kap. 5.1)- ☐ Returnerte
__str__ en streng i stedet for å skrive den ut? (kap. 5.2)- ☐ Hadde den stykkvise klassen en
return etter løkka, for verdier over siste grense? (kap. 5.4)- ☐ Skrev du
f(t, u) med tiden først, og solve((0, T), N)? (kap. 7.3)- ☐ Pakket du ut systemkomponentene med
u[:, k] og ikke u[k]? (kap. 7.3)- ☐ Sto
t[n+1] og ikke t[n] i den implisitte metoden? (kap. 7.4)- ☐ Brukte testfunksjonene
abs(expected - computed) < tol og ikke ==? (kap. 3.1)- ☐ Hadde hvert
plot-kall label=, og fulgte legend() etter? (kap. 4.3)- ☐ Lot du oppgave 15 stå tom?
Om karakteren. Ikke regn poengsummen om til en bokstav. Karakteren settes samlet av begge eksamenene, og C er en god og vanlig karakter i IN1900. Målet med dette settet er ikke å bevise noe, men å finne ut hvilke to eller tre mønstre du fortsatt må skrive ut i sin helhet noen ganger til.
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.
Skolesaga er en uavhengig læringsressurs og er ikke tilknyttet eller godkjent av Universitetet i Oslo. Dette er ikke offisielt studiemateriell. Les mer.