MATLAB Code Standards
MATLAB Code Standards
Standard: Senior Principal Computational Scientist + PhD researcher quality
1. Reproducibility
rng()called ONCE at top if stochastic operations are present (never inside loops/functions)- All paths relative to the script working directory (usually
code/[task_group]/) - Path construction uses
fileseporfullfile()for cross-platform compatibility - No hardcoded absolute paths (e.g.,
/Users/...,C:\Users\...) - Rely on the Makefile to make directories (when Makefiles exist)
2. Function Design
- Consistent naming convention (
snake_casematching existing codebase) - Comment-block docstring immediately after function signature:
function [obj, grad, H] = objective_fn(x, data, Params) % OBJECTIVE_FN Compute objective, gradient, and Hessian. % % [obj, grad, H] = objective_fn(x, data, Params) % % Inputs: % x - Parameter vector (N x 1) % data - Structure with fields: ... % Params - Configuration structure with fields: ... % % Outputs: % obj - Scalar objective value % grad - Gradient vector (N x 1) % H - Hessian matrix (N x N) - Use
Paramsstruct for configuration and tuning values (no magic numbers) - Input validation via
assert()for critical dimensions
3. Domain Correctness
- Verify objective function implementations match paper formulas (
latex/manuscript.tex) - Check known package/solver bugs (document below in Common Pitfalls)
4. Solver Configuration
Projects using optimization should follow a dual-solver pattern (e.g., KNITRO + fmincon) controlled by a configuration flag. Key requirements:
- Option file paths constructed with
fileseporfullfile() - Hessian callback matches the wrapper signature
- Both solver paths should produce consistent results
- Always check
exitflagafter solver call
5. Output Paths
Task-group scripts usually run from code/[task_group]/, so paths are
relative to that working directory. In the standard layout, define
output_root once and write into the main subdirectories under the repo-root
output/ directory:
output_root = fullfile("..", "..", "output");
writetable(results, fullfile(output_root, "tables", "results.csv"));
writematrix(data, fullfile(output_root, "tables", "output.csv"));
save(fullfile(output_root, "tables", "results.mat"), "results", "params");
Projects with a Params struct may wrap these paths (e.g., Params.outputdir
instead of output_root), but the main subdirectories (tables/,
figures/, numbers/) remain the same.
6. Common Pitfalls
| Pitfall | Impact | Prevention |
|---|---|---|
| Hardcoded absolute paths | Breaks on other machines | Use relative paths with filesep |
Unchecked solver exitflag |
Silent convergence failure (Critical, -20) | Always check exitflag > 0 |
| Missing NaN/Inf guards | Solver crashes or wrong results | Check before and after optimization |
| Inconsistent index trimming | Wrong data alignment | Trim all parallel arrays identically |
i/j as loop variables |
Shadows complex unit | Use ii, jj, kk or descriptive names |
| Asymmetric Hessian | Silently wrong results (Critical, -25) | Symmetrize: H = (H + H') / 2 |
| Missing semicolons | Unwanted console output | End assignment lines with ; |
7. Line Length
Standard: Keep lines <= 120 characters. Mathematical formulas may exceed 120 chars if breaking the line would harm readability, an inline comment explains the operation, and the line is in a numerically intensive section.
8. Code Quality Checklist
[ ] rng() once at top (if stochastic)
[ ] Clean header block with purpose, inputs, outputs, and assumptions
[ ] All paths relative with filesep/fullfile() from the script working directory
[ ] Functions documented (comment-block docstrings)
[ ] One operation per line; long calls split by argument where readable
[ ] Descriptive snake_case names matching the existing codebase
[ ] Solver exitflag checked after every optimization call
[ ] NaN/Inf guards on data input and solver output
[ ] Hessian symmetry verified
[ ] Output files saved (writetable/writematrix/save)
[ ] Comments explain WHY not WHAT
[ ] No magic numbers (use Params struct)
[ ] Semicolons on all assignment lines