% \iffalse meta-comment
%
% causalmodels.dtx
%
% Copyright (C) 2026 by Alex Markham <alex.markham@causal.dev>
%
% This work may be distributed and/or modified under the conditions of
% the LaTeX Project Public License, either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in https://www.latex-project.org/lppl.txt and
% version 1.3c or later is part of all distributions of LaTeX version
% 2005/12/01 or later.
%
% This work has the LPPL maintenance status 'author-maintained'.
%
% The Current Maintainer of this work is Alex Markham.
%
% This work consists of the files causalmodels.dtx, causalmodels.ins, and
% causalmodels.bib, and the derived files causalmodels.sty,
% causalmodels-doc.tex, and causalmodels-doc.pdf.
%
%<*driver>
\ProvidesFile{causalmodels.dtx}
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
\definecolor{causaldevpurple}{HTML}{7C4DFF}
\definecolor{causaldevgreen}{HTML}{43A047}
\usepackage{causalmodels}
\usepackage{amssymb}
\usetikzlibrary{positioning}
\usepackage[most]{tcolorbox}
\usepackage[numbers]{natbib}
\usepackage[hyperindex=false,colorlinks=true,linkcolor=causaldevpurple,%
	citecolor=causaldevpurple,urlcolor=causaldevpurple]{hyperref}
\newcommand{\doi}[1]{\href{https://doi.org/#1}{doi:~#1}}
\EnableCrossrefs
\RecordChanges
\begin{document}
\DocInput{causalmodels.dtx}
\PrintChanges
\end{document}
%</driver>
% \fi
%
% \changes{v1.0.0}{2026/08/22}{Initial release}
%
% \GetFileInfo{causalmodels.sty}
%
% \title{The \textsf{causalmodels} package}
% \author{Alex Markham \\ \texttt{alex.markham@causal.dev}}
% \date{\filedate\ \fileversion}
%
% \newcommand{\doccolsep}{@{\hspace{3em}}}
%
% \maketitle
%
% \begin{tcolorbox}[breakable, title=Quickstart, colframe=causaldevgreen,
%   colback=causaldevgreen!8, colbacktitle=causaldevgreen, coltitle=white]
% Loading the package with \verb|\usepackage{causalmodels}| provides
% macros for common operators, relations, and edges.  For example,
% some common operators include
% \begin{center}
% \begin{tabular}{rl \doccolsep rl}
% $\pa{u}$   & \verb|\pa{u}|   & $\ch{u}$ & \verb|\ch{u}| \\
% $\nei{u}$ & \verb|\nei{u}| & $\doo{X}$   & \verb|\doo{X}|,
% \end{tabular}
% \end{center}
% separation relations include
% \begin{center}
% \begin{tabular}{rl \doccolsep rl}
% $\indep{X}{Y}{}$ & \verb|\indep{X}{Y}{}| & $\nindep{X}{Y}{Z}$ & \verb|\nindep{X}{Y}{Z}|,
% \end{tabular}
% \end{center}
% and edge types include
% \begin{center}
% \begin{tabular}{rl \doccolsep rl}
% $u \undir v$ & \verb|u \undir v| & $u \rightdir v$ & \verb|u \rightdir v| \\
% $u \leftdir v$ & \verb|u \leftdir v| & $u \bidir v$ & \verb|u \bidir v|.
% \end{tabular}
% \end{center}
% See Section~\ref{sec:usage} for more macros and usage details.
% \end{tcolorbox}
%
% \tableofcontents
%
% \section{Introduction}
%
% This package is a collection of macros for notation and symbols
% commonly used in the causal graphical models literature.  On the one
% hand, these macros are relatively simply built from tools in
% \textsf{amsmath} and \textsf{PGF/TikZ}.  On the other hand, I find
% myself redefining these macros almost every time I start a new
% \LaTeX document, and I regularly read new papers that (should) do
% the same, so I expect collecting them into a single \TeX package to
% be useful nevertheless.
% 
% Besides typesetting common operators like $\pa[\mathcal{G}]{u}$
% properly using \textsf{amsmath}'s \verb|\operatorname|---which is
% subtly different from using \verb|$\mathrm{pa}$| and more noticeably
% so from plain \verb|$pa$|---this package makes three modest
% innovations: it uses \textsf{PGF/TikZ} to define (i) a well-behaved
% independence symbol ($\indep{}{}{}$) without the issues of other
% approaches\footnote{For example, approaches suggested at
% \url{https://tex.stackexchange.com/q/719657} tend to require using
% other fonts and can ignore scaling of surrounding math text; and the
% overlapping \texttt{\textbackslash perp} approach discussed at
% \url{https://tex.stackexchange.com/q/79434} and in the
% \textsf{comprehensive} package documentation at
% \url{https://ctan.org/pkg/comprehensive}, with attribution to a post
% by Donald Arseneau on \texttt{comp.text.tex} in June 2000, produces
% a slightly thicker stroke weight where the symbols overlap.} and
% (ii) a set of edges with uniform width when used inline (like
% $\tailhead$ and $\circhead$), and it (iii) provides two macros for
% simply and consistently defining new operators and edges.
% 
% If you find yourself regularly redefining a macro because it is not
% in this package---or modifying one that is part of this
% package---please send me an
% email\footnote{\href{mailto:alex.markham@causal.dev?subject=causalatex}{\texttt{alex.markham@causal.dev}}}
% or open an issue/make a pull
% request\footnote{\href{https://codeberg.org/alex-markham/causalatex}{\texttt{https://codeberg.org/alex-markham/causalatex}}}
% describing it.
%
% \section{Usage}
% \label{sec:usage}
%
% This section covers the package's four macro families---graph
% operators, the do-operator, separation relations, and edge
% marks---after loading it:
% \begin{verbatim}
% \usepackage{causalmodels}
% \end{verbatim}
% It requires \textsf{amsmath}, \textsf{tikz} (with the
% \textsf{arrows.meta} library), and \textsf{centernot}.
%
% \subsection{Graph operators}
%
% Each of the eleven graph operators below (e.g., \cs{pa}) shares one
% syntax,
% \begin{quote}
% \meta{op}[\meta{graph}]\{\meta{vertex}\},
% \end{quote}
% which is unary and prefix, takes a vertex (set) as its argument,
% plus an optional leading subscript (any graph label, e.g.,
% \verb|\pa[G]{u}|) to disambiguate between multiple graphs:
% \begin{center}
% \begin{tabular}{rl \doccolsep rl \doccolsep rl}
% $\pa{u}$ & \verb|\pa{u}| & $\ch{u}$ & \verb|\ch{u}| & $\an{u}$ & \verb|\an{u}| \\
% $\de{u}$ & \verb|\de{u}| & $\nd{u}$ & \verb|\nd{u}| & $\mb{u}$ & \verb|\mb{u}| \\
% $\nei{u}$ & \verb|\nei{u}| & $\spo{u}$ & \verb|\spo{u}| & $\dis{u}$ & \verb|\dis{u}| \\
% $\ant{u}$ & \verb|\ant{u}| & $\cc{u}$ & \verb|\cc{u}| & &
% \end{tabular}
% \end{center}
% In addition to the usual \cs{nei} (neighbors), \cs{pa} (parents),
% \cs{ch} (children), \cs{an} (ancestors), and \cs{de} (descendants),
% we have \cs{nd} (non-descendants) and \cs{mb} (Markov blanket)
% \citep{pearl1988}, \cs{spo} (spouse) and \cs{ant} (anterior)
% \citep{richardsonspirtes2002}, \cs{dis} (district)
% \citep{richardson2003}, and \cs{cc} (chain component)
% \citep{anderssonmadiganperlman1997}.
%
% For an operator not named above,
% \cs{newgraphop}\{\meta{macro}\}\{\meta{name}\} defines \meta{macro}
% as a new operator, with the same syntax as above, that displays as
% \meta{name}: \verb|\newgraphop{\eg}{eg}| makes \verb|\eg[G]{u}|
% available.
%
% \subsection{The do-operator}
%
% Pearl's $do(\cdot)$ notation \citep{pearl1995} is typeset with
% \cs{doo}\{\meta{variable}\}, which is unary, prefix, and takes no
% optional argument:
% \begin{center}
% \begin{tabular}{ll}
% $\doo{X}$ & \verb|\doo{X}| \\
% \end{tabular}
% \end{center}
%
% \subsection{Separation relations}
%
% Each of the four separation relations below (e.g., \cs{sep}) shares
% one syntax,
% \begin{quote}
% \meta{relation}[\meta{sub}]\{\meta{X}\}\{\meta{Y}\}\{\meta{Z}\},
% \end{quote}
% which is ternary and prefix, asserting that \meta{X} and \meta{Y}
% are (conditionally) separated given \meta{Z} \citep{pearl1988}.  An
% optional leading subscript names the distribution, graph, or
% criterion it's relative to, e.g., \verb|\indep[P]{X}{Y}{Z}|, or
% using \verb|m| or \verb|\sigma| as \meta{sub} in \cs{sep} to denote
% m-separation \citep{richardsonspirtes2002} or $\sigma$-separation
% \citep{forremooij2017}.  Leaving \meta{Z} empty (\verb|{}|) gives
% the unconditional form, omitting the conditioning bar entirely.
%
% \begin{center}
% \begin{tabular}{rl \doccolsep rl}
% $\indep{X}{Y}{Z}$ & \verb|\indep{X}{Y}{Z}| & $\sep{u}{v}{w}$ & \verb|\sep{u}{v}{w}| \\
% $\nindep{X}{Y}{Z}$ & \verb|\nindep{X}{Y}{Z}| & $\nsep{u}{v}{w}$ & \verb|\nsep{u}{v}{w}|
% \end{tabular}
% \end{center}
%
% \subsection{Edge marks}
% \label{sec:usage-edges}
%
% Edge marks (used across DAGs \citep{pearl1988}, CPDAGs
% \citep{anderssonmadiganperlman1997}, MPDAGs
% \citep{perkovic2020}, ADMGs \citep{richardson2003}, ancestral
% graphs \citep{richardsonspirtes2002}, and PAGs
% \citep{spirtesmeekrichardson1999})
% use \meta{u} \meta{name} \meta{v}, which is binary, infix notation,
% built from four end marks at each end, so there are $4^2$ different
% marks:
% \begin{center}
% \begin{tabular}{rl \doccolsep rl}
% $u \tailtail v$ & \verb|u \tailtail v| & $u \tailhead v$ & \verb|u \tailhead v| \\
% $u \tailcirc v$ & \verb|u \tailcirc v| & $u \tailwild v$ & \verb|u \tailwild v| \\
% $u \headtail v$ & \verb|u \headtail v| & $u \headhead v$ & \verb|u \headhead v| \\
% $u \headcirc v$ & \verb|u \headcirc v| & $u \headwild v$ & \verb|u \headwild v| \\
% $u \circtail v$ & \verb|u \circtail v| & $u \circhead v$ & \verb|u \circhead v| \\
% $u \circcirc v$ & \verb|u \circcirc v| & $u \circwild v$ & \verb|u \circwild v| \\
% $u \wildtail v$ & \verb|u \wildtail v| & $u \wildhead v$ & \verb|u \wildhead v| \\
% $u \wildcirc v$ & \verb|u \wildcirc v| & $u \wildwild v$ & \verb|u \wildwild v|
% \end{tabular}
% \end{center}
% Four of the sixteen also have short, colloquial aliases---either
% name draws the same edge:
% \begin{center}
% \begin{tabular}{rrcl}
% $u \undir v$ & \verb|u \undir v| & or & \verb|u \tailtail v| \\
% $u \rightdir v$ & \verb|u \rightdir v| & or & \verb|u \tailhead v| \\
% $u \leftdir v$ & \verb|u \leftdir v| & or & \verb|u \headtail v| \\
% $u \bidir v$ & \verb|u \bidir v| & or & \verb|u \headhead v|
% \end{tabular}
% \end{center}
%
% Every edge mark above also has a matching
% \texttt{causalmodels/\meta{name}} \textsf{TikZ} style, for drawing
% edges between arbitrarily-positioned nodes in a real
% \texttt{tikzpicture} rather than typesetting a fixed-length inline
% glyph:
% \begin{verbatim}
% \usetikzlibrary{positioning}
% \begin{tikzpicture}
%   \node (u) {$u$};
%   \node (v) [right=1.5cm of u] {$v$};
%   \draw[causalmodels/circhead] (u) -- (v);
% \end{tikzpicture}
% \end{verbatim}
% See Section~\ref{sec:diagram-styles} for the full set of style
% names.
%
% Arrow length and width---for both inline glyphs and diagram
% styles---are configurable via
% \cs{causalmodelsset}\{arrow-length=\meta{len},
% arrow-width=\meta{wid}\}.  For an edge type not named above,
% \cs{mkedge}\{\meta{arrows.meta spec}\} builds one directly, e.g.,
% \verb|\mkedge{->}| is exactly \cs{rightdir}.
%
% \section{Implementation}
%
% This section documents how each macro from Section~\ref{sec:usage}
% is built.  It also covers \cs{causalmodelsset}, plus \cs{newgraphop}
% and \cs{mkedge}, the helpers for custom operators and edge types.
%
%    \begin{macrocode}
%<*package>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{causalmodels}%
[2026/08/22 v1.0.0 Notation macros for causal graphical models]
%</package>
%    \end{macrocode}
%
% \subsection{Dependencies}
%
% \textsf{amsmath} provides \cs{operatorname} and \cs{mathrel}, used
% throughout the graph operators, do-operator, and separation
% relations.  \textsf{tikz} draws every edge glyph and diagram style;
% \textsf{arrows.meta} specifically supplies the circle and wildcard
% tip shapes (\texttt{\{Circle[open]\}}, \texttt{\{Rays[n=7]\}}) used
% by the edge marks (Section~\ref{sec:edges}):
%    \begin{macrocode}
%<*package>
\RequirePackage{amsmath}
\RequirePackage{tikz}
\usetikzlibrary{arrows.meta}
%</package>
%    \end{macrocode}
% \cs{centernot} is needed for \cs{nindep}'s negation slash: plain
% \cs{not} sizes and positions its slash assuming a normal
% single-character-width symbol, and lands off-center on \cs{indep}'s
% wider hand-drawn glyph (Section~\ref{sec:sepop}).  \cs{centernot}
% measures the actual width of its argument and centers accordingly:
%    \begin{macrocode}
%<*package>
\RequirePackage{centernot}
%</package>
%    \end{macrocode}
%
% \subsection{Graph operators}
% \label{sec:graphops}
%
% \DescribeMacro{\pa}
% \DescribeMacro{\ch}
% \DescribeMacro{\an}
% \DescribeMacro{\de}
% \DescribeMacro{\nd}
% \DescribeMacro{\mb}
% \DescribeMacro{\nei}
% \DescribeMacro{\spo}
% \DescribeMacro{\dis}
% \DescribeMacro{\ant}
% \DescribeMacro{\cc}
% All eleven graph operators share \cs{causalmodels@graphop}, which
% takes an operator name, an optional leading subscript, and one
% required argument.
%
% \cs{nei}, not \cs{ne}: \cs{ne} is already \textsf{amsmath}'s ``not
% equal'' ($\ne$)---only the callable name avoids the collision; it
% still typesets ``ne'' (\cs{operatorname}\{ne\}).  Likewise \cs{spo},
% not \cs{sp}: \cs{sp} is already plain \TeX's superscript primitive
% (\verb|^|).  It still typesets ``sp'' (\cs{operatorname}\{sp\}).
%    \begin{macrocode}
%<*package>
\newcommand{\causalmodels@graphop}[3]{%
	\def\causalmodels@graphopsub{#2}%
	\operatorname{#1}\ifx\causalmodels@graphopsub\@empty\else_{#2}\fi(#3)%
}
\newcommand{\pa}[2][]{\causalmodels@graphop{pa}{#1}{#2}}
\newcommand{\ch}[2][]{\causalmodels@graphop{ch}{#1}{#2}}
\newcommand{\an}[2][]{\causalmodels@graphop{an}{#1}{#2}}
\newcommand{\de}[2][]{\causalmodels@graphop{de}{#1}{#2}}
\newcommand{\nd}[2][]{\causalmodels@graphop{nd}{#1}{#2}}
\newcommand{\mb}[2][]{\causalmodels@graphop{mb}{#1}{#2}}
\newcommand{\nei}[2][]{\causalmodels@graphop{ne}{#1}{#2}}
\newcommand{\spo}[2][]{\causalmodels@graphop{sp}{#1}{#2}}
\newcommand{\dis}[2][]{\causalmodels@graphop{dis}{#1}{#2}}
\newcommand{\ant}[2][]{\causalmodels@graphop{ant}{#1}{#2}}
\newcommand{\cc}[2][]{\causalmodels@graphop{cc}{#1}{#2}}
%</package>
%    \end{macrocode}
%
% \DescribeMacro{\newgraphop}
% \cs{newgraphop}\{\meta{macro}\}\{\meta{name}\} defines a new graph
% operator, for one this package doesn't already name: \meta{macro}
% is the macro it defines, and \meta{name} is the string
% \cs{operatorname} displays.  \cs{newgraphop}\{\cs{eg}\}\{eg\}
% makes \verb|\eg[G]{u}| available, built the same way \cs{pa} is.
%    \begin{macrocode}
%<*package>
\newcommand{\newgraphop}[2]{%
	\newcommand{#1}[2][]{\causalmodels@graphop{#2}{##1}{##2}}%
}
%</package>
%    \end{macrocode}
%
% \subsection{The do-operator}
% \label{sec:doo}
%
% Unlike the graph operators and separation relations, \cs{doo} needs
% no shared helper---it's a single \cs{operatorname} call:
% \DescribeMacro{\doo}
%    \begin{macrocode}
%<*package>
\newcommand{\doo}[1]{\operatorname{do}(#1)}
%</package>
%    \end{macrocode}
%
% \subsection{Separation relations}
% \label{sec:sepop}
%
% \DescribeMacro{\indep}
% \DescribeMacro{\nindep}
% \DescribeMacro{\sep}
% \DescribeMacro{\nsep}
% \cs{indep}, \cs{nindep}, \cs{sep}, and \cs{nsep} all share
% \cs{causalmodels@sepop}, which takes a glyph, an optional leading
% subscript, and three required arguments---the third left empty omits
% the ``\cs{mid}''.
%
% \cs{indep}'s glyph is built the same way $\vDash$ relates to
% $\vdash$: $\vdash$ is a single vertical spine with one centered
% horizontal tick; $\vDash$ is the same spine with two horizontal
% ticks straddling that center.  \cs{indep} applies that to $\perp$:
% its horizontal bar, with the one centered vertical tick replaced by
% two ticks straddling the same center, at the same offset ratio
% (measured from \TeX's own $\vdash$/$\vDash$ font outlines).  The
% glyph is drawn directly from $\perp$'s own measured dimensions,
% remeasured on every use, so it tracks the surrounding font size,
% math style, and whatever math font is loaded.
%    \begin{macrocode}
%<*package>
\newcommand{\causalmodels@sepop}[5]{%
	\def\causalmodels@sepopsub{#2}%
	\def\causalmodels@sepopz{#5}%
	#3 \mathrel{#1\ifx\causalmodels@sepopsub\@empty\else_{#2}\fi} #4%
	\ifx\causalmodels@sepopz\@empty\else\mid #5\fi
}
\newsavebox{\causalmodels@perpbox}
\newlength{\causalmodels@perpht}
\newlength{\causalmodels@perpwd}
\newlength{\causalmodels@indeptickoffset}
\newlength{\causalmodels@indepbarmid}
\newlength{\causalmodels@indeptick}
\newcommand{\causalmodels@indeptickoffsetratio}{0.1398}
\newcommand{\causalmodels@indepstrokewidth}{0.04em}
\newcommand{\causalmodels@indepstyled}[2]{%
	\sbox{\causalmodels@perpbox}{$#1\perp$}%
	\settoheight{\causalmodels@perpht}{\usebox{\causalmodels@perpbox}}%
	\settowidth{\causalmodels@perpwd}{\usebox{\causalmodels@perpbox}}%
	\pgfmathsetlength{\causalmodels@indeptickoffset}%
	{\causalmodels@indeptickoffsetratio*\causalmodels@perpwd}%
	\pgfmathsetlength{\causalmodels@indepbarmid}{0.5\causalmodels@perpwd}%
	\mathrel{\tikz[baseline=0pt]{%
			\draw[line width=\causalmodels@indepstrokewidth]%
			(0pt,0pt) -- (\causalmodels@perpwd,0pt);%
			\pgfmathsetlength{\causalmodels@indeptick}%
			{\causalmodels@indepbarmid-\causalmodels@indeptickoffset}%
			\draw[line width=\causalmodels@indepstrokewidth]%
			(\causalmodels@indeptick,0pt) --%
			(\causalmodels@indeptick,\causalmodels@perpht);%
			\pgfmathsetlength{\causalmodels@indeptick}%
			{\causalmodels@indepbarmid+\causalmodels@indeptickoffset}%
			\draw[line width=\causalmodels@indepstrokewidth]%
			(\causalmodels@indeptick,0pt) --%
			(\causalmodels@indeptick,\causalmodels@perpht);%
		}}%
}
\newcommand{\causalmodels@indepglyph}%
{\mathpalette\causalmodels@indepstyled\relax}
\newcommand{\causalmodels@nindepglyph}%
{\centernot{\causalmodels@indepglyph}}
\newcommand{\causalmodels@nsepglyph}{\centernot{\perp}}
\newcommand{\indep}[4][]%
{\causalmodels@sepop{\causalmodels@indepglyph}{#1}{#2}{#3}{#4}}
\newcommand{\nindep}[4][]%
{\causalmodels@sepop{\causalmodels@nindepglyph}{#1}{#2}{#3}{#4}}
\newcommand{\sep}[4][]{\causalmodels@sepop{\perp}{#1}{#2}{#3}{#4}}
\newcommand{\nsep}[4][]%
{\causalmodels@sepop{\causalmodels@nsepglyph}{#1}{#2}{#3}{#4}}
%</package>
%    \end{macrocode}
%
% \subsection{Configuration: \cs{causalmodelsset}}
%
% \DescribeMacro{\causalmodelsset}
% Its \texttt{arrow-length} and \texttt{arrow-width} keys resolve
% where the edge is actually drawn, not where \cs{causalmodelsset} is
% called, so they always match its surrounding font size:
% \begin{center}
%   {\normalsize $u \rightdir v \bidir w \circhead x$} \\[4pt]
%   {\LARGE $u \rightdir v \bidir w \circhead x$}
% \end{center}
%    \begin{macrocode}
%<*package>
\newcommand{\causalmodels@arrowlength}{2.5ex}
\newcommand{\causalmodels@arrowwidth}{0.045em}
\pgfkeys{
	/causalmodels/.cd,
	arrow-length/.store in=\causalmodels@arrowlength,
	arrow-width/.store in=\causalmodels@arrowwidth,
}
\newcommand{\causalmodelsset}[1]{\pgfkeys{/causalmodels/.cd,#1}}
%</package>
%    \end{macrocode}
%
% \subsection{The \cs{mkedge} helper}
%
% \DescribeMacro{\mkedge}
% Every edge mark below is built from \cs{mkedge}\{\meta{arrows.meta
% spec}\}: a short \textsf{TikZ} line with that tip decoration,
% wrapped as an inline math relation.
%    \begin{macrocode}
%<*package>
\newcommand{\causalmodels@mkedge}[1]{%
	\mathrel{\tikz[baseline=-0.5ex]{%
			\draw[line width=\causalmodels@arrowwidth,#1]%
			(0,0) -- (\causalmodels@arrowlength,0);%
		}}%
}
\newcommand{\mkedge}[1]{\ensuremath{\causalmodels@mkedge{#1}}}
%</package>
%    \end{macrocode}
%
% \cs{causalmodels@defedge}\{name\}\{spec\} defines both the inline
% glyph and the matching \texttt{causalmodels/name} diagram style
% (Section~\ref{sec:diagram-styles}) from one spec.
%    \begin{macrocode}
%<*package>
\newcommand{\causalmodels@defedge}[2]{%
	\expandafter\newcommand\csname #1\endcsname{\mkedge{#2}}%
	\tikzset{causalmodels/#1/.style={#2,line width=\causalmodels@arrowwidth}}%
}
%</package>
%    \end{macrocode}
%
% \subsection{Edge marks}
% \label{sec:edges}
%
% Every edge mark, regardless of how many marks decorate its ends,
% spans the same tip-to-tip width, so a plain \cs{undir} line and a
% doubly-decorated \cs{wildwild} line drawn to the same length look
% the same length, even though \cs{wildwild}'s decorations eat into
% more of that span.  Every edge mark works in text and math mode.
%
% Every edge is named compositionally, left-to-right, from a fixed
% vocabulary: \texttt{tail} (a plain line end), \texttt{head} (an
% arrowhead), \texttt{circ}, and \texttt{wild} (a wildcard mark,
% standing in for any of the other three).
%
% \DescribeMacro{\tailtail}
% \DescribeMacro{\tailhead}
% \DescribeMacro{\headtail}
% \DescribeMacro{\headhead}
% \DescribeMacro{\tailcirc}
% \DescribeMacro{\tailwild}
% \DescribeMacro{\headcirc}
% \DescribeMacro{\headwild}
% \DescribeMacro{\circtail}
% \DescribeMacro{\circhead}
% \DescribeMacro{\circcirc}
% \DescribeMacro{\circwild}
% \DescribeMacro{\wildtail}
% \DescribeMacro{\wildhead}
% \DescribeMacro{\wildcirc}
% \DescribeMacro{\wildwild}
% For example, \cs{circhead} is circle-then-right-arrow and
% \cs{headcirc} is left-arrow-then-circle.  Sixteen edges in total:
% every pairing of the four end marks (tail, head, circ, wild) at the
% two ends of the edge, $4^2 = 16$.
%    \begin{macrocode}
%<*package>
\causalmodels@defedge{tailtail}{-}
\causalmodels@defedge{tailhead}{->}
\causalmodels@defedge{headtail}{<-}
\causalmodels@defedge{headhead}{<->}
\causalmodels@defedge{tailcirc}{-{Circle[open]}}
\causalmodels@defedge{tailwild}{-{Rays[n=7]}}
\causalmodels@defedge{headcirc}{<-{Circle[open]}}
\causalmodels@defedge{headwild}{<-{Rays[n=7]}}
\causalmodels@defedge{circtail}{{Circle[open]}-}
\causalmodels@defedge{circhead}{{Circle[open]}->}
\causalmodels@defedge{circcirc}{{Circle[open]}-{Circle[open]}}
\causalmodels@defedge{circwild}{{Circle[open]}-{Rays[n=7]}}
\causalmodels@defedge{wildtail}{{Rays[n=7]}-}
\causalmodels@defedge{wildhead}{{Rays[n=7]}-{>}}
\causalmodels@defedge{wildcirc}{{Rays[n=7]}-{Circle[open]}}
\causalmodels@defedge{wildwild}{{Rays[n=7]}-{Rays[n=7]}}
%    \end{macrocode}
%
% \DescribeMacro{\undir}
% \DescribeMacro{\rightdir}
% \DescribeMacro{\leftdir}
% \DescribeMacro{\bidir}
% Four of the sixteen also get short, colloquial aliases ending in
% \texttt{dir}---exactly equivalent to the names above: \cs{undir},
% \cs{rightdir}, \cs{leftdir}, \cs{bidir}.
%    \begin{macrocode}
\let\undir\tailtail
\let\rightdir\tailhead
\let\leftdir\headtail
\let\bidir\headhead
%</package>
%    \end{macrocode}
%
% \subsection{Diagram styles}
% \label{sec:diagram-styles}
%
% The edge marks above are complete, self-contained inline glyphs, not
% path styles, so they cannot be dropped into \texttt{\cs{draw} (u) --
% (v);} inside a real \texttt{tikzpicture} to connect two
% arbitrarily-positioned nodes.  The styles below, namespaced under
% \texttt{causalmodels/}, expose the same arrow-tip specs and
% configurable line width instead (\cs{causalmodelsset} affects diagrams
% and inline glyphs together, so a figure can match a paper's inline
% notation exactly).
%
% One style exists per edge mark above (including the four colloquial
% aliases), by the same name: \texttt{causalmodels/\allowbreak
% tailhead}, \texttt{causalmodels/\allowbreak circhead}, \dots.  The
% sixteen non-alias styles are defined alongside their inline macros
% in Section~\ref{sec:edges}, via \cs{causalmodels@defedge}; only the
% four alias styles below are defined directly here.  Diagram styles
% deliberately don't include arrow length---unlike the inline glyphs,
% diagram edges span whatever distance node positions dictate.
% Compare against the inline glyphs directly: $u \circhead v$,
% $u \tailhead w$, $v \wildwild w$.
% \begin{center}
% \begin{tikzpicture}
% \node (u) {$u$};
% \node (v) [right=1.5cm of u] {$v$};
% \node (w) [below=1cm of v] {$w$};
% \draw[causalmodels/circhead] (u) -- (v);
% \draw[causalmodels/tailhead] (u) -- (w);
% \draw[causalmodels/wildwild] (v) -- (w);
% \end{tikzpicture}
% \end{center}
% Alias styles work the same way.
%    \begin{macrocode}
%<*package>
\tikzset{
	causalmodels/undir/.style={causalmodels/tailtail},
	causalmodels/rightdir/.style={causalmodels/tailhead},
	causalmodels/leftdir/.style={causalmodels/headtail},
	causalmodels/bidir/.style={causalmodels/headhead},
}
%</package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*package>
\endinput
%</package>
%    \end{macrocode}
%
% \bibliographystyle{plainnat}
% \bibliography{causalmodels}
%
% \Finale

% \endinput
