Scientific Computing (Python)
Chapter: 5.4 Scientific Computing (Python) Level: 1 — Recognition (MCQ / Matching / True-False with Justification) Time Limit: 20 minutes Total Marks: 30
Section A — Multiple Choice (1 mark each) [10 marks]
Q1. For a NumPy array a = np.zeros((3, 4)) of dtype float64, what are its strides?
- (a)
(4, 3) - (b)
(32, 8) - (c)
(8, 32) - (d)
(12, 4)
Q2. Which function creates an array of 5 evenly spaced points including both endpoints 0 and 1?
- (a)
np.arange(0, 1, 5) - (b)
np.linspace(0, 1, 5) - (c)
np.zeros(5) - (d)
np.random.rand(5)
Q3. Given a = np.array([10, 20, 30, 40]), what does a[a > 15] return?
- (a)
array([20, 30, 40]) - (b)
array([False, True, True, True]) - (c)
array([10]) - (d)
array([1, 2, 3])
Q4. Adding arrays of shapes (3, 1) and (1, 4) produces a result of shape:
- (a)
(3, 4) - (b)
(1, 1) - (c) error
- (d)
(4, 3)
Q5. Which SciPy function solves a linear system and generally uses more numerically stable LAPACK routines than the NumPy equivalent?
- (a)
numpy.dot - (b)
scipy.linalg.solve - (c)
scipy.integrate.quad - (d)
scipy.optimize.fsolve
Q6. scipy.integrate.quad(f, a, b) is used for:
- (a) solving ODEs
- (b) definite numerical integration of a 1-D function
- (c) matrix factorization
- (d) FFT
Q7. In the classical RK4 method, the update for one step uses a weighted average of slopes with weights:
- (a)
- (b)
- (c)
- (d)
Q8. Which sparse format is most efficient for row slicing and matrix–vector products?
- (a) CSC
- (b) CSR
- (c) COO
- (d) DIA
Q9. The composite trapezoidal rule on equal subintervals of width has an error term of order:
- (a)
- (b)
- (c)
- (d)
Q10. In Matplotlib's object-oriented architecture, the container that holds one set of axes, ticks, and plotted data is the:
- (a) Figure
- (b) Axes
- (c) Canvas
- (d) Backend
Section B — Matching (1 mark each) [10 marks]
Q11–Q15. Match each SciPy/library tool (left) to its purpose (right). Write the letter.
| # | Tool | Purpose | |
|---|---|---|---|
| Q11 | scipy.optimize.curve_fit |
A | Symbolic differentiation & ODE solving |
| Q12 | np.fft.fft |
B | Least-squares fitting of a model to data |
| Q13 | sympy.diff |
C | Fast (discrete) Fourier transform |
| Q14 | scipy.stats.ttest_ind |
D | LU / QR / Schur decompositions |
| Q15 | scipy.linalg.lu |
E | Two-sample hypothesis test |
Q16–Q20. Match each array/function (left) to what it produces (right). Write the letter.
| # | Expression | Result / Role | |
|---|---|---|---|
| Q16 | np.arange(0, 6, 2) |
A | matplotlib.animation.FuncAnimation |
| Q17 | np.linalg.eig(A) |
B | array([0, 2, 4]) |
| Q18 | Repeatedly redraw frames for a movie | C | eigenvalues and eigenvectors |
| Q19 | pandas.DataFrame.groupby |
D | image / heatmap from a 2-D array |
| Q20 | plt.imshow |
E | split-apply-combine aggregation |
Section C — True / False with one-line justification (2 marks each: 1 T/F + 1 justification) [10 marks]
Q21. Floating-point addition is associative, so (a + b) + c == a + (b + c) always holds exactly.
Q22. Vectorized NumPy operations are typically faster than equivalent pure-Python for loops because the loop runs in compiled C over contiguous memory.
Q23. Broadcasting requires both arrays to have identical shapes.
Q24. np.linalg.det of a singular matrix is exactly 0.0 in floating point.
Q25. The Newton–Raphson method requires the derivative and generally converges faster (quadratically) than bisection near a simple root.
Answer keyMark scheme & solutions
Section A
Q1 — (b) (32, 8). (1)
Row-major float64 (8 bytes). Moving one column = 8 bytes; one row = 4 columns × 8 = 32 bytes → strides (32, 8).
Q2 — (b) np.linspace(0, 1, 5). (1)
linspace includes both endpoints by default and takes a count, not a step. Gives [0, .25, .5, .75, 1].
Q3 — (a) array([20, 30, 40]). (1)
Boolean mask a>15 = [F,T,T,T]; indexing selects the True elements.
Q4 — (a) (3, 4). (1)
Broadcasting stretches each size-1 dimension: (3,1) and (1,4) → (3,4).
Q5 — (b) scipy.linalg.solve. (1)
scipy.linalg wraps LAPACK and is generally preferred for stability over numpy.linalg.
Q6 — (b) definite numerical integration of a 1-D function. (1)
quad performs adaptive Gaussian quadrature.
Q7 — (b) . (1) Classical RK4: .
Q8 — (b) CSR. (1) Compressed Sparse Row is optimized for row access and fast SpMV.
Q9 — (b) . (1) Composite trapezoidal global error is .
Q10 — (b) Axes. (1) A Figure can hold multiple Axes; the Axes holds the actual plot region, ticks, and data.
Section B
Q11 → B (curve_fit = least-squares model fitting). (1) Q12 → C (fft = fast Fourier transform). (1) Q13 → A (sympy.diff = symbolic calculus). (1) Q14 → E (ttest_ind = two-sample hypothesis test). (1) Q15 → D (lu = LU decomposition). (1)
Q16 → B (np.arange(0,6,2) = [0,2,4]). (1)
Q17 → C (eig returns eigenvalues & eigenvectors). (1)
Q18 → A (FuncAnimation redraws frames). (1)
Q19 → E (groupby = split-apply-combine). (1)
Q20 → D (imshow = image/heatmap of 2-D array). (1)
Section C
Q21 — FALSE. (1) Justification (1): Rounding at each step means association order changes the result; classic example (0.1+0.2)+0.3 ≠ 0.1+(0.2+0.3) in double precision.
Q22 — TRUE. (1) Justification (1): The inner loop executes in optimized C on contiguous memory, avoiding per-element Python object overhead.
Q23 — FALSE. (1) Justification (1): Broadcasting only needs compatible dimensions (equal or one of them 1); shapes need not be identical.
Q24 — FALSE. (1) Justification (1): Floating-point rounding usually yields a tiny nonzero determinant (e.g. 1e-16), not exact 0; check via condition number/rank instead.
Q25 — TRUE. (1) Justification (1): Newton uses ; near a simple root it converges quadratically, faster than bisection's linear (halving) rate.
[
{"claim":"Q1 strides for float64 (3,4) C-order are (32,8)","code":"import numpy as _np; a=_np.zeros((3,4),dtype='float64'); result = a.strides==(32,8)"},
{"claim":"Q3 boolean mask returns [20,30,40]","code":"import numpy as _np; a=_np.array([10,20,30,40]); result = list(a[a>15])==[20,30,40]"},
{"claim":"Q4 broadcasting (3,1)+(1,4) -> (3,4)","code":"import numpy as _np; r=_np.ones((3,1))+_np.ones((1,4)); result = r.shape==(3,4)"},
{"claim":"Q16 np.arange(0,6,2) equals [0,2,4]","code":"import numpy as _np; result = list(_np.arange(0,6,2))==[0,2,4]"},
{"claim":"Q21 float addition not associative for 0.1,0.2,0.3","code":"result = ((0.1+0.2)+0.3 != 0.1+(0.2+0.3))"}
]