mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-07-18 00:44:29 -05:00
2277 lines
91 KiB
TeX
2277 lines
91 KiB
TeX
% =============================================================================
|
|
% LATEX HEADER CONFIGURATION FOR MLSYSBOOK PDF
|
|
% =============================================================================
|
|
% This file contains all LaTeX package imports, custom commands, and styling
|
|
% definitions for the PDF output of the Machine Learning Systems textbook.
|
|
%
|
|
% Key Features:
|
|
% - Harvard crimson branding throughout
|
|
% - Custom part/chapter/section styling
|
|
% - Professional table formatting with colored headers
|
|
% - Margin notes with custom styling
|
|
% - TikZ-based part dividers
|
|
% - Page numbering (Roman for frontmatter, Arabic for mainmatter)
|
|
%
|
|
% Note: This file is included via _quarto-pdf.yml and affects PDF output only.
|
|
% HTML/EPUB styling is handled separately via CSS files.
|
|
% =============================================================================
|
|
|
|
% =============================================================================
|
|
% PACKAGE IMPORTS
|
|
% =============================================================================
|
|
|
|
\PassOptionsToPackage{hyphens}{url} % Add URL breakpoints before hyperref loads url
|
|
|
|
% Layout and positioning
|
|
% \usepackage[outercaption, ragged]{sidecap} % Commented out to make figure captions inline instead of in margin
|
|
\usepackage{adjustbox} % Adjusting box dimensions
|
|
\usepackage{afterpage} % Execute commands after page break
|
|
\usepackage{morefloats} % Increase number of floats
|
|
\usepackage{array} % Enhanced table column formatting
|
|
\usepackage{makecell} % Line breaks in table cells (\makecell)
|
|
\usepackage{atbegshi} % Insert content at page beginning
|
|
%\usepackage{changepage} % Change page dimensions mid-document
|
|
\usepackage{emptypage} % Clear headers/footers on empty pages
|
|
|
|
% Language and text
|
|
\usepackage[english]{babel} % English language support
|
|
\usepackage{microtype} % Improved typography and hyphenation
|
|
|
|
% Captions and floats
|
|
\usepackage{caption}
|
|
% Caption styling configuration
|
|
%\captionsetup[table]{belowskip=5pt}
|
|
\captionsetup{format=plain}
|
|
\DeclareCaptionLabelFormat{mylabel}{#1
|
|
#2:\hspace{1.0ex}}
|
|
\DeclareCaptionFont{ninept}{\fontsize{7pt}{8}\selectfont #1}
|
|
|
|
% Figure captions: Small font, bold label, ragged right
|
|
\captionsetup[figure]{labelfont={bf,ninept},labelsep=space,
|
|
belowskip=2pt,aboveskip=6pt,labelformat=mylabel,
|
|
justification=raggedright,singlelinecheck=false,font={ninept}}
|
|
|
|
% Table captions: Small font, bold label, ragged right
|
|
\captionsetup[table]{aboveskip=0pt,belowskip=6pt,labelfont={bf,ninept},labelsep=none,
|
|
labelformat=mylabel,justification=raggedright,singlelinecheck=false,font={ninept}}
|
|
|
|
|
|
|
|
% Typography fine-tuning
|
|
\emergencystretch=5pt % Allow extra stretch to avoid overfull boxes
|
|
|
|
% Utility packages
|
|
\usepackage{etoolbox} % For patching commands and environments
|
|
|
|
% Algorithm pseudocode (algpseudocodex): in the narrow text column, forbid
|
|
% mid-word hyphenation so algorithm steps wrap at spaces, not inside words.
|
|
% Deferred to begin-document and guarded so it applies only when a chapter
|
|
% actually loads the pseudocode package.
|
|
\AtBeginDocument{%
|
|
\ifdef{\algorithmic}{%
|
|
\AtBeginEnvironment{algorithmic}{\hyphenpenalty=10000\exhyphenpenalty=10000\tolerance=3000\emergencystretch=2.5em}%
|
|
}{}%
|
|
}
|
|
|
|
% Page layout and headers
|
|
\usepackage{fancyhdr} % Custom headers and footers
|
|
\usepackage{geometry} % Page dimensions and margins
|
|
|
|
% Graphics and figures
|
|
\usepackage{graphicx} % Include graphics
|
|
\usepackage{float} % Improved float placement
|
|
\usepackage[skins,breakable]{tcolorbox} % Coloured and framed text boxes
|
|
\tcbset{before upper=\setlength{\parskip}{2pt}}
|
|
|
|
% Tables
|
|
\usepackage{longtable} % Multi-page tables
|
|
|
|
% Fonts and typography
|
|
\usepackage{fontspec} % Font selection for LuaLaTeX
|
|
\usepackage{mathptmx} % Times-like math fonts
|
|
\usepackage{newpxtext} % Palatino-like font for body text
|
|
\usepackage[scaled=0.92]{helvet} % Helvetica for sans-serif (sidenotes, captions, TikZ labels); scaled to match Palatino x-height
|
|
\IfFontExistsTF{Vatico}{%
|
|
\newfontfamily\mlsysFigureSans{Vatico}%
|
|
}{%
|
|
\newcommand{\mlsysFigureSans}{\usefont{T1}{phv}{m}{n}}%
|
|
}
|
|
|
|
% Colors and visual elements
|
|
\usepackage[dvipsnames]{xcolor} % Extended color support
|
|
\usepackage{tikz} % Programmatic graphics
|
|
\usepackage{pgfplots} % Axis plots in TikZ (e.g. fault_tolerance bathtub curve)
|
|
\pgfplotsset{compat=1.18}
|
|
\usetikzlibrary{angles}
|
|
\usetikzlibrary{arrows.meta}
|
|
\usetikzlibrary{arrows}
|
|
\usetikzlibrary{backgrounds}
|
|
\usetikzlibrary{bending}
|
|
\usetikzlibrary{calc}
|
|
\usetikzlibrary{chains}
|
|
\usetikzlibrary{shadows.blur}
|
|
\usetikzlibrary{fit}
|
|
\usetikzlibrary{intersections}
|
|
\usetikzlibrary{positioning}
|
|
\usetikzlibrary{shapes.arrows}
|
|
\usetikzlibrary{shapes.geometric}
|
|
\usetikzlibrary{shapes}
|
|
\usetikzlibrary{quotes}
|
|
\usetikzlibrary{decorations.pathmorphing}
|
|
\usetikzlibrary{decorations.markings}
|
|
\usetikzlibrary{decorations.pathreplacing}
|
|
\usetikzlibrary{matrix}
|
|
\usetikzlibrary{patterns}
|
|
\usepackage{tikzpagenodes} % TikZ positioning relative to page
|
|
|
|
% Code listings
|
|
\usepackage{listings} % Code highlighting
|
|
|
|
% Hyperlinks
|
|
\usepackage{hyperref} % Clickable links in PDF
|
|
\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % More URL breakpoints in long references
|
|
\urlstyle{same}
|
|
|
|
% Textbook PDFs should not make citations visually read like web links.
|
|
% Pandoc/Quarto may emit its own \hypersetup later in the preamble, so defer
|
|
% this override until the document begins.
|
|
\AtBeginDocument{%
|
|
\hypersetup{citecolor=black}%
|
|
}
|
|
|
|
% Conditional logic
|
|
\usepackage{ifthen} % If-then-else commands
|
|
|
|
% Math symbols
|
|
\usepackage{amsmath} % AMS math extensions
|
|
\usepackage{amssymb} % AMS math symbols
|
|
\usepackage{latexsym} % Additional LaTeX symbols
|
|
\usepackage{pifont} % Zapf Dingbats symbols
|
|
\providecommand{\blacklozenge}{\ding{117}} % Black diamond symbol
|
|
|
|
% Lists
|
|
\usepackage{enumitem} % Customizable lists
|
|
\usepackage{multicol} % Multi-column layouts (used for glossary)
|
|
|
|
% Margin notes and sidenotes
|
|
\usepackage{ifoddpage} % Detect recto/verso for margin-side placement
|
|
\usepackage{marginfix} % Fixes margin note overflow
|
|
\usepackage{marginnote} % Margin notes
|
|
\usepackage{sidenotes} % Academic-style sidenotes
|
|
\renewcommand\raggedrightmarginnote{\sloppy}
|
|
\renewcommand\raggedleftmarginnote{\sloppy}
|
|
|
|
% --- Auto-keep margin figures on the page (margin-overflow fix) --------------
|
|
% Quarto emits every ::: {.column-margin} block as \marginnote{...}. The
|
|
% marginnote package places content at a FIXED vertical position and is NOT
|
|
% managed by marginfix (which only governs \marginpar). A tall margin figure
|
|
% anchored low on the page therefore runs straight off the bottom past the
|
|
% footer. Rerouting \marginnote through \marginpar hands it to marginfix,
|
|
% which floats it UP to stay within the column, exactly as it already does for
|
|
% the \sidenote marginpars.
|
|
% The body of a margin figure can contain blank lines (\par), so the wrapper
|
|
% uses xparse's +m argument. It must also consume marginnote's trailing
|
|
% optional vertical offset because the sidenotes package emits
|
|
% \marginnote{...}[<offset>] for adjusted sidenotes; failing to consume that
|
|
% argument leaves literal "[-20mm]" text in the rendered PDF.
|
|
% \marginpar is marginfix-managed (floats to stay on the page) but is ILLEGAL
|
|
% in inner mode (inside a callout/tcolorbox, float, minipage, or box) where it
|
|
% raises "Not in outer par mode". \marginnote works everywhere but is
|
|
% unmanaged. So we route to \marginpar only in outer par mode and fall back to
|
|
% the original \marginnote inside boxes. \ifinner is true inside tcolorbox
|
|
% content / boxes / restricted modes, which is exactly where \marginpar fails.
|
|
\makeatletter
|
|
\let\mfxOrigMarginnote\marginnote
|
|
% \normalcolor resets the color inside the \marginpar: marginpar content is
|
|
% typeset in the output routine, so one shipped out next to a crimson heading
|
|
% would otherwise inherit that crimson (the original \marginnote typeset at the
|
|
% definition point, always black). This is why some margin captions went red.
|
|
\ExplSyntaxOn
|
|
\RenewDocumentCommand{\marginnote}{ O{} +m O{\z@} }{%
|
|
\tl_if_in:nnTF {#2} { \chapterminitoc }
|
|
{%
|
|
% Chapter mini-TOCs rely on etoc's current chapter context. Keep them
|
|
% as immediate marginnote content; routing through marginpar makes the
|
|
% first opener collect later chapters and leaves later openers empty.
|
|
\mfxOrigMarginnote[#1]{#2}[#3]%
|
|
}{%
|
|
\ifinner
|
|
\mfxOrigMarginnote[#1]{#2}[#3]%
|
|
\else
|
|
\marginpar{\normalcolor\vspace*{#3}#2}%
|
|
\fi
|
|
}%
|
|
}
|
|
\ExplSyntaxOff
|
|
\makeatother
|
|
|
|
% Safety fallback: ensure \sidenote is defined even if sidenotes package fails
|
|
% This allows graceful degradation to footnotes
|
|
\providecommand{\sidenote}[1]{\footnote{#1}}
|
|
|
|
% Typography improvements
|
|
\usepackage{ragged2e} % Better ragged text
|
|
\usepackage[all]{nowidow} % Prevent widows and orphans
|
|
\usepackage{needspace} % Ensure minimum space on page
|
|
|
|
% Section formatting
|
|
\usepackage[explicit]{titlesec} % Custom section titles
|
|
\usepackage{tocloft} % Table of contents formatting
|
|
\usepackage{etoc} % Local (chapter-level) table of contents
|
|
|
|
% QR codes and icons
|
|
\usepackage{fontawesome5} % Font Awesome icons
|
|
\usepackage{qrcode} % QR code generation
|
|
\qrset{link, height=15mm}
|
|
|
|
% =============================================================================
|
|
% FLOAT CONFIGURATION
|
|
% =============================================================================
|
|
% Allow more floats per page to handle figure-heavy chapters
|
|
% Note: 1000 is needed for copyedit builds with double-spacing
|
|
\extrafloats{1000}
|
|
\setcounter{topnumber}{12} % Max floats at top of page
|
|
\setcounter{bottomnumber}{12} % Max floats at bottom of page
|
|
\setcounter{totalnumber}{24} % Max floats per page
|
|
\setcounter{dbltopnumber}{8} % Max floats at top of two-column page
|
|
\renewcommand{\topfraction}{.95} % Max fraction of page for top floats
|
|
\renewcommand{\bottomfraction}{.95}
|
|
\renewcommand{\textfraction}{.05} % Min fraction of page for text
|
|
\renewcommand{\floatpagefraction}{.7} % Min fraction of float page
|
|
\renewcommand{\dbltopfraction}{.95}
|
|
|
|
% Prevent "Float(s) lost" errors by flushing floats more aggressively
|
|
\usepackage{placeins} % Provides \FloatBarrier
|
|
|
|
% =============================================================================
|
|
% COLOR DEFINITIONS
|
|
% =============================================================================
|
|
% NOTE: TikZ colors (BlueLine, GreenLine, RedLine, OrangeLine, etc.) are defined
|
|
% in the YAML config files under format > pdf > tikz > include-headers.
|
|
% Only colors specific to LaTeX packages (not TikZ) are defined here.
|
|
|
|
% Primary accent color - defined by theme-colors-volX.tex
|
|
% Fallback to Harvard crimson if theme file not loaded
|
|
\providecolor{accentcolor}{HTML}{A51C30}
|
|
% Alias for backwards compatibility
|
|
\colorlet{crimson}{accentcolor}
|
|
% Per-volume TOC link color (overridden by theme-colors-volX.tex);
|
|
% defaults to black so a missing theme file still produces a sane TOC.
|
|
\providecolor{toccolor}{HTML}{000000}
|
|
|
|
% Fleet Stack color aliases
|
|
% Keep the Volume 2 stack as one visual system: hue identifies the volume;
|
|
% intensity identifies chapter relevance. Part structure is carried by the
|
|
% rotated Roman labels, not by separate colors.
|
|
\colorlet{fleetinfra}{accentcolor} % Part I: The Fleet
|
|
\colorlet{fleetdist}{accentcolor} % Part II: Distributed ML
|
|
\colorlet{fleetserve}{accentcolor} % Part III: Deployment at Scale
|
|
\colorlet{fleetassure}{accentcolor} % Assurance layer within Part IV
|
|
\colorlet{fleetgov}{accentcolor} % Part IV: The Responsible Fleet
|
|
|
|
% Quiz element colors
|
|
\definecolor{quiz-question-color1}{RGB}{225,243,248} % Light blue background
|
|
\definecolor{quiz-question-color2}{RGB}{17,158,199} % Blue border
|
|
\definecolor{quiz-answer-color1}{RGB}{250,234,241} % Light pink background
|
|
\definecolor{quiz-answer-color2}{RGB}{152,14,90} % Magenta border
|
|
|
|
% =============================================================================
|
|
% LIST FORMATTING
|
|
% =============================================================================
|
|
% Tighter list spacing for academic style
|
|
\def\tightlist{}
|
|
\setlist{itemsep=1pt, parsep=1pt, topsep=0pt,after={\vspace{0.3\baselineskip}}}
|
|
\let\tightlist\relax
|
|
|
|
\makeatletter
|
|
\@ifpackageloaded{framed}{}{\usepackage{framed}}
|
|
\@ifpackageloaded{fancyvrb}{}{\usepackage{fancyvrb}}
|
|
\makeatother
|
|
|
|
\makeatletter
|
|
%New float "codelisting" has been updated
|
|
\AtBeginDocument{%
|
|
\floatstyle{ruled}
|
|
\newfloat{codelisting}{!htb}{lop}
|
|
\floatname{codelisting}{Listing}
|
|
\floatplacement{codelisting}{!htb}
|
|
\captionsetup[codelisting]{labelfont={bf,ninept},labelformat=mylabel,
|
|
singlelinecheck=false,width=\linewidth,labelsep=none,font={ninept}}%
|
|
% Prevent a code listing from stubbing at a page bottom (caption + 2-3 lines,
|
|
% then a break). Listings are placed [H] (forced here), so when figures float
|
|
% onto the same page they cram the listing to the bottom (e.g. p265 Listing
|
|
% 6.7 under two QKV figures). Reserve ~6 lines: if fewer fit, the whole listing
|
|
% (caption + code) moves to the next page instead of leaving an orphaned stub.
|
|
\BeforeBeginEnvironment{codelisting}{\needspace{6\baselineskip}}%
|
|
\renewenvironment{snugshade}{%
|
|
\def\OuterFrameSep{3pt}%
|
|
\def\FrameCommand{\fboxsep=5pt\colorbox{shadecolor}}%
|
|
\MakeFramed{\advance\hsize-\width\FrameRestore}%
|
|
\leftskip 0.5em \rightskip 0.5em%
|
|
\small% decrease font size
|
|
}{\endMakeFramed}%
|
|
}
|
|
\makeatother
|
|
|
|
%The space before and after the verbatim environment "Highlighting" has been reduced
|
|
\fvset{listparameters=\setlength{\topsep}{0pt}\setlength{\partopsep}{0pt}}
|
|
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{framesep=0mm,commandchars=\\\{\}}
|
|
|
|
\makeatletter
|
|
\renewcommand\fs@ruled{\def\@fs@cfont{\bfseries}\let\@fs@capt\floatc@ruled
|
|
\def\@fs@pre{\hrule height.8pt depth0pt \kern2pt}%
|
|
\def\@fs@post{\kern2pt\hrule\relax}%
|
|
\def\@fs@mid{\kern2pt\hrule\kern1pt}%space between float and caption
|
|
\let\@fs@iftopcapt\iftrue}
|
|
\makeatother
|
|
|
|
|
|
% =============================================================================
|
|
% HYPHENATION RULES
|
|
% =============================================================================
|
|
% Explicit hyphenation points for technical terms to avoid bad breaks
|
|
\hyphenation{
|
|
light-weight
|
|
light-weight-ed
|
|
de-vel-op-ment
|
|
un-der-stand-ing
|
|
mod-els
|
|
prin-ci-ples
|
|
ex-per-tise
|
|
com-pli-cat-ed
|
|
blue-print
|
|
per‧for‧mance
|
|
com-mu-ni-ca-tion
|
|
par-a-digms
|
|
hy-per-ten-sion
|
|
a-chieved
|
|
sus-tain-abil-ity
|
|
}
|
|
|
|
% =============================================================================
|
|
% CODE LISTING CONFIGURATION
|
|
% =============================================================================
|
|
% Settings for code blocks using listings package
|
|
\lstset{
|
|
breaklines=true, % Automatic line wrapping
|
|
breakatwhitespace=true, % Break at whitespace only
|
|
basicstyle=\ttfamily, % Monospace font
|
|
frame=none, % No frame around code
|
|
keepspaces=true, % Preserve spaces
|
|
showspaces=false, % Don't show space characters
|
|
showtabs=false, % Don't show tab characters
|
|
columns=flexible, % Flexible column width
|
|
belowskip=0pt, % Minimal spacing
|
|
aboveskip=0pt
|
|
}
|
|
|
|
% =============================================================================
|
|
% PAGE GEOMETRY
|
|
% =============================================================================
|
|
% MIT Press trim size: 8" x 10" (per publisher specifications, Feb 2026)
|
|
%
|
|
% Layout (per MIT Press markup):
|
|
% - 1/2" (0.5in) from top of page to header
|
|
% - 5/8" (0.625in) bottom margin
|
|
% - 7/8" (0.875in) inner/gutter margin (binding side)
|
|
% - 1/4" (0.25in) from page edge to margin notes
|
|
%
|
|
\geometry{
|
|
paperwidth=8in,
|
|
paperheight=10in,
|
|
top=0.5in, % 1/2" from top edge to header
|
|
bottom=0.625in, % 5/8" bottom margin
|
|
inner=0.875in, % 7/8" gutter (binding side)
|
|
outer=1.75in, % Outer margin (includes space for sidenotes)
|
|
headheight=14pt, % Height for header text (~0.2")
|
|
headsep=18pt, % Small gap between header line and text
|
|
includehead, % Header starts at top margin position
|
|
footskip=24pt, % Space from text to footer
|
|
marginparwidth=1.25in, % Width for margin notes
|
|
marginparsep=0.25in, % Gap between text and margin notes
|
|
twoside % Different left/right pages
|
|
}
|
|
|
|
% =============================================================================
|
|
% SIDENOTE STYLING
|
|
% =============================================================================
|
|
% Custom sidenote design with crimson vertical bar
|
|
\renewcommand{\thefootnote}{\textcolor{crimson}{\arabic{footnote}}}
|
|
|
|
% Save original sidenote command only once
|
|
\makeatletter
|
|
\@ifundefined{origsidenote}{%
|
|
\let\origsidenote\sidenote%
|
|
}{}
|
|
\makeatother
|
|
|
|
% New command with support for optional offset
|
|
% \styledsidenote[<number>][<offset>]{<text>}
|
|
\NewDocumentCommand{\styledsidenote}{ O{} O{} m }{%
|
|
\origsidenote[#1][#2]{%
|
|
\noindent
|
|
\color{crimson!100}%
|
|
\raisebox{0pt}{\rule{0.5pt}{1.5em}}%
|
|
\hspace{0.3em}%
|
|
\color{black}%
|
|
\footnotesize #3%
|
|
}%
|
|
}
|
|
|
|
% Save original sidenote command
|
|
\makeatletter
|
|
\@ifundefined{oldsidenote}{
|
|
\let\oldsidenote\sidenote%
|
|
}{}
|
|
\makeatother
|
|
|
|
% Redefine sidenote with vertical crimson bar
|
|
\renewcommand{\sidenote}[1]{%
|
|
\oldsidenote{%
|
|
\noindent
|
|
\color{crimson!100}% % Crimson vertical line
|
|
\raisebox{0em}{%
|
|
\rule{0.5pt}{1.2em}% % Thin vertical line
|
|
}
|
|
\hspace{0.3em}% % Space after line
|
|
\color{black}% % Reset text color
|
|
\footnotesize\ignorespaces#1\unskip% % Sidenote content
|
|
}%
|
|
}
|
|
|
|
% =============================================================================
|
|
% FLOAT HANDLING
|
|
% =============================================================================
|
|
% Patch LaTeX's output routine to handle float overflow gracefully
|
|
% The "Float(s) lost" error occurs in \@doclearpage when \@currlist is not empty
|
|
% This patch silently clears pending floats that can't be placed
|
|
\makeatletter
|
|
\let\orig@doclearpage\@doclearpage
|
|
\def\@doclearpage{%
|
|
\ifx\@currlist\@empty\else
|
|
\global\let\@currlist\@empty
|
|
\typeout{Warning: Floats cleared to prevent overflow}%
|
|
\fi
|
|
\orig@doclearpage
|
|
}
|
|
\makeatother
|
|
|
|
% Additional safety for structural commands
|
|
\let\originalbackmatter\backmatter
|
|
\renewcommand{\backmatter}{%
|
|
\clearpage%
|
|
\originalbackmatter%
|
|
}
|
|
|
|
% Half-title hook. Per-volume preamble files (tex/halftitle-volX.tex) may
|
|
% \renewcommand\halftitle to emit a half-title page. The default below is
|
|
% empty so volumes that have no half-title still build cleanly. The macro
|
|
% is called from _extensions/mlsysbook-ext/titlepage/before-body.tex at the
|
|
% seam between the coverpage block and the titlepage block, producing the
|
|
% standard academic book front-matter sequence: cover art -> blank verso
|
|
% -> half-title -> blank verso -> title page.
|
|
\providecommand{\halftitle}{}
|
|
|
|
% Copyright/dedication hooks. Same pattern as \halftitle above: the shared
|
|
% titlepage extension (before-body.tex) calls \copyrightpage and
|
|
% \dedicationpage unconditionally, so they must exist as no-ops for any
|
|
% volume that does not define them. Volume I \renewcommand-s both in
|
|
% tex/frontmatter-vol1.tex. (2026-06-07: added after the Vol II PDF build
|
|
% failed with "Undefined control sequence \copyrightpage" — the macros were
|
|
% \newcommand-ed only in the vol1 include.)
|
|
\providecommand{\copyrightpage}{}
|
|
\providecommand{\dedicationpage}{}
|
|
|
|
\let\originalfrontmatter\frontmatter
|
|
\renewcommand{\frontmatter}{%
|
|
\clearpage%
|
|
\originalfrontmatter%
|
|
}
|
|
|
|
\let\originalmainmatter\mainmatter
|
|
\renewcommand{\mainmatter}{%
|
|
\clearpage%
|
|
\originalmainmatter%
|
|
}
|
|
|
|
% =============================================================================
|
|
% PAGE HEADERS AND FOOTERS
|
|
% =============================================================================
|
|
% Ensure chapters use fancy page style (not plain)
|
|
\patchcmd{\chapter}{\thispagestyle{plain}}{\thispagestyle{fancy}}{}{}
|
|
|
|
% Main page style with crimson headers
|
|
% Page numbers on OUTSIDE edge (standard book convention per MIT Press)
|
|
\pagestyle{fancy}
|
|
\fancyhf{} % Clear all
|
|
\fancyhead[LE]{\color{crimson}\thepage} % Left even: page number (outside)
|
|
\fancyhead[RE]{\small\color{crimson}\nouppercase{\rightmark}} % Right even: section
|
|
\fancyhead[LO]{\small\color{crimson}\nouppercase{\leftmark}} % Left odd: chapter
|
|
\fancyhead[RO]{\color{crimson}\thepage} % Right odd: page number (outside)
|
|
\renewcommand{\headrulewidth}{0.4pt} % Thin header line
|
|
\renewcommand{\footrulewidth}{0pt} % No footer line
|
|
|
|
% Plain page style (for chapter openings)
|
|
\fancypagestyle{plain}{
|
|
\fancyhf{}
|
|
\fancyfoot[C]{\color{crimson}\thepage} % Centered page number
|
|
\renewcommand{\headrulewidth}{0pt}
|
|
\renewcommand{\footrulewidth}{0pt}
|
|
}
|
|
|
|
% =============================================================================
|
|
% KOMA-SCRIPT FONT ADJUSTMENTS
|
|
% =============================================================================
|
|
% Apply crimson color to all heading levels
|
|
\addtokomafont{disposition}{\rmfamily\color{crimson}}
|
|
\addtokomafont{chapter}{\color{crimson}}
|
|
\addtokomafont{section}{\color{crimson}}
|
|
\addtokomafont{subsection}{\color{crimson}}
|
|
|
|
% =============================================================================
|
|
% ABSTRACT ENVIRONMENT
|
|
% =============================================================================
|
|
\newenvironment{abstract}{
|
|
\chapter*{\abstractname}
|
|
\addcontentsline{toc}{chapter}{\abstractname}
|
|
\small
|
|
}{
|
|
\clearpage
|
|
}
|
|
|
|
% =============================================================================
|
|
% HYPERLINK CONFIGURATION
|
|
% =============================================================================
|
|
% Crimson-colored links throughout, single-page PDF layout (MIT Press preflight)
|
|
\hypersetup{
|
|
linkcolor=crimson,
|
|
citecolor=crimson,
|
|
urlcolor=crimson,
|
|
pdfpagelayout=SinglePage, % Single page view (per MIT Press requirement)
|
|
pdfstartview=Fit % Initial zoom fits page
|
|
}
|
|
|
|
% Override hyperref link color for TOC entries only.
|
|
% TOC entries are typeset as hyperlinks, so their visible color is hyperref's
|
|
% linkcolor (NOT \textcolor). We wrap every \contentsline call in a group
|
|
% that locally swaps linkcolor/citecolor/urlcolor to \toccolor, leaving body
|
|
% cross-refs/citations untouched.
|
|
\makeatletter
|
|
\let\MLSYSorigcontentsline\contentsline
|
|
\renewcommand{\contentsline}[4]{%
|
|
\begingroup
|
|
\hypersetup{linkcolor=toccolor,citecolor=toccolor,urlcolor=toccolor}%
|
|
\MLSYSorigcontentsline{#1}{#2}{#3}{#4}%
|
|
\endgroup
|
|
}
|
|
\makeatother
|
|
|
|
% =============================================================================
|
|
% PART SUMMARY SYSTEM
|
|
% =============================================================================
|
|
% Allows adding descriptive text below part titles
|
|
\newcommand{\partsummary}{} % Empty by default
|
|
\newif\ifhaspartsummary%
|
|
\haspartsummaryfalse%
|
|
|
|
\newcommand{\setpartsummary}[1]{%
|
|
\renewcommand{\partsummary}{#1}%
|
|
\haspartsummarytrue%
|
|
}
|
|
|
|
% Additional colors for part page backgrounds
|
|
\definecolor{BrownLL}{RGB}{233,222,220}
|
|
\definecolor{BlueDD}{RGB}{62,100,125}
|
|
\colorlet{BlueDD}{accentcolor}
|
|
|
|
% Diagram colors (used by inline TikZ in chapters; also in diagram.yml for SVG)
|
|
\definecolor{BlueLine}{HTML}{006395}
|
|
\definecolor{BlueL}{RGB}{209,243,255}
|
|
\definecolor{GreenLine}{HTML}{008F45}
|
|
\definecolor{GreenL}{RGB}{219,253,166}
|
|
\definecolor{GreenL0}{HTML}{D5F5E3}
|
|
\definecolor{OrangeLine}{HTML}{E67817}
|
|
\definecolor{OrangeL}{RGB}{250,212,175}
|
|
\definecolor{RedLine}{HTML}{D9534F}
|
|
\definecolor{RedL}{RGB}{253,226,240}
|
|
\definecolor{GrayLine}{HTML}{666666}
|
|
\definecolor{GrayL}{HTML}{E0E0E0}
|
|
\definecolor{VioletLine}{HTML}{7E317B}
|
|
\definecolor{VioletL}{RGB}{247,180,247}
|
|
\definecolor{BrownLine}{RGB}{143,120,116}
|
|
\definecolor{BrownL}{RGB}{233,222,220}
|
|
|
|
% ===============================================================================
|
|
% PART STYLING SYSTEM
|
|
% ===============================================================================
|
|
%
|
|
% This system provides three distinct visual styles for book organization:
|
|
%
|
|
% 1. NUMBERED PARTS (\part{title}) - For main book sections
|
|
% - Roman numerals (I, II, III, etc.) in top right corner
|
|
% - Crimson title with horizontal lines above/below
|
|
% - "Part I" label in sidebar
|
|
% - Used for: foundations, principles, optimization, deployment, etc.
|
|
%
|
|
% 2. UNNUMBERED PARTS (\part*{title}) - For special sections like "Labs"
|
|
% - Division-style geometric background (left side)
|
|
% - No Roman numerals
|
|
% - Used for: labs section
|
|
%
|
|
% 3. DIVISIONS (\division{title}) - For major book divisions
|
|
% - Clean geometric background with centered title
|
|
% - Used for: frontmatter, main_content, backmatter
|
|
%
|
|
% The Lua filter (inject-parts.lua) automatically routes parts by {key:xxx} commands
|
|
% to the appropriate LaTeX command based on the key name.
|
|
% ===============================================================================
|
|
|
|
% NUMBERED PARTS: Roman numeral styling for main book sections
|
|
\titleformat{\part}[display]
|
|
{\thispagestyle{empty}}{}{20pt}{
|
|
\begin{tikzpicture}[remember picture,overlay]
|
|
%%%
|
|
%%
|
|
\node[crimson,align=flush right,
|
|
inner sep=0,outer sep=0mm,draw=none,%
|
|
anchor=east,minimum height=31mm, text width=1.2\textwidth,
|
|
yshift=-30mm,font={%
|
|
\fontsize{98pt}{104}\selectfont\bfseries}] (BG) at (current page text area.north east){\thepart};
|
|
%
|
|
\node[black,inner sep=0mm,draw=none,
|
|
anchor=mid,text width=1.2\textwidth,
|
|
minimum height=35mm, align=right,
|
|
node distance=7mm,below=of BG,
|
|
font={\fontsize{30pt}{34}\selectfont}]
|
|
(BGG) {\hyphenchar\font=-1 \color{black}\MakeUppercase {#1}};
|
|
\draw [crimson,line width=3pt] ([yshift=0mm]BGG.north west) -- ([yshift=0mm]BGG.north east);
|
|
\draw [crimson,line width=2pt] ([yshift=0mm]BGG.south west) -- ([yshift=0mm]BGG.south east);
|
|
%
|
|
\node[fill=crimson,text=white,rotate=90,%
|
|
anchor=south west,minimum height=15mm,
|
|
minimum width=40mm,font={%
|
|
\fontsize{20pt}{20}\selectfont\bfseries}](BP) at
|
|
(current page text area.south east)
|
|
{{Part}~\thepart};
|
|
%
|
|
\path[red](BP.north west)-|coordinate(PS)(BGG.south west);
|
|
%
|
|
% Part summary box commented out for cleaner design
|
|
% \ifhaspartsummary
|
|
% \node[inner sep=4pt,text width=0.7\textwidth,draw=none,fill=BrownLL!40,
|
|
% align=justify,font={\fontsize{9pt}{12}\selectfont},anchor=south west]
|
|
% at (PS) {\partsummary};
|
|
% \fi
|
|
\end{tikzpicture}
|
|
}[]
|
|
|
|
\renewcommand{\thepart}{\Roman{part}}
|
|
|
|
% UNNUMBERED PARTS: Division-style background for special sections
|
|
\titleformat{name=\part,numberless}[display]
|
|
{\thispagestyle{empty}}{}{20pt}{
|
|
\begin{tikzpicture}[remember picture,overlay]
|
|
%%%
|
|
\coordinate(S1)at([yshift=-200mm]current page.north west);
|
|
\draw[draw=none,fill=BlueDD!7](S1)--++(45:16)coordinate(S2)-
|
|
|(S2|-current page.north west)--(current page.north west)coordinate(S3)--(S1);
|
|
%
|
|
\coordinate(E1)at([yshift=-98mm]current page.north west);
|
|
\draw[draw=none,fill=BlueDD!15](E1)--(current page.north west)coordinate(E2)
|
|
--++(0:98mm)coordinate(E3)--(E1);
|
|
%
|
|
\coordinate(D1)at([yshift=15mm]current page.south west);
|
|
\draw[draw=none,fill=BlueDD!40,opacity=0.5](D1)--++(45:5.5)coordinate(D2)
|
|
-|(D2|-current page.north west)--(current page.north west)coordinate(D3)--(D1);
|
|
%%%%
|
|
\path[red](S2)-|(S2-|current page.east)coordinate(SS2);
|
|
%PART
|
|
\node[crimson,align=flush right,inner sep=0,outer sep=0mm,draw=none,anchor=south,
|
|
font={\fontsize{48pt}{48}\selectfont\bfseries}] (BG) at ($(S2)!0.5!(SS2)$){\hphantom{Part}};
|
|
%%%
|
|
\path[green]([yshift=15mm]D2)-|coordinate(TPD)(BG.south east);
|
|
\node[inner sep=0mm,draw=none,anchor=south east,%text width=0.9\textwidth,
|
|
align=right,font={\fontsize{40pt}{40}\selectfont}]
|
|
(BGG) at (TPD) {\color{crimson}\MakeUppercase {#1}};%\MakeUppercase {}
|
|
\end{tikzpicture}
|
|
}
|
|
|
|
% Define \numberedpart command for numbered parts
|
|
% Note: This command also triggers the switch from Roman to Arabic page numbering
|
|
% when the first numbered part is encountered (before Chapter 1)
|
|
\makeatletter
|
|
\newif\if@firstnumberedpart%
|
|
\@firstnumberedparttrue%
|
|
|
|
\newcommand{\numberedpart}[1]{%
|
|
\FloatBarrier% % Flush all pending floats before part break
|
|
\cleardoublepage
|
|
% Switch to Arabic page numbering on first numbered part
|
|
\if@firstnumberedpart%
|
|
\cleardoublepage%
|
|
%\setcounter{lastRomanPage}{\value{page}}%
|
|
%\pagenumbering{arabic}%
|
|
\@firstnumberedpartfalse%
|
|
\@firstnumberedfalse% % Also mark chapters as not first (prevents double switch)
|
|
\fi
|
|
\thispagestyle{empty}
|
|
\stepcounter{part}%
|
|
\begin{tikzpicture}[remember picture,overlay]
|
|
%%%
|
|
%%
|
|
\node[crimson,align=flush right,
|
|
inner sep=0,outer sep=0mm,draw=none,%
|
|
anchor=east,minimum height=31mm, text width=1.2\textwidth,
|
|
yshift=-30mm,font={%
|
|
\fontsize{98pt}{104}\selectfont\bfseries}] (BG) at (current page text area.north east){\thepart};
|
|
%
|
|
\node[black,inner sep=0mm,draw=none,
|
|
anchor=mid,text width=1.2\textwidth,
|
|
minimum height=35mm, align=right,
|
|
node distance=7mm,below=of BG,
|
|
font={\fontsize{30pt}{34}\selectfont}]
|
|
(BGG) {\hyphenchar\font=-1 \color{black}\MakeUppercase {#1}};
|
|
\draw [crimson,line width=3pt] ([yshift=0mm]BGG.north west) -- ([yshift=0mm]BGG.north east);
|
|
\draw [crimson,line width=2pt] ([yshift=0mm]BGG.south west) -- ([yshift=0mm]BGG.south east);
|
|
%
|
|
\node[fill=crimson,text=white,rotate=90,%
|
|
anchor=south west,minimum height=15mm,
|
|
minimum width=40mm,font={%
|
|
\fontsize{20pt}{20}\selectfont\bfseries}](BP) at
|
|
(current page text area.south east)
|
|
{{Part}~\thepart};
|
|
%
|
|
\path[red](BP.north west)-|coordinate(PS)(BGG.south west);
|
|
%
|
|
% Part summary box commented out for cleaner design
|
|
% \ifhaspartsummary
|
|
% \node[inner sep=4pt,text width=0.7\textwidth,draw=none,fill=BrownLL!40,
|
|
% align=justify,font={\fontsize{9pt}{12}\selectfont},anchor=south west]
|
|
% at (PS) {\partsummary};
|
|
% \fi
|
|
\end{tikzpicture}
|
|
\clearpage
|
|
}
|
|
\makeatother
|
|
|
|
|
|
\makeatletter
|
|
\newif\if@firstdivision
|
|
\@firstdivisiontrue
|
|
|
|
% DIVISIONS: Clean geometric styling with subtle tech elements
|
|
% Used for frontmatter, main_content, and backmatter divisions
|
|
\newcommand{\division}[1]{%
|
|
\FloatBarrier% % Flush all pending floats before division break
|
|
\cleardoublepage
|
|
%
|
|
\if@firstdivision
|
|
\pagenumbering{arabic}% starts arabic numbering from 1
|
|
\@firstdivisionfalse
|
|
\fi
|
|
%
|
|
\thispagestyle{empty}
|
|
\begin{tikzpicture}[remember picture,overlay]
|
|
|
|
% Clean geometric background (original design)
|
|
\coordinate(S1)at([yshift=-200mm]current page.north west);
|
|
\draw[draw=none,fill=BlueDD!7](S1)--++(45:16)coordinate(S2)-
|
|
|(S2|-current page.north west)--(current page.north west)coordinate(S3)--(S1);
|
|
|
|
\coordinate(E1)at([yshift=-98mm]current page.north west);
|
|
\draw[draw=none,fill=BlueDD!15](E1)--(current page.north west)coordinate(E2)
|
|
--++(0:98mm)coordinate(E3)--(E1);
|
|
|
|
\coordinate(D1)at([yshift=15mm]current page.south west);
|
|
\draw[draw=none,fill=BlueDD!40,opacity=0.5](D1)--++(45:5.5)coordinate(D2)
|
|
-|(D2|-current page.north west)--(current page.north west)coordinate(D3)--(D1);
|
|
|
|
% Subtle tech elements - positioned in white areas for better visibility
|
|
% Upper right white area - more visible
|
|
\draw[crimson!40, line width=0.8pt] ([xshift=140mm,yshift=-60mm]current page.north west) -- ++(40mm,0);
|
|
\draw[crimson!40, line width=0.8pt] ([xshift=150mm,yshift=-70mm]current page.north west) -- ++(30mm,0);
|
|
\draw[crimson!35, line width=0.7pt] ([xshift=160mm,yshift=-60mm]current page.north west) -- ++(0,-15mm);
|
|
\draw[crimson!35, line width=0.7pt] ([xshift=170mm,yshift=-70mm]current page.north west) -- ++(0,10mm);
|
|
|
|
% Circuit nodes - upper right
|
|
\fill[crimson!50] ([xshift=160mm,yshift=-60mm]current page.north west) circle (1.5mm);
|
|
\fill[white] ([xshift=160mm,yshift=-60mm]current page.north west) circle (0.8mm);
|
|
\fill[crimson!50] ([xshift=170mm,yshift=-70mm]current page.north west) circle (1.3mm);
|
|
\fill[white] ([xshift=170mm,yshift=-70mm]current page.north west) circle (0.6mm);
|
|
|
|
% Lower right white area - enhanced visibility
|
|
\draw[crimson!45, line width=0.9pt] ([xshift=140mm,yshift=-190mm]current page.north west) -- ++(45mm,0);
|
|
\draw[crimson!45, line width=0.9pt] ([xshift=150mm,yshift=-200mm]current page.north west) -- ++(35mm,0);
|
|
\draw[crimson!40, line width=0.8pt] ([xshift=160mm,yshift=-190mm]current page.north west) -- ++(0,-20mm);
|
|
\draw[crimson!40, line width=0.8pt] ([xshift=170mm,yshift=-200mm]current page.north west) -- ++(0,15mm);
|
|
|
|
% Additional connecting lines in lower right
|
|
\draw[crimson!35, line width=0.7pt] ([xshift=130mm,yshift=-180mm]current page.north west) -- ++(25mm,0);
|
|
\draw[crimson!35, line width=0.7pt] ([xshift=145mm,yshift=-180mm]current page.north west) -- ++(0,-25mm);
|
|
|
|
% Circuit nodes - lower right (more prominent)
|
|
\fill[crimson!55] ([xshift=160mm,yshift=-190mm]current page.north west) circle (1.6mm);
|
|
\fill[white] ([xshift=160mm,yshift=-190mm]current page.north west) circle (0.9mm);
|
|
\fill[crimson!55] ([xshift=170mm,yshift=-200mm]current page.north west) circle (1.4mm);
|
|
\fill[white] ([xshift=170mm,yshift=-200mm]current page.north west) circle (0.7mm);
|
|
\fill[crimson!50] ([xshift=145mm,yshift=-180mm]current page.north west) circle (1.2mm);
|
|
\fill[white] ([xshift=145mm,yshift=-180mm]current page.north west) circle (0.6mm);
|
|
|
|
% Title positioned in center - clean and readable
|
|
\node[inner sep=0mm,draw=none,anchor=center,text width=0.8\textwidth,
|
|
align=center,font={\fontsize{40pt}{40}\selectfont}]
|
|
(BGG) at (current page.center) {\color{crimson}\MakeUppercase {#1}};
|
|
|
|
\end{tikzpicture}
|
|
\clearpage
|
|
}
|
|
|
|
\makeatother
|
|
|
|
% LAB DIVISIONS: Circuit-style neural network design for lab sections
|
|
% Used specifically for lab platform sections (arduino, xiao, grove, etc.)
|
|
\newcommand{\labdivision}[1]{%
|
|
\FloatBarrier% % Flush all pending floats before lab division break
|
|
\clearpage
|
|
\thispagestyle{empty}
|
|
\begin{tikzpicture}[remember picture,overlay]
|
|
% Circuit background with subtle gradient
|
|
\coordinate(S1)at([yshift=-200mm]current page.north west);
|
|
\draw[draw=none,fill=BlueDD!5](S1)--++(45:16)coordinate(S2)-
|
|
|(S2|-current page.north west)--(current page.north west)coordinate(S3)--(S1);
|
|
|
|
% TOP AREA: Circuit lines in upper white space
|
|
\draw[crimson!50, line width=1.5pt] ([xshift=30mm,yshift=-40mm]current page.north west) -- ++(60mm,0);
|
|
\draw[crimson!40, line width=1pt] ([xshift=120mm,yshift=-50mm]current page.north west) -- ++(50mm,0);
|
|
\draw[crimson!50, line width=1.5pt] ([xshift=40mm,yshift=-70mm]current page.north west) -- ++(40mm,0);
|
|
|
|
% Connecting lines in top area
|
|
\draw[crimson!30, line width=1pt] ([xshift=60mm,yshift=-40mm]current page.north west) -- ++(0,-20mm);
|
|
\draw[crimson!30, line width=1pt] ([xshift=145mm,yshift=-50mm]current page.north west) -- ++(0,10mm);
|
|
|
|
% Neural nodes in top area
|
|
\fill[crimson!70] ([xshift=60mm,yshift=-40mm]current page.north west) circle (2.5mm);
|
|
\fill[white] ([xshift=60mm,yshift=-40mm]current page.north west) circle (1.5mm);
|
|
\fill[crimson!60] ([xshift=145mm,yshift=-50mm]current page.north west) circle (2mm);
|
|
\fill[white] ([xshift=145mm,yshift=-50mm]current page.north west) circle (1mm);
|
|
\fill[crimson!80] ([xshift=80mm,yshift=-70mm]current page.north west) circle (2mm);
|
|
\fill[white] ([xshift=80mm,yshift=-70mm]current page.north west) circle (1mm);
|
|
|
|
% BOTTOM AREA: Circuit lines in lower white space
|
|
\draw[crimson!50, line width=1.5pt] ([xshift=20mm,yshift=-200mm]current page.north west) -- ++(70mm,0);
|
|
\draw[crimson!40, line width=1pt] ([xshift=110mm,yshift=-210mm]current page.north west) -- ++(60mm,0);
|
|
\draw[crimson!50, line width=1.5pt] ([xshift=35mm,yshift=-230mm]current page.north west) -- ++(45mm,0);
|
|
|
|
% Connecting lines in bottom area
|
|
\draw[crimson!30, line width=1pt] ([xshift=55mm,yshift=-200mm]current page.north west) -- ++(0,-20mm);
|
|
\draw[crimson!30, line width=1pt] ([xshift=140mm,yshift=-210mm]current page.north west) -- ++(0,15mm);
|
|
|
|
% Neural nodes in bottom area
|
|
\fill[crimson!70] ([xshift=55mm,yshift=-200mm]current page.north west) circle (2.5mm);
|
|
\fill[white] ([xshift=55mm,yshift=-200mm]current page.north west) circle (1.5mm);
|
|
\fill[crimson!60] ([xshift=140mm,yshift=-210mm]current page.north west) circle (2mm);
|
|
\fill[white] ([xshift=140mm,yshift=-210mm]current page.north west) circle (1mm);
|
|
\fill[crimson!80] ([xshift=80mm,yshift=-230mm]current page.north west) circle (2mm);
|
|
\fill[white] ([xshift=80mm,yshift=-230mm]current page.north west) circle (1mm);
|
|
|
|
% SIDE AREAS: Subtle circuit elements on left and right edges
|
|
\draw[crimson!30, line width=1pt] ([xshift=15mm,yshift=-120mm]current page.north west) -- ++(20mm,0);
|
|
\draw[crimson!30, line width=1pt] ([xshift=175mm,yshift=-130mm]current page.north west) -- ++(15mm,0);
|
|
\fill[crimson!50] ([xshift=25mm,yshift=-120mm]current page.north west) circle (1.5mm);
|
|
\fill[white] ([xshift=25mm,yshift=-120mm]current page.north west) circle (0.8mm);
|
|
\fill[crimson!50] ([xshift=185mm,yshift=-130mm]current page.north west) circle (1.5mm);
|
|
\fill[white] ([xshift=185mm,yshift=-130mm]current page.north west) circle (0.8mm);
|
|
|
|
% Title positioned in center - CLEAN AREA
|
|
\node[inner sep=0mm,draw=none,anchor=center,text width=0.8\textwidth,
|
|
align=center,font={\fontsize{44pt}{44}\selectfont\bfseries}]
|
|
(BGG) at (current page.center) {\color{crimson}\MakeUppercase {#1}};
|
|
|
|
\end{tikzpicture}
|
|
\clearpage
|
|
}
|
|
|
|
% Define \lab command for lab styling (different visual treatment)
|
|
\newcommand{\lab}[1]{%
|
|
\begin{tikzpicture}[remember picture,overlay]
|
|
%%%
|
|
% Different background pattern for labs
|
|
\coordinate(S1)at([yshift=-200mm]current page.north west);
|
|
\draw[draw=none,fill=BlueDD!15](S1)--++(45:16)coordinate(S2)-
|
|
|(S2|-current page.north west)--(current page.north west)coordinate(S3)--(S1);
|
|
%
|
|
\coordinate(E1)at([yshift=-98mm]current page.north west);
|
|
\draw[draw=none,fill=BlueDD!25](E1)--(current page.north west)coordinate(E2)
|
|
--++(0:98mm)coordinate(E3)--(E1);
|
|
%
|
|
\coordinate(D1)at([yshift=15mm]current page.south west);
|
|
\draw[draw=none,fill=BlueDD!60,opacity=0.7](D1)--++(45:5.5)coordinate(D2)
|
|
-|(D2|-current page.north west)--(current page.north west)coordinate(D3)--(D1);
|
|
%%%%
|
|
\path[red](S2)-|(S2-|current page.east)coordinate(SS2);
|
|
%LAB - Different styling
|
|
\node[crimson,align=flush right,inner sep=0,outer sep=0mm,draw=none,anchor=south,
|
|
font={\fontsize{48pt}{48}\selectfont\bfseries}] (BG) at ($(S2)!0.5!(SS2)$){\hphantom{Workshop}};
|
|
%%%
|
|
\path[green]([yshift=15mm]D2)-|coordinate(TPD)(BG.south east);
|
|
\node[inner sep=0mm,draw=none,anchor=south east,%text width=0.9\textwidth,
|
|
align=right,font={\fontsize{40pt}{40}\selectfont}]
|
|
(BGG) at (TPD) {\color{crimson}\MakeUppercase {#1}};%\MakeUppercase {}
|
|
\end{tikzpicture}
|
|
\thispagestyle{empty}
|
|
\clearpage
|
|
}
|
|
|
|
% =============================================================================
|
|
% SECTION FORMATTING
|
|
% =============================================================================
|
|
% All section levels use crimson color and are ragged right
|
|
|
|
% Section (Large, bold, crimson)
|
|
\titleformat{\section}
|
|
{\normalfont\Large\bfseries\color{crimson}\raggedright}
|
|
{\thesection}
|
|
{0.5em}
|
|
{#1}
|
|
\titlespacing*{\section}{0pc}{10pt plus 3pt minus 3pt}{4pt plus 1pt minus 1pt}[0pc]
|
|
|
|
% Subsection (large, bold, crimson)
|
|
\titleformat{\subsection}
|
|
{\normalfont\large\bfseries\color{crimson}\raggedright}
|
|
{\thesubsection}
|
|
{0.5em}
|
|
{#1}
|
|
\titlespacing*{\subsection}{0pc}{9pt plus 3pt minus 3pt}{4pt plus 1pt minus 1pt}[0pc]
|
|
|
|
% Subsubsection (normal size, bold, crimson)
|
|
\titleformat{\subsubsection}
|
|
{\normalfont\normalsize\bfseries\color{crimson}\raggedright}
|
|
{\thesubsubsection}
|
|
{0.5em}
|
|
{#1}
|
|
\titlespacing*{\subsubsection}{0pc}{9pt plus 3pt minus 3pt}{3pt plus 1pt minus 1pt}[0pc]
|
|
|
|
% Paragraph (run-in, bold, crimson)
|
|
\titleformat{\paragraph}[runin]
|
|
{\normalfont\normalsize\bfseries\color{crimson}}
|
|
{\theparagraph}
|
|
{0.5em}
|
|
{#1}
|
|
\titlespacing*{\paragraph}{0pc}{4pt plus 2pt minus 1pt}{0.5em}[0pc]
|
|
|
|
% Subparagraph (run-in, italic, crimson)
|
|
\titleformat{\subparagraph}[runin]
|
|
{\normalfont\normalsize\itshape\color{crimson}}
|
|
{\thesubparagraph}
|
|
{0.5em}
|
|
{#1}
|
|
\titlespacing*{\subparagraph}{0pc}{4pt plus 2pt minus 1pt}{0.5em}[0pc]
|
|
|
|
% =============================================================================
|
|
% CHAPTER FORMATTING
|
|
% =============================================================================
|
|
% Numbered chapters: Large number aligned with title (Harris & Harris style)
|
|
% Design inspired by Harris & Harris "Digital Design and Computer Architecture"
|
|
%
|
|
% Chapter-number display hooks (optional display offset)
|
|
% - By default, these render the real chapter number.
|
|
% - For a one-off layout test, set `\mlsysChapNumOffset` via a chapter's
|
|
% `header-includes` (this affects the big title-page number only).
|
|
% - In appendix mode, displays the letter (A, B, C...) instead of a digit.
|
|
\newcommand{\mlsysChapNumOffset}{0}
|
|
\newif\ifmlsysappendix
|
|
\mlsysappendixfalse
|
|
\newcommand{\mlsysChapNum}{%
|
|
\ifmlsysappendix
|
|
\thechapter% Appendix: use letter (A, B, C, ...)
|
|
\else
|
|
\number\numexpr\value{chapter}+\mlsysChapNumOffset\relax% Chapter: use digit
|
|
\fi
|
|
}
|
|
\newcommand{\mlsysChapNumInt}{\numexpr\value{chapter}+\mlsysChapNumOffset\relax}
|
|
|
|
% Chapter-number sizing: uniform 62pt for all chapter numbers.
|
|
% Works for both single and double digits without bleeding into the margin.
|
|
\newcommand{\mlsysChapNumFont}{\fontsize{70pt}{70pt}\selectfont\bfseries}
|
|
|
|
\titleformat{\chapter}[block]
|
|
{\normalfont\bfseries\color{crimson}}
|
|
{}
|
|
{0pt}
|
|
{%
|
|
% Place chapter number in the outer margin, inset from the page edge.
|
|
%
|
|
% Geometry (odd/recto page, 8in wide):
|
|
% outer margin = 1.75in total (marginparsep 0.25 + marginparwidth 1.25 + 0.25 trim)
|
|
%
|
|
% We anchor the number's RIGHT edge 8pt inward from the physical page
|
|
% edge. This guarantees no clipping for any digit count, and the number
|
|
% sits comfortably in the margin area above the mini-TOC.
|
|
\begin{tikzpicture}[remember picture, overlay]
|
|
\node[anchor=north east,
|
|
inner sep=0pt,
|
|
font={\mlsysChapNumFont},
|
|
text=crimson]
|
|
at ([xshift=-40pt]current page.north east |- current page text area.north)
|
|
{\mlsysChapNum};
|
|
\end{tikzpicture}%
|
|
% Title at normal chapter-start position, full text width
|
|
{\fontsize{34pt}{38pt}\selectfont #1}%
|
|
}
|
|
[]
|
|
|
|
% Unnumbered chapters: no prefix, huge crimson title
|
|
\titleformat{name=\chapter,numberless}
|
|
{\normalfont\huge\bfseries\color{crimson}}
|
|
{}
|
|
{0pt}
|
|
{\Huge #1}
|
|
[]
|
|
|
|
\renewcommand{\chaptername}{Chapter}
|
|
|
|
% Hook into \appendix to switch numbering and TOC prefix
|
|
\let\mlsysOrigAppendix\appendix
|
|
\renewcommand{\appendix}{%
|
|
\mlsysOrigAppendix
|
|
\mlsysappendixtrue% Switch margin number from digits to letters
|
|
\renewcommand{\cftchappresnum}{\color{toccolor}Appendix~}%
|
|
}
|
|
|
|
% =============================================================================
|
|
% TABLE OF CONTENTS FORMATTING
|
|
% =============================================================================
|
|
\setcounter{tocdepth}{3} % Chapter + H2 (section) + H3 (subsection); MIT Press / H&P / CLRS convention
|
|
|
|
% TOC spacing adjustments for number widths and indentation
|
|
\setlength{\cftchapnumwidth}{2em} % Chapter number width
|
|
\setlength{\cftsecnumwidth}{2.75em} % Section number width
|
|
\setlength{\cftsubsecnumwidth}{3.25em} % Subsection number width
|
|
\setlength{\cftsubsubsecnumwidth}{4em} % Subsubsection number width
|
|
\setlength{\cftsubsecindent}{4.25em} % Subsection indent
|
|
\setlength{\cftsubsubsecindent}{7.5em} % Subsubsection indent
|
|
|
|
% Chapter entries in TOC: bold, colored per-volume via \toccolor
|
|
\renewcommand{\cftchapfont}{\bfseries\color{toccolor}}
|
|
\renewcommand{\cftchappresnum}{\color{toccolor}Chapter~}
|
|
|
|
% Custom formatting for division entries (styled like parts)
|
|
\newcommand{\divisionchapter}[1]{%
|
|
\addvspace{12pt}%
|
|
\noindent\hfil\bfseries\color{toccolor}#1\hfil\par%
|
|
\addvspace{6pt}%
|
|
}
|
|
|
|
% Adjust TOC spacing for "Chapter" prefix
|
|
\newlength{\xtraspace}
|
|
\settowidth{\xtraspace}{\cftchappresnum\cftchapaftersnum}
|
|
\addtolength{\cftchapnumwidth}{\xtraspace}
|
|
|
|
% Unnumbered chapters with TOC entry
|
|
\newcommand{\likechapter}[1]{%
|
|
\chapter*{#1}
|
|
\addcontentsline{toc}{chapter}{\textcolor{toccolor}{#1}}
|
|
}
|
|
|
|
% =============================================================================
|
|
% PAGE NUMBERING SYSTEM
|
|
% =============================================================================
|
|
% Implements traditional book numbering:
|
|
% - Roman numerals (i, ii, iii...) for frontmatter
|
|
% - Arabic numerals (1, 2, 3...) for mainmatter
|
|
% Automatically switches at first numbered part OR first numbered chapter
|
|
% (whichever comes first). See \numberedpart command above for part handling.
|
|
\makeatletter
|
|
\newif\if@firstnumbered%
|
|
\@firstnumberedtrue%
|
|
\newif\if@firstunnumbered%
|
|
\@firstunnumberedtrue%
|
|
|
|
\newcounter{lastRomanPage}
|
|
\setcounter{lastRomanPage}{1}
|
|
|
|
% Start document with Roman numerals (frontmatter)
|
|
\AtBeginDocument{
|
|
\pagenumbering{roman}
|
|
\renewcommand{\thepage}{\roman{page}}
|
|
}
|
|
|
|
% Intercept chapter command
|
|
\let\old@chapter\chapter%
|
|
\renewcommand{\chapter}{%
|
|
\@ifstar{\unnumbered@chapter}{\numbered@chapter}%
|
|
}
|
|
|
|
% Numbered chapters: switch to Arabic on first occurrence
|
|
\newcommand{\numbered@chapter}[1]{%
|
|
\if\relax\detokenize{#1}\relax
|
|
% Quarto emits an empty numbered chapter for the root index.qmd in some
|
|
% per-volume PDF builds. It should anchor cleanly but not consume Chapter 1.
|
|
\phantomsection%
|
|
\else
|
|
\if@firstnumbered%
|
|
\cleardoublepage%
|
|
%\setcounter{lastRomanPage}{\value{page}}%
|
|
\pagenumbering{arabic}%
|
|
\setcounter{page}{3}%
|
|
\@firstnumberedfalse%
|
|
\else
|
|
\setcounter{page}{\value{page}}%
|
|
\fi
|
|
\setcounter{sidenote}{1} % Reset footnote counter per chapter
|
|
\old@chapter{#1}%
|
|
\fi
|
|
}
|
|
|
|
% Unnumbered chapters: stay in Roman numerals
|
|
\newcommand{\unnumbered@chapter}[1]{%
|
|
\if@firstunnumbered%
|
|
\clearpage
|
|
%\setcounter{lastRomanPage}{\value{page}}%
|
|
\pagenumbering{roman}%
|
|
\setcounter{page}{15}%
|
|
\@firstunnumberedfalse%
|
|
\fi
|
|
\setcounter{sidenote}{1}
|
|
\old@chapter*{#1}%
|
|
}
|
|
\makeatother
|
|
|
|
% =============================================================================
|
|
% TABLE SIZING AND SPACING
|
|
% =============================================================================
|
|
% Make tables slightly smaller to fit more content
|
|
\AtBeginEnvironment{longtable}{\footnotesize}
|
|
|
|
% Increase vertical spacing in table cells (default is 1.0)
|
|
\renewcommand{\arraystretch}{1.6}
|
|
|
|
% Prefer placing figures and tables at the top of pages
|
|
\makeatletter
|
|
\renewcommand{\fps@figure}{t} % Default placement: top of page
|
|
\renewcommand{\fps@table}{t} % Default placement: top of page
|
|
\makeatother
|
|
|
|
% =============================================================================
|
|
% LONGTABLE PAGE BREAKING FIXES (Windows compatibility)
|
|
% =============================================================================
|
|
% Prevent "Infinite glue shrinkage" errors on Windows LaTeX builds
|
|
% by giving longtable more flexibility in page breaking
|
|
|
|
% Allow more flexible page breaking (vs strict \flushbottom)
|
|
\raggedbottom
|
|
|
|
% Process more rows before attempting page break (default is 20)
|
|
\setcounter{LTchunksize}{50}
|
|
|
|
% Add extra stretch for longtable environments specifically
|
|
\AtBeginEnvironment{longtable}{%
|
|
\setlength{\emergencystretch}{3em}%
|
|
\setlength{\parskip}{0pt plus 1pt}%
|
|
}
|
|
|
|
% =============================================================================
|
|
% LONGTABLE COUNTER FIX FOR UNCAPTIONED TABLES
|
|
% =============================================================================
|
|
% Pandoc/Quarto often renders Markdown tables as longtable.
|
|
% Some longtable versions advance the table counter at the beginning of every
|
|
% longtable environment, even when the table has no caption.
|
|
%
|
|
% We save the table counter at the beginning of each longtable.
|
|
% If the longtable contains a \label command, we treat it as a numbered/captioned
|
|
% table and keep the number.
|
|
% If it has no label, we treat it as an uncaptioned table and restore the counter.
|
|
|
|
\makeatletter
|
|
|
|
\newif\ifmlsys@inside@longtable
|
|
\newif\ifmlsys@longtable@numbered
|
|
\newcounter{mlsysSavedTableCounter}
|
|
|
|
\AtBeginEnvironment{longtable}{%
|
|
\global\mlsys@inside@longtabletrue
|
|
\global\mlsys@longtable@numberedfalse
|
|
\setcounter{mlsysSavedTableCounter}{\value{table}}%
|
|
}
|
|
|
|
\AfterEndEnvironment{longtable}{%
|
|
\ifmlsys@longtable@numbered
|
|
% Captioned/numbered table: keep the number.
|
|
\else
|
|
% Uncaptioned table: restore the previous table counter.
|
|
\setcounter{table}{\value{mlsysSavedTableCounter}}%
|
|
\fi
|
|
\global\mlsys@inside@longtablefalse
|
|
}
|
|
|
|
% Save original \label only once
|
|
\@ifundefined{mlsys@orig@label}{%
|
|
\let\mlsys@orig@label\label
|
|
}{}
|
|
|
|
% Detect labels inside longtable.
|
|
% In Quarto/Pandoc output, captioned tables normally have \label{tbl-...}.
|
|
\renewcommand{\label}[1]{%
|
|
\ifmlsys@inside@longtable
|
|
\global\mlsys@longtable@numberedtrue
|
|
\fi
|
|
\mlsys@orig@label{#1}%
|
|
}
|
|
|
|
\makeatother
|
|
|
|
% =============================================================================
|
|
% IN-CALLOUT TABLES: render Pandoc longtables as confined (non-breaking) tabulars
|
|
% =============================================================================
|
|
% longtable runs LaTeX's output routine to page-break, so it cannot live inside
|
|
% a tcolorbox callout: it escapes the box and the continuation renders unframed
|
|
% (the "broken callout" symptom). Inside our callouts (flag \ifmfxInCallout,
|
|
% set by the fbx / fbxSimple environments) we redefine longtable to a plain
|
|
% tabular confined to the box. Pandoc's longtable body has a fixed shape, so we
|
|
% redirect \caption/\label, swallow the caption-row terminator, and gobble the
|
|
% repeated header + foot scaffolding (\endfirsthead ... \endlastfoot), then add
|
|
% a closing rule. Non-callout longtables are untouched: the \else branch runs
|
|
% the original, fully patched by the counter hooks above.
|
|
\makeatletter
|
|
\@ifundefined{mfx@inCalloutTablesPatched}{%
|
|
\gdef\mfx@inCalloutTablesPatched{}%
|
|
|
|
\newif\ifmfxInCallout
|
|
\let\mfx@orig@longtable\longtable
|
|
\let\mfx@orig@endlongtable\endlongtable
|
|
\let\mfx@orig@caption\caption
|
|
\long\def\mfx@tbl@gobble#1\endlastfoot{}
|
|
% Start the tabular lazily at the first \toprule. Pandoc emits \caption BEFORE
|
|
% \toprule, so deferring the tabular lets the caption typeset ABOVE the table
|
|
% (matching body tables) instead of below.
|
|
\def\mfx@tbl@starttable{%
|
|
\let\toprule\mfx@tbl@realtoprule
|
|
\par\noindent
|
|
% expand the stored colspec into tabular's preamble (array does not expand it)
|
|
\expandafter\mfx@tbl@dostart\expandafter{\mfx@tbl@colspec}%
|
|
}
|
|
% \footnotesize matches the original longtable (\AtBeginEnvironment{longtable}
|
|
% {\footnotesize}); without it the confined tabular renders at the callout's
|
|
% larger font, wrapping more and looking squished.
|
|
\def\mfx@tbl@dostart#1{\footnotesize\begin{tabular}{#1}\mfx@tbl@realtoprule}
|
|
% How many lines must remain in the current box-part for the caption+table to
|
|
% start here; otherwise the breakable foldbox breaks BEFORE the caption and the
|
|
% whole (unbreakable) caption+table block moves to the next page-part, framed.
|
|
% Tunable: raise to push more tables to a fresh part, lower to break less often.
|
|
\def\mfx@tbl@needlines{6}
|
|
|
|
\def\mfx@tbl@begin[#1]#2{%
|
|
\gdef\mfx@tbl@colspec{#2}%
|
|
% space above (separate caption from preceding body text) and below (separate
|
|
% from the table). The callout sets parskip=2pt, so add it explicitly or the
|
|
% caption jams against the text and the rule. \needspace REPLACES the old
|
|
% \nopagebreak: it still keeps the caption off a page bottom, but it now lets
|
|
% the foldbox break right before the caption when fewer than N lines remain,
|
|
% so a tall in-callout table no longer shoves the whole callout (large gap).
|
|
\def\caption##1{%
|
|
\par\addvspace{8\p@}%
|
|
\needspace{\mfx@tbl@needlines\baselineskip}%
|
|
\global\mlsys@longtable@numberedtrue
|
|
\let\mfx@tbl@savedcaption\caption
|
|
\let\caption\mfx@orig@caption
|
|
\captionof{table}{##1}%
|
|
\let\caption\mfx@tbl@savedcaption
|
|
\par\nobreak\vskip 3\p@\nobreak
|
|
}%
|
|
|
|
\let\label\mlsys@orig@label
|
|
\let\tabularnewline\relax
|
|
\let\endfirsthead\mfx@tbl@gobble
|
|
\let\endhead\mfx@tbl@gobble
|
|
\let\mfx@tbl@realtoprule\toprule
|
|
\let\toprule\mfx@tbl@starttable
|
|
}
|
|
\def\mfx@tbl@end{%
|
|
\bottomrule
|
|
\end{tabular}\par\vspace{12\p@}%
|
|
}
|
|
\def\mfx@tbl@longtable{\@ifnextchar[\mfx@tbl@begin{\mfx@tbl@begin[]}}
|
|
\def\longtable{\ifmfxInCallout\expandafter\mfx@tbl@longtable\else
|
|
\expandafter\mfx@orig@longtable\fi}
|
|
\def\endlongtable{\ifmfxInCallout\expandafter\mfx@tbl@end\else
|
|
\expandafter\mfx@orig@endlongtable\fi}
|
|
}{}
|
|
\makeatother
|
|
|
|
% =============================================================================
|
|
% TABLE STYLING - Clean tables with crimson borders
|
|
% =============================================================================
|
|
% Professional table appearance with:
|
|
% - Clean white background (no colored rows)
|
|
% - Crimson-colored borders
|
|
% - Good spacing for readability
|
|
%
|
|
% Note: Headers are automatically bolded by Quarto when using **text** in source
|
|
\usepackage{booktabs} % Professional table rules (\toprule, \midrule, \bottomrule)
|
|
\usepackage{colortbl} % For colored borders (\arrayrulecolor)
|
|
|
|
% Global table styling - crimson borders
|
|
\setlength{\arrayrulewidth}{0.5pt} % Thinner borders than default
|
|
%\arrayrulecolor{crimson} % Crimson borders matching brand
|
|
|
|
% =============================================================================
|
|
% DROP CAPS (Lettrine)
|
|
% =============================================================================
|
|
% Decorative large first letter at chapter openings, following the tradition
|
|
% of Hennessy & Patterson and other MIT Press textbooks.
|
|
% Usage in QMD: \lettrine{T}{he first sentence...}
|
|
\usepackage{lettrine}
|
|
\renewcommand{\LettrineFontHook}{\color{crimson}\bfseries}
|
|
\setcounter{DefaultLines}{3} % Drop cap spans 3 lines
|
|
\renewcommand{\DefaultLoversize}{0.1} % Slight oversize for visual weight
|
|
\renewcommand{\DefaultLraise}{0} % No vertical shift
|
|
\setlength{\DefaultNindent}{0.5em} % Indent of continuation text
|
|
\setlength{\DefaultSlope}{0pt} % No slope on continuation
|
|
|
|
% =============================================================================
|
|
% RUNNING HEADERS — Truncation Safety
|
|
% =============================================================================
|
|
% Long chapter/section titles can overflow the header. These marks truncate
|
|
% gracefully so headers stay within the text block.
|
|
\renewcommand{\chaptermark}[1]{%
|
|
\markboth{\thechapter.\ #1}{}}
|
|
\renewcommand{\sectionmark}[1]{%
|
|
\markright{\thesection\ #1}}
|
|
|
|
% =============================================================================
|
|
% EPIGRAPH ENVIRONMENT
|
|
% =============================================================================
|
|
% For chapter-opening quotations. Renders as right-aligned italic block
|
|
% with attribution in small caps below.
|
|
% Usage: \epigraph{Quote text}{Author Name, \textit{Source}}
|
|
\newcommand{\bookepigraph}[2]{%
|
|
\vspace{1em}%
|
|
\begin{flushright}%
|
|
\begin{minipage}{0.75\textwidth}%
|
|
\raggedleft\itshape\small #1\\[0.5em]%
|
|
\normalfont\small --- #2%
|
|
\end{minipage}%
|
|
\end{flushright}%
|
|
\vspace{1.5em}%
|
|
}
|
|
|
|
% =============================================================================
|
|
% THUMB INDEX TABS
|
|
% =============================================================================
|
|
% Colored tabs on the outer page edge for quick chapter navigation.
|
|
% Each Part gets a different vertical position; chapters within a Part
|
|
% share the same tab position. Visible when flipping through the book.
|
|
\newcounter{thumbindex}
|
|
\setcounter{thumbindex}{0}
|
|
\newlength{\thumbtabheight}
|
|
\setlength{\thumbtabheight}{16mm} % Height of each tab
|
|
\newlength{\thumbtabwidth}
|
|
\setlength{\thumbtabwidth}{8mm} % Width protruding from edge
|
|
\newlength{\thumbtabgap}
|
|
\setlength{\thumbtabgap}{1mm} % Gap between tabs
|
|
|
|
% Advance to next thumb tab position (call at each \part)
|
|
\newcommand{\nextthumb}{%
|
|
\stepcounter{thumbindex}%
|
|
}
|
|
|
|
% Draw the thumb tab on every page (placed in header via fancyhdr)
|
|
\newcommand{\drawthumb}{%
|
|
\ifnum\value{thumbindex}>0%
|
|
\begin{tikzpicture}[remember picture,overlay]
|
|
\pgfmathsetmacro{\thumboffset}{%
|
|
20 + (\value{thumbindex}-1) * (16 + 1)} % mm from top
|
|
\ifodd\value{page}%
|
|
% Odd pages: tab on right edge
|
|
\fill[crimson!80]
|
|
([yshift=-\thumboffset mm]current page.north east)
|
|
rectangle +(-\thumbtabwidth, -\thumbtabheight);
|
|
\node[white,font=\tiny\bfseries,rotate=90]
|
|
at ([yshift=-\thumboffset mm - 0.5\thumbtabheight,
|
|
xshift=-0.5\thumbtabwidth]current page.north east)
|
|
{\Roman{thumbindex}};
|
|
\else
|
|
% Even pages: tab on left edge
|
|
\fill[crimson!80]
|
|
([yshift=-\thumboffset mm]current page.north west)
|
|
rectangle +(\thumbtabwidth, -\thumbtabheight);
|
|
\node[white,font=\tiny\bfseries,rotate=-90]
|
|
at ([yshift=-\thumboffset mm - 0.5\thumbtabheight,
|
|
xshift=0.5\thumbtabwidth]current page.north west)
|
|
{\Roman{thumbindex}};
|
|
\fi
|
|
\end{tikzpicture}%
|
|
\fi
|
|
}
|
|
|
|
% Hook into fancyhdr to draw thumb on every content page
|
|
\AddToHook{shipout/foreground}{%
|
|
\drawthumb%
|
|
}
|
|
|
|
% =============================================================================
|
|
% CROP / BLEED MARKS
|
|
% =============================================================================
|
|
% For final print submission, uncomment the line below to add crop marks.
|
|
% MIT Press production will advise on exact requirements.
|
|
% \usepackage[cam,center,width=7.5in,height=10.5in]{crop}
|
|
|
|
% =============================================================================
|
|
% PDF/A ARCHIVAL COMPLIANCE
|
|
% =============================================================================
|
|
% MIT Press increasingly requires PDF/A for long-term preservation.
|
|
% This embeds all fonts and removes transparency.
|
|
% Note: pdfx must be loaded early; if it conflicts with hyperref,
|
|
% MIT Press production can handle the conversion post-build.
|
|
% Uncomment when ready for final submission:
|
|
% \usepackage[a-3u]{pdfx}
|
|
|
|
% =============================================================================
|
|
% ENHANCED WIDOW / ORPHAN CONTROL
|
|
% =============================================================================
|
|
% Prevent single lines at top/bottom of pages and breaks before equations
|
|
\clubpenalty=10000 % No orphans (single first line at bottom)
|
|
\widowpenalty=10000 % No widows (single last line at top)
|
|
\displaywidowpenalty=10000 % No widow before display math
|
|
\predisplaypenalty=10000 % No page break just before display math
|
|
\postdisplaypenalty=0 % Allow break after display math (natural)
|
|
|
|
% =============================================================================
|
|
% INDEX GENERATION (imakeidx)
|
|
% =============================================================================
|
|
% Creates a professional index at the end of the book.
|
|
% Usage in QMD files: \index{term} or \index{term!subterm}
|
|
% Features enabled:
|
|
% - intoc=true: Adds "Index" entry to Table of Contents
|
|
% - columns=3: Three-column index layout for space efficiency (MIT Press)
|
|
% - columnseprule=true: Vertical line between columns
|
|
\usepackage{imakeidx}
|
|
|
|
\makeindex[
|
|
intoc=true,
|
|
columns=3,
|
|
columnseprule=true,
|
|
title=Index
|
|
]
|
|
|
|
\indexsetup{
|
|
level=\chapter*,
|
|
toclevel=chapter,
|
|
othercode={\scriptsize\sloppy}
|
|
}
|
|
|
|
% =============================================================================
|
|
% BIBLIOGRAPHY FONT SIZE (MIT Press page reduction)
|
|
% =============================================================================
|
|
% Shrink bibliography entries to footnotesize and allow long URLs to break.
|
|
\ExplSyntaxOn
|
|
\cs_new_protected:Npn \mlsysbookbibliographyhrefclean #1#2
|
|
{
|
|
\tl_set:Nn \l_tmpa_tl {#2}
|
|
\tl_trim_spaces:N \l_tmpa_tl
|
|
\exp_args:NV \mlsysbookbibliographyhref \l_tmpa_tl { \nolinkurl{#2} }
|
|
}
|
|
\ExplSyntaxOff
|
|
\AtBeginEnvironment{CSLReferences}{%
|
|
\footnotesize%
|
|
\sloppy%
|
|
\setlength{\emergencystretch}{2em}%
|
|
\setlength{\parskip}{1pt plus 0.5pt}%
|
|
\ifdefined\Urlmuskip
|
|
\Urlmuskip=0mu plus 2mu\relax
|
|
\fi
|
|
% citeproc can emit wrapped URL fields as \href targets with encoded
|
|
% source newlines. Use the visible URL for both target and text here,
|
|
% then route the text through \nolinkurl for URL-safe breakpoints.
|
|
\let\mlsysbookbibliographyhref\href%
|
|
\renewcommand{\href}[2]{\mlsysbookbibliographyhrefclean{#1}{#2}}%
|
|
}
|
|
\AtBeginEnvironment{thebibliography}{%
|
|
\footnotesize%
|
|
\sloppy%
|
|
\setlength{\emergencystretch}{2em}%
|
|
\ifdefined\Urlmuskip
|
|
\Urlmuskip=0mu plus 2mu\relax
|
|
\fi
|
|
}
|
|
|
|
% =============================================================================
|
|
% LIST OF FIGURES / LIST OF TABLES FONT SIZE (MIT Press page reduction)
|
|
% =============================================================================
|
|
% Shrink LOF and LOT entries for space efficiency
|
|
\renewcommand{\cftfigfont}{\footnotesize}
|
|
\renewcommand{\cfttabfont}{\footnotesize}
|
|
\renewcommand{\cftfigpagefont}{\footnotesize}
|
|
\renewcommand{\cfttabpagefont}{\footnotesize}
|
|
% Tighter spacing in LOF/LOT
|
|
\setlength{\cftbeforefigskip}{1pt}
|
|
\setlength{\cftbeforetabskip}{1pt}
|
|
|
|
% =============================================================================
|
|
% FIGURE MANIFEST FOR MIT PRESS (LaTeX extraction)
|
|
% =============================================================================
|
|
% Writes figure data during PDF compilation to an absolute path.
|
|
% Output: scripts/mit_press/FIGURE_MANIFEST_LATEX.txt
|
|
% =============================================================================
|
|
|
|
\newwrite\figlatex
|
|
\makeatletter
|
|
\AtBeginDocument{%
|
|
\immediate\openout\figlatex=\jobname_figures.txt%
|
|
\immediate\write\figlatex{LATEX FIGURE MANIFEST}%
|
|
\immediate\write\figlatex{=====================}%
|
|
}
|
|
|
|
% Hook: write after each figure caption is processed
|
|
% Using deferred \write (no \immediate) so page number is captured at shipout
|
|
% when LaTeX knows the actual page where the float lands
|
|
\let\orig@makecaption\@makecaption
|
|
\renewcommand{\@makecaption}[2]{%
|
|
\orig@makecaption{#1}{#2}%
|
|
% Check if this is a figure caption
|
|
\def\@figtest{figure}%
|
|
\ifx\@captype\@figtest
|
|
\write\figlatex{Figure \thefigure\space | Page \thepage}%
|
|
\fi
|
|
}
|
|
|
|
% =============================================================================
|
|
% CHAPTER MINI-TOC (MARGIN)
|
|
% =============================================================================
|
|
% Places a compact, styled local table of contents in the margin at the
|
|
% chapter opening page. Inspired by Harris & Harris "Digital Design and
|
|
% Computer Architecture" (Elsevier, 2nd ed.) which lists section numbers
|
|
% and titles in the right margin of the chapter opener.
|
|
%
|
|
% PLACEMENT IN QMD FILES
|
|
% ──────────────────────
|
|
% Place \chapterminitoc inside the cover-image margin slot, immediately
|
|
% after the chapter heading. This replaces the DALL-E prompt caption:
|
|
%
|
|
% # Chapter Title {#sec-label}
|
|
% ::: {layout-narrow}
|
|
% ::: {.column-margin}
|
|
% \chapterminitoc ← renders the mini-TOC here
|
|
% :::
|
|
% \noindent
|
|
% {fig-alt="..."}
|
|
% :::
|
|
%
|
|
% The etoc package's \localtableofcontents scopes to the current chapter
|
|
% automatically when placed after the # heading. Only ## (section-level)
|
|
% headings appear; unnumbered sections (e.g. Purpose) are excluded via
|
|
% \etocifnumbered.
|
|
%
|
|
% HOW PART HEADINGS ARE SUPPRESSED
|
|
% ─────────────────────────────────
|
|
% inject_parts.lua writes Part headings to the .toc file via:
|
|
% \addtocontents{toc}{\protect\tocpartentry{Part~I~Title}}
|
|
%
|
|
% \protect prevents LaTeX from expanding \tocpartentry at write time,
|
|
% so the command survives into the .toc file as-is. When the .toc is
|
|
% later read, \tocpartentry checks the \ifminitoc flag:
|
|
% - During \chapterminitoc → flag is true → Part heading suppressed
|
|
% - During global TOC → flag is false → Part heading rendered
|
|
%
|
|
% \DeclareRobustCommand is used as a belt-and-suspenders measure so
|
|
% \tocpartentry is also safe if \protect is ever omitted.
|
|
% =============================================================================
|
|
|
|
% --- \tocpartentry: Part heading in TOC (global only) -------------------------
|
|
% Renders a centered crimson Part heading in the global table of contents.
|
|
% Suppressed inside chapter mini-TOCs via the \ifminitoc flag.
|
|
% Called from inject_parts.lua via \addtocontents{toc}{\protect\tocpartentry{…}}
|
|
\newif\ifminitoc
|
|
\minitocfalse
|
|
\DeclareRobustCommand{\tocpartentry}[1]{%
|
|
\ifminitoc\else
|
|
\par\addvspace{12pt}%
|
|
\noindent\hfil\bfseries\color{toccolor}#1\color{black}\hfil
|
|
\par\addvspace{6pt}%
|
|
\fi
|
|
}
|
|
|
|
% --- \tocdivisionentry: Division heading in TOC (global only) -----------------
|
|
% Renders a centered crimson division heading (e.g. "Back Matter") in the
|
|
% global table of contents. Suppressed inside chapter mini-TOCs via \ifminitoc.
|
|
% Called from inject_parts.lua via \addtocontents{toc}{\protect\tocdivisionentry{…}}
|
|
\DeclareRobustCommand{\tocdivisionentry}[1]{%
|
|
\ifminitoc\else
|
|
\par\addvspace{12pt}%
|
|
\noindent\hfil\bfseries\color{toccolor}#1\color{black}\hfil
|
|
\par\addvspace{6pt}%
|
|
\fi
|
|
}
|
|
|
|
% --- \tocdivisionline: Crimson rule in TOC (global only) ----------------------
|
|
% Renders a centered crimson horizontal rule below division headings.
|
|
% Suppressed inside chapter mini-TOCs via \ifminitoc.
|
|
\DeclareRobustCommand{\tocdivisionline}{%
|
|
\ifminitoc\else
|
|
\par\noindent\hfil{\color{toccolor}\rule{0.6\textwidth}{0.5pt}}\hfil
|
|
\par\addvspace{6pt}%
|
|
\fi
|
|
}
|
|
|
|
% --- \chapterminitoc: chapter-scoped mini-TOC in the margin -------------------
|
|
% Renders numbered section titles (e.g. "1.1 Title") in small bold
|
|
% sans-serif with crimson section numbers. Emits a \parbox directly;
|
|
% margin placement is handled by the ::: {.column-margin} div in the
|
|
% .qmd files, which Quarto translates to \marginnote{...}.
|
|
%
|
|
% Style: 6.5/8pt sans-serif bold, 1pt vertical gap between entries.
|
|
% Depth: section only (subsection and below are hidden).
|
|
\newcommand{\chapterminitoc}{%
|
|
% NOTE: This command emits the mini-TOC content WITHOUT \marginnote.
|
|
% The .qmd files place \chapterminitoc inside ::: {.column-margin},
|
|
% which Quarto translates to \marginnote{...} in the PDF output.
|
|
% Previously, this command also wrapped content in \marginnote,
|
|
% creating double-nesting that caused misalignment in later chapters
|
|
% (LaTeX's margin-note float algorithm accumulated offset errors).
|
|
\parbox{\marginparwidth}{%
|
|
\raggedright
|
|
\setlength{\parskip}{0pt}%
|
|
\setlength{\parindent}{0pt}%
|
|
%
|
|
% Section entries: accent-coloured number in a 2em box, then bold accent title.
|
|
% Mini-TOC uses the volume accent (Crimson / ETHZ Blue) — distinct from the
|
|
% long global TOC which uses toccolor (black) for readability.
|
|
\etocsetstyle{section}%
|
|
{}% begin
|
|
{}% prefix
|
|
{% contents — skip unnumbered sections (e.g. Purpose, Summary)
|
|
% Font note: \rmfamily (not \sffamily) so mini-TOC entries share the
|
|
% book's Palatino (newpxtext) body font. Under LuaLaTeX, \sffamily
|
|
% falls through to Latin Modern Roman rather than Helvetica, producing
|
|
% a visibly different typeface from body text in the chapter opener.
|
|
\etocifnumbered{%
|
|
\noindent
|
|
\makebox[2.3em][l]{%
|
|
\rmfamily\fontsize{6.5}{8}\selectfont\bfseries\color{accentcolor}%
|
|
\etocnumber
|
|
}%
|
|
{\rmfamily\fontsize{6.5}{8}\selectfont\bfseries\color{accentcolor}\etocname}%
|
|
\par\vspace{1pt}%
|
|
}{}%
|
|
}%
|
|
{}% end
|
|
%
|
|
% Hide all other TOC levels
|
|
\etocsetstyle{part}{}{}{}{}%
|
|
\etocsetstyle{chapter}{}{}{}{}%
|
|
\etocsetstyle{subsection}{}{}{}{}%
|
|
\etocsetstyle{subsubsection}{}{}{}{}%
|
|
%
|
|
\etocsetnexttocdepth{section}%
|
|
\etocsettocstyle{}{}%
|
|
\etocinline
|
|
\global\minitoctrue
|
|
% Override hyperref link colour for mini-TOC entries so explicit \color
|
|
% above is honoured (etoc bypasses our \contentsline wrapper).
|
|
\begingroup
|
|
\hypersetup{linkcolor=accentcolor,citecolor=accentcolor,urlcolor=accentcolor}%
|
|
\localtableofcontents
|
|
\endgroup
|
|
\global\minitocfalse
|
|
}%
|
|
}
|
|
|
|
% =============================================================================
|
|
% ML SYSTEMS STACK DIAGRAM (VOLUME 1 — REUSABLE MACRO)
|
|
% =============================================================================
|
|
% Renders a vertical stack of 7 layers with configurable shading (0-100).
|
|
% Used in "Purpose" sections to show which layers a chapter touches.
|
|
%
|
|
% ML Systems Stack Visualization
|
|
% ================================
|
|
% A 7-layer abstraction stack modeled after the traditional computer systems
|
|
% stack (Tanenbaum, Patterson & Hennessy). Each layer provides an abstraction
|
|
% to the layer above and consumes the layer below.
|
|
%
|
|
% Two variants:
|
|
% \mlsysstack — Margin figure: 7 layers + data bar (8 args)
|
|
% \mlsysstackfull — Full-size with subtitles + data bar (8 args, for About page)
|
|
%
|
|
% Usage: \mlsysstack{<hw>}{<fw>}{<models>}{<train>}{<serve>}{<ops>}{<apps>}{<data>}
|
|
% \mlsysstackfull{<hw>}{<fw>}{<models>}{<train>}{<serve>}{<ops>}{<apps>}{<data>}
|
|
%
|
|
% Arguments 1-7: Layer intensities (0 to 100, Integer)
|
|
% 0: Gray (inactive / not covered)
|
|
% 100: Crimson (primary focus)
|
|
% 1-99: Gradient shading (contextual relevance)
|
|
%
|
|
% Argument 8: Data flow intensity (0 to 100)
|
|
% Controls the uniform color of the data bar:
|
|
% - data=0: Gray (inactive — data is not a focus)
|
|
% - data=90: Strong crimson (data is the dominant concern)
|
|
% - data=30: Moderate tint (data is contextually relevant)
|
|
% The data bar is always a single uniform color, never a gradient.
|
|
% This communicates a clear, orthogonal message: "how much does data
|
|
% matter in this chapter?" — independent of which stack layers are lit.
|
|
%
|
|
% Data connectors ("wires"):
|
|
% Each layer has a horizontal connector line from its right edge to the
|
|
% data bar. The connector color matches its layer's own intensity — if a
|
|
% layer is crimson at 60%, its wire to the data bar is also crimson at
|
|
% 60%. If a layer is gray (0%), its wire is faint gray.
|
|
%
|
|
% The wires show how strongly each layer plugs into data. A bright wire
|
|
% from Training into a bright data bar says "training depends heavily on
|
|
% data in this chapter." A faint wire from Hardware into a bright data
|
|
% bar says "hardware doesn't interact with data here, but data still
|
|
% dominates the chapter."
|
|
%
|
|
% Stack (bottom to top):
|
|
% 1. Hardware — Accelerators, silicon, benchmarking
|
|
% 2. Frameworks — PyTorch, TensorFlow, compilers, graph execution
|
|
% 3. Models — Neural network architectures, DL foundations
|
|
% 4. Training — Training loops, distributed training, data selection
|
|
% 5. Serving — Inference runtime, model serving
|
|
% 6. Operations — MLOps, monitoring, CI/CD, deployment pipelines
|
|
% 7. Applications — End-user ML products, responsible AI
|
|
% (Data) — Cross-cutting flow: pipelines, engineering, selection
|
|
|
|
\tikzset{
|
|
% Define simple icons as pics
|
|
% Hardware: Chip with pins
|
|
icon_hardware/.pic={
|
|
\draw[thick] (-0.25,-0.25) rectangle (0.25,0.25);
|
|
\foreach \x in {-0.15, 0, 0.15} \foreach \y in {-0.15, 0, 0.15}
|
|
\fill (\x,\y) circle (0.03);
|
|
\foreach \i in {-0.15, 0.15} {
|
|
\draw (-0.25, \i) -- (-0.35, \i); \draw (0.25, \i) -- (0.35, \i);
|
|
\draw (\i, -0.25) -- (\i, -0.35); \draw (\i, 0.25) -- (\i, 0.35);
|
|
}
|
|
},
|
|
% Frameworks: Stacked blocks
|
|
icon_frameworks/.pic={
|
|
\draw[thick] (-0.25,-0.2) rectangle (0.25,-0.08);
|
|
\draw[thick] (-0.2,-0.08) rectangle (0.2,0.04);
|
|
\draw[thick] (-0.15,0.04) rectangle (0.15,0.16);
|
|
},
|
|
% Models: Neural Network graph
|
|
icon_models/.pic={
|
|
\node[circle,fill,inner sep=0.8pt] (i1) at (-0.25,-0.15) {};
|
|
\node[circle,fill,inner sep=0.8pt] (i2) at (-0.25,0.15) {};
|
|
\node[circle,fill,inner sep=0.8pt] (h1) at (0,-0.15) {};
|
|
\node[circle,fill,inner sep=0.8pt] (h2) at (0,0.15) {};
|
|
\node[circle,fill,inner sep=0.8pt] (o1) at (0.25,0) {};
|
|
\draw (i1)--(h1); \draw (i1)--(h2);
|
|
\draw (i2)--(h1); \draw (i2)--(h2);
|
|
\draw (h1)--(o1); \draw (h2)--(o1);
|
|
},
|
|
% Training: Cycle/Loop with gradient
|
|
icon_training/.pic={
|
|
\draw[thick, ->] (0,0.15) arc (90:360:0.15);
|
|
\draw[thick, ->] (0,-0.15) arc (-90:180:0.15);
|
|
\node[scale=0.6] at (0,0) {$\nabla$};
|
|
},
|
|
% Serving: Server rack / box
|
|
icon_serving/.pic={
|
|
\draw[thick] (-0.3,-0.2) rectangle (0.3,0.2);
|
|
\foreach \y in {-0.08, 0.08}
|
|
\draw (-0.2,\y) -- (0.2,\y);
|
|
\fill (0.15, 0.14) circle (0.03);
|
|
\fill (0.15, -0.02) circle (0.03);
|
|
\fill (0.15, -0.14) circle (0.03);
|
|
},
|
|
% Operations: Gears
|
|
icon_operations/.pic={
|
|
\draw[thick] (0.1,0) circle (0.13);
|
|
\draw[thick] (-0.1,0.05) circle (0.1);
|
|
\foreach \a in {0,60,...,300} {
|
|
\draw[thick] (0.1,0) ++(\a:0.13) -- ++(\a:0.05);
|
|
}
|
|
\foreach \a in {0,72,...,288} {
|
|
\draw[thick] (-0.1,0.05) ++(\a:0.1) -- ++(\a:0.04);
|
|
}
|
|
},
|
|
% Applications: Window with prompt
|
|
icon_applications/.pic={
|
|
\draw[thick] (-0.3,-0.2) rectangle (0.3,0.2);
|
|
\draw (-0.3,0.1) -- (0.3,0.1);
|
|
\node[scale=0.5, anchor=center] at (0,-0.05) {$>\_$};
|
|
}
|
|
}
|
|
|
|
\newcommand{\stacklayer}[4]{
|
|
% Helper command for a single layer
|
|
% #1: y-position (bottom)
|
|
% #2: Text label
|
|
% #3: Intensity (0-100)
|
|
% #4: Icon name
|
|
|
|
% Calculate colors based on intensity
|
|
\ifnum#3=0
|
|
\def\fillcol{black!5}
|
|
\def\textcol{black!30}
|
|
\else
|
|
\def\fillcol{crimson!#3}
|
|
% Text color logic: White for dark backgrounds (>50), Crimson for light (<50)
|
|
\ifnum#3>50
|
|
\def\textcol{white}
|
|
\else
|
|
\def\textcol{crimson}
|
|
\fi
|
|
\fi
|
|
|
|
\node[
|
|
draw=white,
|
|
line width=0.5pt,
|
|
fill=\fillcol,
|
|
minimum width=2.6cm,
|
|
minimum height=1.0cm,
|
|
anchor=south west,
|
|
rounded corners=0pt,
|
|
inner sep=0pt
|
|
] (box) at (0,#1) {};
|
|
|
|
% Text
|
|
% Font note: \rmfamily (not \sffamily) so TikZ label inherits the book's
|
|
% Palatino (newpxtext) body font. With LuaLaTeX + newpxtext + helvet, a
|
|
% bare \sffamily falls through to Latin Modern Roman rather than Helvetica,
|
|
% producing a visibly different typeface from the body text in the margin.
|
|
\node[anchor=west, text=\textcol, font=\rmfamily\scriptsize\bfseries] at ($(box.west)+(0.12,0)$) {#2};
|
|
|
|
% Icon (positioned on the right, nudged left to reduce right-side whitespace)
|
|
\path (box.east) +(-0.50,0) pic[scale=0.78, draw=\textcol, fill=\textcol, text=\textcol] {#4};
|
|
}
|
|
|
|
% 7-layer stack with data bar for chapter margin figures
|
|
\newcommand{\mlsysstack}[8]{
|
|
\begin{tikzpicture}
|
|
% Stack layers with 1.0cm height and no gap (contiguous)
|
|
% Layers are 2.6cm wide; data bar sits to the right with a 0.25cm gap
|
|
% Total width: ~3.15cm to fit within margin figure width
|
|
|
|
% Layer 7: Applications
|
|
\stacklayer{6.0}{Applications}{#7}{icon_applications}
|
|
|
|
% Layer 6: Operations
|
|
\stacklayer{5.0}{Operations}{#6}{icon_operations}
|
|
|
|
% Layer 5: Serving
|
|
\stacklayer{4.0}{Serving}{#5}{icon_serving}
|
|
|
|
% Layer 4: Training
|
|
\stacklayer{3.0}{Training}{#4}{icon_training}
|
|
|
|
% Layer 3: Models
|
|
\stacklayer{2.0}{Models}{#3}{icon_models}
|
|
|
|
% Layer 2: Frameworks
|
|
\stacklayer{1.0}{Frameworks}{#2}{icon_frameworks}
|
|
|
|
% Layer 1: Hardware
|
|
\stacklayer{0.0}{Hardware}{#1}{icon_hardware}
|
|
|
|
% --- Data: vertical bar with uniform fill ---
|
|
% The data bar is a solid color block whose intensity is set by
|
|
% arg 8. It communicates an orthogonal message from the layer
|
|
% boxes: "how central is data to this chapter?" The wires still
|
|
% connect each layer to the bar at that layer's own intensity,
|
|
% showing which layers interact with data.
|
|
|
|
% Data bar: uniform fill from arg 8.
|
|
% The bar is a single solid color — no gradient. This gives a clear
|
|
% reading: "data matters this much in this chapter."
|
|
\pgfmathtruncatemacro{\ddata}{#8}
|
|
\ifnum\ddata=0
|
|
\def\databarcol{black!5}
|
|
\else
|
|
\def\databarcol{crimson!\ddata}
|
|
\fi
|
|
|
|
\fill[\databarcol, rounded corners=1.5pt]
|
|
(2.85, -0.1) rectangle (3.15, 7.10);
|
|
|
|
% Horizontal connectors ("wires") from each layer into the data bar.
|
|
% Each wire's color matches its layer's intensity — the wire is as
|
|
% strong as the layer's relevance to this chapter. Data is the shared
|
|
% bus; the wires show how strongly each layer plugs into it.
|
|
%
|
|
% Layer order bottom-to-top: HW(#1), FW(#2), MOD(#3), TRN(#4),
|
|
% SRV(#5), OPS(#6), APP(#7)
|
|
\foreach \layerint/\ypos in {#1/0.5, #2/1.5, #3/2.5, #4/3.5, #5/4.5, #6/5.5, #7/6.5} {
|
|
\pgfmathtruncatemacro{\lint}{\layerint}
|
|
\ifnum\lint=0
|
|
\def\wirecol{black!8}
|
|
\else
|
|
\edef\wirecol{crimson!\lint}
|
|
\fi
|
|
\draw[\wirecol, line width=1.2pt] (2.6, \ypos) -- (2.85, \ypos);
|
|
}
|
|
|
|
% "Data" label — color based on data bar intensity for readability
|
|
\ifnum\ddata>50
|
|
\def\datatextcol{white}
|
|
\else
|
|
\ifnum\ddata<10
|
|
\def\datatextcol{black!25}
|
|
\else
|
|
\def\datatextcol{crimson}
|
|
\fi
|
|
\fi
|
|
\node[rotate=90, text=\datatextcol, font=\rmfamily\scriptsize\bfseries]
|
|
at (3.0, 3.5) {Data};
|
|
|
|
\end{tikzpicture}
|
|
}
|
|
|
|
% Full-size stack with subtitles and data bar for introductory/explanatory use
|
|
\newcommand{\stacklayerfull}[5]{
|
|
% Helper for full-size layers with subtitle
|
|
% #1: y-position (bottom)
|
|
% #2: Text label
|
|
% #3: Subtitle (brief description)
|
|
% #4: Intensity (0-100)
|
|
% #5: Icon name
|
|
|
|
% Calculate colors based on intensity
|
|
\ifnum#4=0
|
|
\def\fillcol{black!5}
|
|
\def\textcol{black!30}
|
|
\else
|
|
\def\fillcol{crimson!#4}
|
|
\ifnum#4>50
|
|
\def\textcol{white}
|
|
\else
|
|
\def\textcol{crimson}
|
|
\fi
|
|
\fi
|
|
|
|
\node[
|
|
draw=white,
|
|
line width=0.5pt,
|
|
fill=\fillcol,
|
|
minimum width=4.0cm,
|
|
minimum height=1.1cm,
|
|
anchor=south west,
|
|
rounded corners=0pt,
|
|
inner sep=0pt
|
|
] (box) at (0,#1) {};
|
|
|
|
% Title
|
|
% Font note: \rmfamily for Palatino body-font consistency (see \stacklayer).
|
|
\node[anchor=west, text=\textcol, font=\rmfamily\scriptsize\bfseries]
|
|
at ($(box.west)+(0.2,0.12)$) {#2};
|
|
|
|
% Subtitle
|
|
\node[anchor=west, text=\textcol, font=\rmfamily\fontsize{4.5}{5.5}\selectfont, opacity=0.8]
|
|
at ($(box.west)+(0.2,-0.12)$) {#3};
|
|
|
|
% Icon (positioned on the right)
|
|
\path (box.east) +(-0.5,0) pic[scale=0.8, draw=\textcol, fill=\textcol, text=\textcol] {#5};
|
|
}
|
|
|
|
\newcommand{\mlsysstackfull}[8]{
|
|
\begin{tikzpicture}
|
|
% Stack layers with 1.1cm height and no gap (contiguous)
|
|
|
|
% Layer 7: Applications
|
|
\stacklayerfull{6.60}{Applications}{End-user products, responsible AI}{#7}{icon_applications}
|
|
|
|
% Layer 6: Operations
|
|
\stacklayerfull{5.50}{Operations}{MLOps, monitoring, CI/CD}{#6}{icon_operations}
|
|
|
|
% Layer 5: Serving
|
|
\stacklayerfull{4.40}{Serving}{Inference runtime, deployment}{#5}{icon_serving}
|
|
|
|
% Layer 4: Training
|
|
\stacklayerfull{3.30}{Training}{Training loops, distributed training}{#4}{icon_training}
|
|
|
|
% Layer 3: Models
|
|
\stacklayerfull{2.20}{Models}{Neural network architectures}{#3}{icon_models}
|
|
|
|
% Layer 2: Frameworks
|
|
\stacklayerfull{1.10}{Frameworks}{PyTorch, TensorFlow, compilers}{#2}{icon_frameworks}
|
|
|
|
% Layer 1: Hardware
|
|
\stacklayerfull{0.0}{Hardware}{GPUs, TPUs, accelerators}{#1}{icon_hardware}
|
|
|
|
% --- Data: uniform color bar (same logic as \mlsysstack) ---
|
|
|
|
% Data bar: uniform fill from arg 8 (same logic as \mlsysstack)
|
|
\pgfmathtruncatemacro{\ddata}{#8}
|
|
\ifnum\ddata=0
|
|
\def\databarcol{black!5}
|
|
\else
|
|
\def\databarcol{crimson!\ddata}
|
|
\fi
|
|
|
|
\fill[\databarcol, rounded corners=2pt]
|
|
(4.45, -0.15) rectangle (4.75, 7.85);
|
|
|
|
% Horizontal connectors ("wires") — each colored by its layer's intensity
|
|
\foreach \layerint/\ypos in {#1/0.55, #2/1.65, #3/2.75, #4/3.85, #5/4.95, #6/6.05, #7/7.15} {
|
|
\pgfmathtruncatemacro{\lint}{\layerint}
|
|
\ifnum\lint=0
|
|
\def\wirecol{black!8}
|
|
\else
|
|
\edef\wirecol{crimson!\lint}
|
|
\fi
|
|
\draw[\wirecol, line width=1.5pt] (4.0, \ypos) -- (4.45, \ypos);
|
|
}
|
|
|
|
% "Data" label — color based on data bar intensity for readability
|
|
\ifnum\ddata>50
|
|
\def\datatextcol{white}
|
|
\else
|
|
\ifnum\ddata<10
|
|
\def\datatextcol{black!25}
|
|
\else
|
|
\def\datatextcol{crimson}
|
|
\fi
|
|
\fi
|
|
\node[rotate=90, text=\datatextcol, font=\rmfamily\scriptsize\bfseries]
|
|
at (4.60, 3.85) {Data};
|
|
|
|
\end{tikzpicture}
|
|
}
|
|
|
|
% =============================================================================
|
|
% ML FLEET STACK DIAGRAM (VOLUME 2)
|
|
% =============================================================================
|
|
% Renders the Volume 2 deep stack with configurable shading (0-100).
|
|
% The interface mirrors Volume 1's \mlsysstack: a primary chapter focus is
|
|
% usually 90-100, neighboring/context rows use lower intensities, and inactive
|
|
% rows use 0. The margin stack is capped at 3.15 cm, matching the Volume 1
|
|
% margin-stack width target.
|
|
%
|
|
% Usage:
|
|
% \mlfleetstack{<facility>}{<fabric>}{<execution>}{<control>}
|
|
% {<serving>}{<operations>}{<assurance>}{<governance>}
|
|
% \mlfleetstacknoparts{...same 8 args...}
|
|
% \mlfleetstackfull{...same 8 args...}
|
|
%
|
|
% Stack (bottom to top):
|
|
% Part I: Facility & Accelerators, Fabric & Storage
|
|
% Part II: Distributed Execution, Reliability & Control
|
|
% Part III: Runtime & Serving, Operations
|
|
% Part IV: Assurance, Governance & Sustainability
|
|
|
|
% Toggle for camera-ready margin-width checks. Production default is off.
|
|
\newif\ifMLFleetStackGuides
|
|
\MLFleetStackGuidesfalse
|
|
|
|
% --- Fleet Stack Icons --------------------------------------------------------
|
|
\tikzset{
|
|
icon_fleet_facility/.pic={
|
|
\draw[thick] (-0.24,-0.22) rectangle (0.24,0.22);
|
|
\draw (-0.24,-0.04) -- (0.24,-0.04);
|
|
\foreach \x in {-0.13,0.02,0.17} \fill (\x,0.10) circle (0.023);
|
|
\draw (-0.12,-0.15) -- (0.12,-0.15);
|
|
},
|
|
icon_fleet_fabric/.pic={
|
|
\foreach \p in {(-0.22,0.13),(0.22,0.13),(-0.22,-0.13),(0.22,-0.13)}
|
|
\fill \p circle (0.035);
|
|
\draw[thick] (-0.22,0.13)--(0.22,0.13)--(0.22,-0.13)--(-0.22,-0.13)--cycle;
|
|
\draw[thick] (-0.22,0.13)--(0.22,-0.13);
|
|
\draw[thick] (0.22,0.13)--(-0.22,-0.13);
|
|
},
|
|
icon_fleet_execution/.pic={
|
|
\draw[thick,->] (-0.26,0.10)--(0.24,0.10);
|
|
\draw[thick,->] (0.26,-0.10)--(-0.24,-0.10);
|
|
\draw[thick] (-0.02,-0.20)--(0.02,0.20);
|
|
},
|
|
icon_fleet_control/.pic={
|
|
\draw[thick] (-0.22,-0.16) rectangle (0.22,0.16);
|
|
\draw (-0.13,0.06)--(0.13,0.06);
|
|
\draw[thick,->] (0.12,-0.07) arc (-35:210:0.12);
|
|
},
|
|
icon_fleet_serving/.pic={
|
|
\fill (-0.25,0) circle (0.035);
|
|
\draw[thick] (-0.25,0)--(-0.03,0);
|
|
\draw[thick] (-0.03,0)--(0.24,0.14);
|
|
\draw[thick] (-0.03,0)--(0.24,0);
|
|
\draw[thick] (-0.03,0)--(0.24,-0.14);
|
|
\foreach \p in {(0.24,0.14),(0.24,0),(0.24,-0.14)}
|
|
\fill \p circle (0.027);
|
|
},
|
|
icon_fleet_operations/.pic={
|
|
\draw[thick] (-0.24,-0.16) rectangle (0.24,0.16);
|
|
\draw (-0.18,-0.07)--(-0.07,0.07)--(0.04,-0.02)--(0.16,0.10);
|
|
\draw (-0.08,-0.16)--(-0.08,-0.23);
|
|
\draw (0.08,-0.16)--(0.08,-0.23);
|
|
\draw (-0.15,-0.23)--(0.15,-0.23);
|
|
},
|
|
icon_fleet_assurance/.pic={
|
|
\draw[thick] (0,0.23)--(-0.19,0.12)--(-0.17,-0.05)
|
|
.. controls (-0.14,-0.17) and (0,-0.24) .. (0,-0.24)
|
|
.. controls (0,-0.24) and (0.14,-0.17) .. (0.17,-0.05)
|
|
--(0.19,0.12)--cycle;
|
|
\draw (-0.07,-0.02)--(-0.01,-0.08)--(0.10,0.07);
|
|
},
|
|
icon_fleet_governance/.pic={
|
|
\draw[thick] (0,-0.24)--(0,0.14);
|
|
\draw[thick] (-0.24,0.12)--(0.24,0.12);
|
|
\draw (-0.19,0.12)--(-0.26,-0.02)--(-0.12,-0.02)--cycle;
|
|
\draw (0.19,0.12)--(0.12,-0.02)--(0.26,-0.02)--cycle;
|
|
}
|
|
}
|
|
|
|
\newcommand{\fleetstacksetcolors}[2]{%
|
|
\pgfmathtruncatemacro{\fleetint}{#2}%
|
|
\ifnum\fleetint=0
|
|
\def\fleetfill{black!5}%
|
|
\def\fleettext{black!30}%
|
|
\else
|
|
\edef\fleetfill{#1!\fleetint}%
|
|
\ifnum\fleetint>55
|
|
\def\fleettext{white}%
|
|
\else
|
|
\def\fleettext{#1}%
|
|
\fi
|
|
\fi
|
|
}
|
|
|
|
\newcommand{\fleetstackpartboxmargin}[3]{%
|
|
% #1 y-position, #2 color, #3 Roman numeral
|
|
\draw[#2,line width=0.68pt,rounded corners=1pt]
|
|
(0,#1+0.03) rectangle ++(0.44,1.54);
|
|
\node[font=\rmfamily\fontsize{4.6}{5.0}\selectfont\bfseries,
|
|
text=#2,rotate=90,inner sep=0pt]
|
|
at (0.22,#1+0.80) {Part~#3};
|
|
}
|
|
|
|
\newcommand{\fleetstackpartboxfull}[3]{%
|
|
% #1 y-position, #2 color, #3 Roman numeral
|
|
\draw[#2,line width=0.8pt,rounded corners=1.4pt]
|
|
(0,#1) rectangle ++(1.08,1.68);
|
|
\node[font=\rmfamily\fontsize{8.4}{8.8}\selectfont\bfseries,
|
|
text=#2,rotate=90,inner sep=0pt]
|
|
at (0.54,#1+0.84) {Part~#3};
|
|
}
|
|
|
|
\newcommand{\fleetstacklayermarginparts}[5]{%
|
|
% #1 y, #2 label, #3 intensity, #4 color, #5 icon
|
|
\fleetstacksetcolors{#4}{#3}%
|
|
\node[draw=white,line width=0.45pt,fill=\fleetfill,
|
|
minimum width=2.60cm,minimum height=0.80cm,
|
|
anchor=south west,rounded corners=0pt,inner sep=0pt] (fleetbox) at (0.52,#1) {};
|
|
\node[anchor=west,text=\fleettext,
|
|
font=\rmfamily\fontsize{5.35}{5.75}\selectfont\bfseries]
|
|
at ($(fleetbox.west)+(0.16,0)$) {#2};
|
|
\path (fleetbox.east)+(-0.30,0)
|
|
pic[scale=0.49,draw=\fleettext,fill=\fleettext,text=\fleettext] {#5};
|
|
}
|
|
|
|
\newcommand{\fleetstacklayermarginnoparts}[5]{%
|
|
% #1 y, #2 label, #3 intensity, #4 color, #5 icon
|
|
\fleetstacksetcolors{#4}{#3}%
|
|
\node[draw=white,line width=0.45pt,fill=\fleetfill,
|
|
minimum width=3.12cm,minimum height=0.80cm,
|
|
anchor=south west,rounded corners=0pt,inner sep=0pt] (fleetbox) at (0,#1) {};
|
|
\node[anchor=west,text=\fleettext,
|
|
font=\rmfamily\fontsize{5.75}{6.15}\selectfont\bfseries]
|
|
at ($(fleetbox.west)+(0.16,0)$) {#2};
|
|
\path (fleetbox.east)+(-0.30,0)
|
|
pic[scale=0.52,draw=\fleettext,fill=\fleettext,text=\fleettext] {#5};
|
|
}
|
|
|
|
\newcommand{\fleetstacklayerfull}[6]{%
|
|
% #1 y, #2 title, #3 subtitle, #4 intensity, #5 color, #6 icon
|
|
\fleetstacksetcolors{#5}{#4}%
|
|
\node[draw=white,line width=0.5pt,fill=\fleetfill,
|
|
minimum width=8.05cm,minimum height=0.86cm,
|
|
anchor=south west,rounded corners=0pt,inner sep=0pt] (fleetfullbox) at (1.24,#1) {};
|
|
\node[anchor=west,text=\fleettext,
|
|
font=\rmfamily\fontsize{8.5}{9.1}\selectfont\bfseries]
|
|
at ($(fleetfullbox.west)+(0.22,0.18)$) {#2};
|
|
\node[anchor=west,text=\fleettext,
|
|
font=\rmfamily\fontsize{5.4}{5.9}\selectfont,opacity=0.86]
|
|
at ($(fleetfullbox.west)+(0.22,-0.16)$) {#3};
|
|
\path (fleetfullbox.east)+(-0.48,0)
|
|
pic[scale=0.60,draw=\fleettext,fill=\fleettext,text=\fleettext] {#6};
|
|
}
|
|
|
|
\newcommand{\mlfleetstackwithparts}[8]{%
|
|
\begin{tikzpicture}
|
|
\fleetstackpartboxmargin{0.00}{fleetinfra}{I}
|
|
\fleetstackpartboxmargin{1.60}{fleetdist}{II}
|
|
\fleetstackpartboxmargin{3.20}{fleetserve}{III}
|
|
\fleetstackpartboxmargin{4.80}{fleetgov}{IV}
|
|
|
|
\fleetstacklayermarginparts{0.00}{Facility}{#1}{fleetinfra}{icon_fleet_facility}
|
|
\fleetstacklayermarginparts{0.80}{Fabric}{#2}{fleetinfra}{icon_fleet_fabric}
|
|
\fleetstacklayermarginparts{1.60}{Execution}{#3}{fleetdist}{icon_fleet_execution}
|
|
\fleetstacklayermarginparts{2.40}{Control}{#4}{fleetdist}{icon_fleet_control}
|
|
\fleetstacklayermarginparts{3.20}{Serving}{#5}{fleetserve}{icon_fleet_serving}
|
|
\fleetstacklayermarginparts{4.00}{Operations}{#6}{fleetserve}{icon_fleet_operations}
|
|
\fleetstacklayermarginparts{4.80}{Assurance}{#7}{fleetassure}{icon_fleet_assurance}
|
|
\fleetstacklayermarginparts{5.60}{Governance}{#8}{fleetgov}{icon_fleet_governance}
|
|
|
|
\ifMLFleetStackGuides
|
|
\draw[red!45,line width=0.25pt] (0,-0.06) rectangle (3.15,6.46);
|
|
\draw[red!45,line width=0.25pt] (3.15,-0.11)--(3.15,6.51);
|
|
\fi
|
|
\end{tikzpicture}
|
|
}
|
|
|
|
\newcommand{\mlfleetstacknoparts}[8]{%
|
|
\begin{tikzpicture}
|
|
\fleetstacklayermarginnoparts{0.00}{Facility}{#1}{fleetinfra}{icon_fleet_facility}
|
|
\fleetstacklayermarginnoparts{0.80}{Fabric}{#2}{fleetinfra}{icon_fleet_fabric}
|
|
\fleetstacklayermarginnoparts{1.60}{Execution}{#3}{fleetdist}{icon_fleet_execution}
|
|
\fleetstacklayermarginnoparts{2.40}{Control}{#4}{fleetdist}{icon_fleet_control}
|
|
\fleetstacklayermarginnoparts{3.20}{Serving}{#5}{fleetserve}{icon_fleet_serving}
|
|
\fleetstacklayermarginnoparts{4.00}{Operations}{#6}{fleetserve}{icon_fleet_operations}
|
|
\fleetstacklayermarginnoparts{4.80}{Assurance}{#7}{fleetassure}{icon_fleet_assurance}
|
|
\fleetstacklayermarginnoparts{5.60}{Governance}{#8}{fleetgov}{icon_fleet_governance}
|
|
|
|
\ifMLFleetStackGuides
|
|
\draw[red!45,line width=0.25pt] (0,-0.06) rectangle (3.15,6.46);
|
|
\draw[red!45,line width=0.25pt] (3.15,-0.11)--(3.15,6.51);
|
|
\fi
|
|
\end{tikzpicture}
|
|
}
|
|
|
|
% Default production margin stack: compact D-prime layout with rotated Part boxes.
|
|
\newcommand{\mlfleetstack}[8]{%
|
|
\mlfleetstackwithparts{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}%
|
|
}
|
|
|
|
\newcommand{\mlfleetstackfull}[8]{%
|
|
\begin{tikzpicture}
|
|
\fleetstackpartboxfull{0.00}{fleetinfra}{I}
|
|
\fleetstackpartboxfull{1.72}{fleetdist}{II}
|
|
\fleetstackpartboxfull{3.44}{fleetserve}{III}
|
|
\fleetstackpartboxfull{5.16}{fleetgov}{IV}
|
|
|
|
\fleetstacklayerfull{0.00}{Facility \& Accelerators}{power, cooling, racks, GPUs/TPUs, HBM}{#1}{fleetinfra}{icon_fleet_facility}
|
|
\fleetstacklayerfull{0.86}{Fabric \& Storage}{topology, bandwidth, storage tiers, data movement}{#2}{fleetinfra}{icon_fleet_fabric}
|
|
\fleetstacklayerfull{1.72}{Distributed Execution}{parallelism strategies, collectives, synchronization}{#3}{fleetdist}{icon_fleet_execution}
|
|
\fleetstacklayerfull{2.58}{Reliability \& Control}{checkpointing, recovery, schedulers, placement}{#4}{fleetdist}{icon_fleet_control}
|
|
\fleetstacklayerfull{3.44}{Runtime \& Serving}{kernels, inference, batching, routing, KV cache, edge}{#5}{fleetserve}{icon_fleet_serving}
|
|
\fleetstacklayerfull{4.30}{Operations}{SLOs, monitoring, drift, incidents, lifecycle}{#6}{fleetserve}{icon_fleet_operations}
|
|
\fleetstacklayerfull{5.16}{Assurance}{security, privacy, robustness, risk controls}{#7}{fleetassure}{icon_fleet_assurance}
|
|
\fleetstacklayerfull{6.02}{Governance \& Sustainability}{auditability, policy, carbon budgets, accountable release}{#8}{fleetgov}{icon_fleet_governance}
|
|
\end{tikzpicture}
|
|
}
|
|
|
|
\AtEndDocument{%
|
|
\immediate\closeout\figlatex%
|
|
}
|
|
|
|
\makeatother
|
|
|
|
|
|
% Fallback for \tcbbreak (used by callout-audit PR #1789 to force tcolorbox
|
|
% page-breaks). If a runtime tcolorbox version doesn't define it, no-op so
|
|
% the PDF builds cleanly. See dev commit fee17cc2c0 and downstream merges.
|
|
\providecommand{\tcbbreak}{}
|
|
|
|
|
|
% ─────────────────────────────────────────────────────────────────────────────
|
|
% MARGIN ALIGNMENT GUIDES (development aid — toggle)
|
|
% Draws light frames around the text block, header/footer, and the margin-note
|
|
% column, so margin figures can be aligned during authoring.
|
|
% Set \MarginDebugfalse for production builds; \MarginDebugtrue to show guides.
|
|
% ─────────────────────────────────────────────────────────────────────────────
|
|
\newif\ifMarginDebug
|
|
\MarginDebugfalse% <<< set to \MarginDebugtrue to show margin alignment guides
|
|
\ifMarginDebug
|
|
\usepackage{showframe}
|
|
\renewcommand*\ShowFrameLinethickness{0.2pt}
|
|
\renewcommand*\ShowFrameColor{\color{red!45}}
|
|
\fi |