NumPy broadcasting aligns trailing dimensions, allowing compatible size-one axes to expand without copying the input for each result position.
Python NumPy shape validation: reject accidental broadcasting before arithmetic
Operation contract
The demand matrix has one row per warehouse and one column per product. The price contract requires exactly one price for each product, represented as a one-dimensional vector. A shape of two by one could broadcast per warehouse and still produce a result, so compatibility alone is insufficient. The boundary converts to float64, caps matrix dimensions at eight, rejects nonfinite inputs and checks the price shape before multiplication. It returns one cost total per warehouse.
Failure and ownership boundary
The requested domain shape is stricter than NumPy’s broadcasting rules. Conversion can allocate before the post-conversion size gate; this is a trusted local input fixture, not a serialized-array reception boundary. float64 costs are approximate and are not an exact currency ledger. NumPy broadcasting: declare axes and bound integer arithmetic, NumPy slices and indexed copies: verify who owns the buffer and Python Decimal money: parse decimal text and choose rounding explicitly cover the adjacent decisions.
Tested environment
Dependency check: this program was executed on CPython 3.14.6 with numpy==2.5.3. Install these versions in a separate virtual environment. The download includes the recorded environment snapshot; no third-party package is part of the website runtime.
Working program
import numpy as np
def warehouse_costs(demand, prices):
matrix = np.asarray(demand, dtype=np.float64)
vector = np.asarray(prices, dtype=np.float64)
if matrix.ndim != 2 or any(not 1 <= size <= 8 for size in matrix.shape) or vector.shape != (matrix.shape[1],):
raise ValueError("warehouse/product shape")
if not np.isfinite(matrix).all() or not np.isfinite(vector).all() or (matrix < 0).any() or (vector < 0).any():
raise ValueError("finite nonnegative values")
return (matrix * vector).sum(axis=1)
print("totals:", warehouse_costs([[2, 1], [1, 3]], [1.5, 2.0]).tolist())
try:
warehouse_costs([[2, 1], [1, 3]], [[1.5], [2.0]])
except ValueError:
print("broadcastable wrong shape rejected")Output
totals: [5.0, 7.5]
broadcastable wrong shape rejectedCosts and limits
For R warehouses and C products, multiplication and reduction take O(R times C) arithmetic and the intermediate product matrix retains O(R times C) floats. Broadcasting does not eliminate that result allocation. These fixtures have small nonoverflowing values; the boundary does not cap arbitrary finite magnitudes or guarantee finite outputs for every finite input.
Common Mistakes
- A broadcastable array can still represent the wrong domain axis.
- Broadcasting avoids repeated input copies, not every result allocation.
Connected lessons
NumPy broadcasting: declare axes and bound integer arithmetic, NumPy slices and indexed copies: verify who owns the buffer, NumPy floating-point checks: finite values and declared tolerances.
