Compare commits

...

7 Commits

Author SHA1 Message Date
Georges Dupéron
f110a36916 Use a recent version of TeX Live for the Travis-CI build. 2017-08-18 11:22:29 +02:00
OanaAndreescu
1e15ba95f5 Merge pull request #2 from jsmaniac/georges-travis-ci
Automatic builds of the LaTeX file on travis-ci, etc.
2017-08-17 23:53:03 +02:00
Georges Dupéron
6f02242bbb Automatic builds of the LaTeX file on travis-ci, and automatic deployment from my fork. Added dependency on lmodern and stmaryrd packages. Upgraded pgf and pgfplots. Used -halt-on-error -interaction=nonstopmode . 2017-08-17 23:50:33 +02:00
Georges Dupéron
d1970c9a83 Created the README file 2017-08-17 23:45:30 +02:00
Jensen
ca127548e1 nits 2017-08-17 18:06:59 +02:00
Jensen
ea6f4ec8b9 nits 2017-08-17 16:57:35 +02:00
Jensen
20355f9c01 correlation section started 2017-08-17 16:48:43 +02:00
21 changed files with 9914 additions and 8 deletions

2
.gitignore vendored
View File

@ -7,3 +7,5 @@
*.out
*.toc
*.lof
travis-deploy-key-id_rsa
travis-deploy-key-id_rsa.pub

31
.travis.yml Normal file
View File

@ -0,0 +1,31 @@
language: c
sudo: false
env:
- PATH="$HOME/texlive/bin/x86_64-linux:$PATH"
before_install:
- true
install:
- echo "Installing LaTeX and LaTeX packages."
- curl -L -o texlive.tar.gz https://github.com/yihui/ubuntu-bin/releases/download/latest/texlive.tar.gz
- tar -C "$HOME/" -zxf texlive.tar.gz
- tlmgr update --self
- tlmgr install newunicodechar mathpartir pgf pgfplots bera float cancel pgfopts elocalloc environ savesym bbding wasy wasysym epigraph
- echo "Finished installing LaTeX and LaTeX packages."
# ################## #
# Actual LaTeX build #
# ################## #
- pdflatex -halt-on-error -interaction=nonstopmode main.tex
- bibtex main
- pdflatex -halt-on-error -interaction=nonstopmode main.tex
- pdflatex -halt-on-error -interaction=nonstopmode main.tex
- pdflatex -halt-on-error -interaction=nonstopmode main.tex
# ################## #
# End of LaTeX build #
# ################## #
- bash ./auto-push-gh-pages.sh
script:
- true

8
README.md Normal file
View File

@ -0,0 +1,8 @@
[![Build Status,](https://img.shields.io/travis/jsmaniac/journal-article/master.svg)](https://travis-ci.org/jsmaniac/journal-article)
[![Build Stats,](https://img.shields.io/website-stats-stats%20unavailable-blue-red/https/jsmaniac.github.io/travis-stats/.svg?label=build)](http://jsmaniac.github.io/travis-stats/#jsmaniac/journal-article)
[![Try our Tool Online](https://img.shields.io/website-online-currently%20unavailable-blue-red/http/ajl-demo.fr/2016/.svg?label=try%20our%20tool)](http://ajl-demo.fr/2016/)
[![Read Online (PDF)](https://img.shields.io/website-PDF-PDF%20unavailable-blue-red/https/jsmaniac.github.io/journal-article-gh-pages/main.pdf.svg?label=read%20online)](https://jsmaniac.github.io/journal-article-gh-pages/main.pdf)
# journal-article
This repository contains the LaTeX code for our upcoming journal article.

50
auto-push-gh-pages.sh Executable file
View File

@ -0,0 +1,50 @@
#!/bin/sh
set -e
set +x
if test "$(git config remote.origin.url)" != "https://github.com/jsmaniac/journal-article.git"; then
echo "Not on official repo, will not deploy gh-pages."
elif test "$TRAVIS_PULL_REQUEST" != "false"; then
echo "This is a Pull Request, will not deploy gh-pages."
elif test "$TRAVIS_BRANCH" != "master"; then
echo "Not on master branch (TRAVIS_BRANCH = $TRAVIS_BRANCH), will not deploy gh-pages."
# A key can be created following the steps at https://docs.travis-ci.com/user/encrypting-files/ .
# ssh-keygen -f travis-deploy-key-id_rsa -C 'Deploy key for travis-ci'
# travis encrypt-file travis-deploy-key-id_rsa
elif test -z "${encrypted_264397dfc790_key:-}" -o -z "${encrypted_264397dfc790_iv:-}"; then
echo "Travis CI secure environment variables are unavailable, will not deploy gh-pages."
else
set -x
echo "Automatic push to gh-pages"
# Git configuration:
git config --global user.name "$(git log --format="%aN" HEAD -1) (Travis CI automatic commit)"
git config --global user.email "$(git log --format="%aE" HEAD -1)"
# SSH configuration
mkdir -p ~/.ssh
chmod 700 ~/.ssh
set +x
if openssl aes-256-cbc -K $encrypted_264397dfc790_key -iv $encrypted_264397dfc790_iv -in travis-deploy-key-id_rsa.enc -out travis-deploy-key-id_rsa -d >/dev/null 2>&1; then
echo "Decrypted key successfully."
else
echo "Error while decrypting key."
fi
mv travis-deploy-key-id_rsa ~/.ssh/travis-deploy-key-id_rsa
set -x
chmod 600 ~/.ssh/travis-deploy-key-id_rsa
set +x
eval `ssh-agent -s`
set -x
ssh-add ~/.ssh/travis-deploy-key-id_rsa
TRAVIS_GH_PAGES_DIR="$HOME/travis-gh-pages-$(date +%s)"
if test -e $TRAVIS_GH_PAGES_DIR; then rm -rf $TRAVIS_GH_PAGES_DIR; fi
mkdir -p "$TRAVIS_GH_PAGES_DIR"
mv -i main.pdf $TRAVIS_GH_PAGES_DIR/main.pdf
git init $TRAVIS_GH_PAGES_DIR
touch $TRAVIS_GH_PAGES_DIR/.nojekyll
(cd $TRAVIS_GH_PAGES_DIR && git add -A . && git commit -m "Auto-publish to gh-pages") > commit.log || (cat commit.log && exit 1)
(cd $TRAVIS_GH_PAGES_DIR && git log --oneline --decorate --graph -10)
echo '(cd '"$TRAVIS_GH_PAGES_DIR"'; git push --force --quiet "git@github.com/jsmaniac/journal-article-gh-pages.git" master:gh-pages)'
(cd $TRAVIS_GH_PAGES_DIR; git push --force --quiet "git@github.com:jsmaniac/journal-article-gh-pages.git" master:gh-pages >/dev/null 2>&1) >/dev/null 2>&1 # redirect to /dev/null to avoid showing credentials.
fi

0
biblio.bib Executable file → Normal file
View File

234
correlation-macros.tex Normal file
View File

@ -0,0 +1,234 @@
%%Macros
% This is the definition of meet_r
\def\meetR{%
\alignedmathop{%
\bigwedge%
}{%
\mathchoice%
{\bigwedge\mkern-0.5mu\smash{\raisebox{-0.9ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{R}}}}$}}}%
{\bigwedge\mkern-1.5mu\smash{\raisebox{-0.6ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{R}}}}$}}}%
{\bigwedge\mkern-2.25mu\smash{\raisebox{-0.3ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{R}}}}$}}}%
{\bigwedge\mkern-2.5mu\smash{\raisebox{-0.35ex}{$\resetstyle\mathlarger{{}_{\mathcal{R}}}$}}}%
}%
}
%
% This is the definition of join_k
\def\ijoin{%
\alignedmathop{%
\bigvee%
}{%
\mathchoice%
{\bigvee\mkern-6mu\smash{\raisebox{-0.9ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}%
{\bigvee\mkern-5mu\smash{\raisebox{-0.6ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}%
{\bigvee\mkern-2.25mu\smash{\raisebox{-0.3ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}%
{\bigvee\mkern-2.5mu\smash{\raisebox{-0.35ex}{$\resetstyle\mathlarger{{}_{\mathcal{K}}}$}}}%
}%
}
\def\largeijoin{%
\alignedmathop{%
\bigvee%
}{%
\mathchoice%
{\bigvee\mkern-7mu\smash{\raisebox{-0.6ex}{$\resetstyle\mathlarger{{}_{\mathcal{K}}}$}}}%
{\bigvee\mkern-5mu\smash{\raisebox{-0.6ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}%
{\bigvee\mkern-2.25mu\smash{\raisebox{-0.3ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}%
{\bigvee\mkern-2.5mu\smash{\raisebox{-0.35ex}{$\resetstyle\mathlarger{{}_{\mathcal{K}}}$}}}%
}%
}
%%For Tikz figures
%%%%% Custom pattern definition (not my code):
% defining the new dimensions
\newlength{\hatchspread}
\newlength{\hatchoffset}
\newlength{\hatchthickness}
% declaring the keys in tikz
\tikzset{
hatchspread/.code={\setlength{\hatchspread}{#1}},
hatchoffset/.code={\setlength{\hatchoffset}{#1}},
hatchthickness/.code={\setlength{\hatchthickness}{#1}}
}
% setting the default values
\tikzset{
hatchspread=.5cm,
hatchoffset=0.4pt,
hatchthickness=0.4pt
}
% declaring the pattern
\pgfdeclarepatternformonly[\hatchspread,\hatchthickness]% variables
{custom north east lines}% name
{\pgfqpoint{-2\hatchthickness}{-2\hatchthickness}}% lower left corner
{\pgfqpoint{\dimexpr\hatchspread+2\hatchthickness}{\dimexpr\hatchspread+2\hatchthickness}}% upper right corner
{\pgfqpoint{\hatchspread}{\hatchspread}}% tile size
{% shape description
\pgfsetlinewidth{\hatchthickness}
\pgfpathmoveto{\pgfqpoint{0pt}{\hatchoffset}}
\pgfpathlineto{\pgfqpoint{\dimexpr\hatchspread-\hatchoffset}{\hatchspread}}
\pgfpathmoveto{\pgfqpoint{\dimexpr\hatchspread-\hatchoffset}{0pt}}
\pgfpathlineto{\pgfqpoint{\dimexpr\hatchspread}{\hatchoffset}}
\pgfusepath{stroke}
}
%%%%% End custom pattern definition.
%\pgfmathparse{\year+\time+\currenthour+\currentminute*\currentsecond}
\edef\rndseed{4101} %%%%% To choose a fixed seed
%\edef\rndseed{\pgfmathresult} %%%%% Random seed
\pgfmathsetseed{\rndseed}
\def\cellw{.7cm}
\def\cellh{.8cm}
\def\minth{.15cm}
\def\vtpadding{.2cm}
\def\vbpadding{.1cm}
\def\hpadding{.05cm}
\def\nbnodes{4}
\def\minrand{0.3}
\def\borderh{0.2cm}
\def\triangleArray#1#2{
\foreach \i in {0,...,\nbnodes} {%
\node[inner sep=0pt,minimum height=\cellh, minimum width=\cellw, alias=#1-last, anchor=north west, xshift=\i*\cellw] (#1-\i) at #2 {};
% Magic coordinate calculations
% Fixed top position:
\pgfmathsetmacro{\tpos}{0}
% Random top position:
% \pgfmathsetmacro{\tpos}{rnd*(1-\minrand)+\minrand}
\pgfmathsetmacro{\trih}{rnd*(1-\minrand)+\minrand}
\def\tposformula{(\vtpadding+\tpos*(\cellh-\minth-\vtpadding-\vbpadding))}
\def\thformula{min(\trih*(\cellh-\tposformula-\vbpadding), \cellw*(1/.5555)*.5-2*\hpadding)}
% Triangle:
\draw #2 ++(\i*\cellw+.5*\cellw,{-\tposformula}) coordinate (#1-tt-\i) -- ++({.5555*\thformula},{-\thformula}) coordinate (#1-tr-\i) -- ++({-.5555*\thformula*2},0) coordinate (#1-tl-\i) -- cycle;
\coordinate (#1-tc-\i) at (barycentric cs:#1-tt-\i=1,#1-tr-\i=1,#1-tl-\i=1);
\coordinate (#1-tb-\i) at ($(#1-tl-\i)!.5!(#1-tr-\i)$);
}
% \draw (#1-0.north west) ++(0,\borderh) -- ($(#1-last.north east)+(0,\borderh)$) -- (#1-last.south east) -- (#1-0.south west) -- cycle;
% \draw (#1-0.north west) -- (#1-last.north east);
\draw (#1-last.north east) -- (#1-last.south east) -- (#1-0.south west) -- (#1-0.north west);
\draw[fill=black!7] (#1-0.north west) -- (#1-last.north east) -- ++(0,\borderh) -- ($(#1-0.north west)+(0,\borderh)$) -- cycle;
\foreach \i in {1,...,\nbnodes} {
\draw (#1-\i.north west) -- (#1-\i.south west);
}
}
%Leq for pequiv
\def\rleq{\mathrel{\sqsubseteq_{\kern0.15pt\rdom}}}
\def\rjoin{\mathrel{\vee_{\kern-0.25pt\rdom}}}
\def\rmeet{\mathrel{\wedge_{\kern0.15pt\rdom}}}
%\DeclareMathOperator*{\rbigwedge}{\bigwedge_\rdom}
%Macros for pequiv relations
\def\rdom{\mathscr{R}}
\def\equal{\textsf{Equal}}
\def\qmark{\textsf{Any}}
%\def\rel{\mathit{\mathcal{R}}}
\def\rel{R}
\newcommand{\srel}[2]{\{#1_1 \mapsto \rel_1; \ldots; #1_{#2} \mapsto \rel_{#2}\}}
\newcommand{\sreljoin}[2]{\{#1_1 \mapsto \rel_1 \rjoin \rel'_1; \ldots; #1_{#2} \mapsto \rel_{#2} \rjoin \rel'_{#2} \}}
\newcommand{\srelmeet}[2]{\{#1_1 \mapsto \rel_1 \rmeet \rel'_1; \ldots; #1_{#2} \mapsto \rel_{#2} \rmeet \rel'_{#2} \}}
\newcommand{\sreli}[2]{\{#1_1 \mapsto \rel_1; \ldots; #1_i \mapsto \rel_i; \ldots; #1_{#2} \mapsto \rel_{#2}\}}
\newcommand{\srelitop}[3]{\{#1_1 \mapsto \qmark; \ldots; #1_i \mapsto #3; \ldots; #1_{#2} \mapsto \qmark\}}
\def\srelibot{\{f_1 \mapsto \equal; \ldots; f_i \mapsto \qmark; \ldots; f_n \mapsto \equal\}}
\newcommand{\vrel}[2]{[#1_1 \mapsto \rel_1; \ldots; #1_{#2} \mapsto \rel_{#2}]}
\newcommand{\vreljoin}[2]{[#1_1 \mapsto \rel_1 \rjoin \rel'_1; \ldots; #1_{#2} \mapsto \rel_{#2} \rjoin \rel'_{#2}]}
\newcommand{\vrelmeet}[2]{[#1_1 \mapsto \rel_1 \rmeet \rel'_1; \ldots; #1_{#2} \mapsto \rel_{#2} \rmeet \rel'_{#2}]}
\newcommand{\vreli}[2]{[#1_1 \mapsto \rel_1; \ldots; #1_i \mapsto \rel_i; \ldots; #1_{#2} \mapsto \rel_{#2}]}
\newcommand{\vrelitop}[3]{[#1_1 \mapsto \qmark; \ldots; #1_i \mapsto #3; \ldots; #1_{#2} \mapsto \qmark]}
\newcommand{\arel}[1]{\langle #1 \rangle}
\newcommand{\aerel}[3]{\left\langle #1 \triangleright #2: \; #3 \right\rangle}
\newcommand{\aerelnoleftright}[3]{\langle #1 \triangleright #2: \; #3 \rangle}
\newcommand{\rels}{\srel{f}{n}}
\newcommand{\relsi}{\sreli{f}{n}}
\newcommand{\relv}{\vrel{C}{n}}
\newcommand{\relvi}{\vreli{C}{n}}
\newcommand{\rela}{\arel{\rel}}
\newcommand{\relai}{\langle \rel_{\mathit{def}} \triangleright i \;: \; \rel_{\mathit{exc}} \rangle}
\def\relaitop{\langle \equal \triangleright i \;: \; \qmark \rangle}
\newcommand{\srelv}[3]{\{#1_1 \mapsto #3_1; \ldots; #1_{#2} \mapsto #3_{#2}\}}
\newcommand{\vrelv}[3]{[#1_1 \mapsto #3_1; \ldots; #1_{#2} \mapsto #3_{#2}]}
\newcommand{\semrel}[2]{\llbracket #1 \rrbracket^{#2}}
%Projections on pequiv
\def\fieldp{\textrm{\textsf{\emph{extr}}}_f}
\def\consp{\textrm{\textsf{\emph{extr}}}_C}
\def\allp{\textrm{\textsf{\emph{extr}}}_{\langle * \rangle}}
\def\cellp{\textrm{\textsf{\emph{extr}}}_{\langle i \rangle}}
\def\outp{\textrm{\textsf{\emph{extr}}}_{\langle * \setminus i \rangle}}
%Macros for paths
\def\pcell{\langle i \rangle}
\def\pstruct{.f}
\def\pvar{@C}
\def\pempty{\widehat{\varepsilon}}
\def\identical{\textsf{Identical}}
\def\incompatible{\textsf{Incompatible}}
\def\leftcase{\textsf{Left}}
\def\rightcase{\textsf{Right}}
\def\findl{\curlywedge}
\def\append{\dblcolon}
%Macros for path operators:
%\DeclareMathOperator{\pproj}{\rightsquigarrow}
%\DeclareMathOperator{\pinj}{\curvearrowleft}
%Macros for correlations
%\def\cor{\hat{\mathcal{C}}}
\def\cor{\mathscr{K}}
%\def\corv{\hat{c}}
\def\corv{\kappa}
\def\aleq{\mathrel{\hat{\sqsubseteq}}}
%\DeclareMathOperator*{\ajoin}{\hat{\bigvee}}
%\DeclareMathOperator*{\hatbigwedge}{\hat{\bigwedge}}
\def\acompose{\mathop{\ocircle}}
\def\raligned{\rel_{\aligned(\pi', \rho')}^{(\pi, \rho)}}
\def\ralignedc{\rel_{\aligned\corv}^{(\pi, \rho)}}
\def\ralignedv{\rel_{\aligned\corv_1}^{(\pi, \rho)}}
\def\ralignedw{\rel_{\aligned\corv_2}^{(\pi, \rho)}}
%Macros for intra domains
\def\ileq{\sqsubseteq_{\mathcal{K}}}
%\def\ijoin{\bigvee_{\mathcal{K}}}
\def\justif{\Vvdash}
\def\aligned{\parallel}
\def\intracor{K}
\def\compose{\odot}
%Macros for equations
\newcommand{\Ctransfer}[3]{\mathbb{C}^{#2}_{#3}(#1)}
\def\inter{\mathcal{K}_p}
%Colors
%\definecolor{indianred}{rgb}{0.8, 0.36, 0.36}
\definecolor{iburg}{rgb}{0.75, 0.0, 0.2}
% hat math variables
\def\cptype{\ensuremath{\widehat{\Pi}}}
\def\cpath{\ensuremath{\widehat{\pi}}}
\def\crho{\ensuremath{\widehat{\rho}}}
\def\csigma{\ensuremath{\widehat{\sigma}}}
\def\calpha{\ensuremath{\widehat{\alpha}}}
\def\cbeta{\ensuremath{\widehat{\beta}}}
\def\cgamma{\ensuremath{\widehat{\gamma}}}
\def\cdelta{\ensuremath{\widehat{\delta}}}
\def\kset{$\textrm{\emph{kill}}_\lambda$}
\def\kseti{$\textrm{\emph{kill}}_i$}
\def\ksettrue{$\textrm{\emph{kill}}_{\mathit{true}}$}
\def\dls{c_{\lambda}^s}

190
forest-compat.sty Normal file
View File

@ -0,0 +1,190 @@
% \CheckSum{12884}
% \iffalse meta-comment
% forest-index.dtx
%% `forest-compat' defines a compatibility layer of package `forest'.
%%
%% Copyright (c) 2015 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic@guest.arnes.si
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%%
%% http://www.latex-project.org/lppl.txt
%%
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `author-maintained'.
%%
%% This file is a part of package `forest'. For the list of files
%% constituting the package see main source file of the package,
%% `forest.dtx', or the derived `forest.sty'.
\ProvidesPackage{forest-compat}
\def\forest@deprecated#1{%
\PackageWarning{forest}{Compatibility mode for #1}%
}
\forestset{@@deprecated/.code={\forest@deprecated{#1}}}
\def\forestcompat#1{\pgfqkeys{/forest/@compat}{#1}}
\forestcompat{
silent/.style={\def\forest@deprecated##1{}},
%%% begin listing region: compat_keys
most/.style={1.0-most},
all/.style={1.0-all},
none/.style={},
1.0-most/.style={
1.0-triangle,1.0-linear,1.0-nodewalk,1.0-ancestors,
1.0-fittotree,1.0-for,1.0-forall
},
1.0-all/.style={
1.0-most,
1.0-forstep,1.0-rotate,1.0-stages,1.0-name,
2.0.2-all,
},
2.0.2-all/.style={
2.0.2-delayn,2.0.2-wrapnpgfmathargs,
},
%%% end listing region: compat_keys
1.0-triangle/.style={
/forest/triangle/.style={
@@deprecated={key "triangle" from v1.0.x. Use key "roof" from library "linguistics" instead},
edge path'={%
(.north west)--(!u.south)--(.north east)--cycle
}
}
},
1.0-linear/.style={
/forest/define long step={linear next}{autostep}{%
\forest@deprecated{nodewalk step "linear next" from v1.0. Use key "next node" instead.}%
\edef\forest@cn{\forest@node@linearnextid}},
/forest/define long step={linear previous}{autostep}{%
\forest@deprecated{nodewalk step "linear previous" from v1.0. Use key "previous node" instead.}%
\edef\forest@cn{\forest@node@linearpreviousid}},
},
1.0-nodewalk/.style={
/forest/node walk/before walk/.style={},
/forest/node walk/every step/.style={},
/forest/node walk/after walk/.style={},
/forest/node walk/.style={
@@deprecated={key "node walk" from v1.0. Use key "nodewalk" instead.},
/forest/node walk/before walk,
/forest/nodewalk/before walk/.style={/forest/node walk/before walk},
/forest/nodewalk/every step/.style={/forest/node walk/every step},
/forest/nodewalk/after walk/.style={/forest/node walk/after walk},
/forest/nodewalk/node walk/.style={before walk,for nodewalk={####1,options={/forest/nodewalk/after walk}}{/forest/nodewalk/every step}},
for nodewalk={##1,options={/forest/nodewalk/after walk}}{/forest/nodewalk/every step},
},
},
1.0-ancestors/.style={
/forest/for ancestors'/.style={
@@deprecated={key "for ancestors'" from v1.0.x. Use key "for current and ancestors" instead.},
for current and ancestors={##1}},
},
1.0-fittotree/.style={%
/tikz/fit to tree/.style={
/forest/@@deprecated={key "/tikz/fit to tree" from v1.0.x. Use "/tikz/fit to=tree" instead.},
inner sep=0pt,fit to=tree
}
},
1.0-for/.style={
/forest/for/.code 2 args={% #1 = nodewalk, #2 = after walk keylist
\forest@deprecated{Key "for" from v1.0.x. Use key "for group" instead.}%
\forest@forthis{\forest@nodewalk{##1,options={##2}}{}}%
}
},
1.0-forall/.style={
/forest/for all next/.style={
@@deprecated={Key "for all next" from v1.0.x. Use key "for following siblings" instead.},
for following siblings={##1}},
/forest/for all previous/.style={
@@deprecated={Key "for all previous" from v1.0.x. Use key "for preceding siblings" instead.},
for preceding siblings={##1}},
},
1.0-forstep/.code={%
\def\forest@forstepwrapper##1##2{%
\def\forest@nodewalk@config@everystep@method{independent}%
\def\forest@nodewalk@config@history@method{independent}%
\edef\forest@marshal{%
\def\noexpand\forest@nodewalk@config@oninvalid{compatfake}%
\unexpanded{\forest@Nodewalk{##1}{##2}}%
\def\noexpand\forest@cn{\forest@cn}%
\def\noexpand\forest@nodewalk@config@oninvalid{\forest@nodewalk@config@oninvalid}%
}\forest@marshal
}%
\def\forest@relatednode@option@compat@ignoreinvalidsteps##1{%
\forest@saveandrestoremacro\forest@nodewalk@oninvalid{%
\def\forest@nodewalk@oninvalid{compatfake}%
##1%
}%
}%
},
1.0-rotate/.style={
/forest/undef option=rotate,
rotate/.style={
@@deprecate={Using non-autoforwarded key "rotate". Some keys, like "forked edges" and "folder", might produce a wrong result.},
node options={rotate={##1}},
},
},
1.0-stages/.style={
/forest/@@deprecated={Using v1.0.x "stages" style},
/forest/stages/.style={
process keylist=before typesetting nodes,
typeset nodes stage,
process keylist=before packing,
pack stage,
process keylist=before computing xy,
compute xy stage,
process keylist=before drawing tree,
draw tree stage,
},
/forest/TeX={%
\def\forest@defstages##1{%
\def\forest@stages{%
begin forest,
for root'={
process keylist register=default preamble,
process keylist register=preamble
},
process keylist=given options,
##1,
end forest
}%
}%
},
},
1.0-name/.code={%
\forest@deprecated{key "name": using key "name" from v1.0.x, which does not enforce uniqueness. If you really need this, you're doing something wrong.}%
\def\forest@node@setname##1{%
\ifstrempty{##1}{}{%
\forestoeset{name}{##1}%
\csedef{forest@id@of@##1}{\forest@cn}%
}%
}%
\def\forest@node@setalias##1{%
\ifstrempty{##1}{}{%
\csedef{forest@id@of@##1}{\forest@cn}%
}%
}%
},
2.0.2-delayn/.style={
/forest/delay@n/.style 2 args={
@@deprecated={propagator "delay n" (it introduces two levels of hash doubling)},
if={##1==1}{delay={##2}}{delay={delay@n/.wrap pgfmath arg={{####1}{##2}}{##1-1}}}
},
},
2.0.2-wrapnpgfmathargs/.code={
\def\forest@wrap@pgfmath@args@@@wrapandpasson{%
\forest@deprecated{handler "wrap n pgfmath args" (it introduces two levels of hash doubling)}%
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\forest@wrapped
\expandafter\expandafter\expandafter{%
\expandafter\forest@wrap@code\forest@wrap@args}%
\expandafter\pgfkeysalso\expandafter{\expandafter\pgfkeyscurrentpath\expandafter=\expandafter{\forest@wrapped}}%
}%
},
}
\expandafter\forestcompat\expandafter{\forest@compat}

240
forest-doc.sty Normal file
View File

@ -0,0 +1,240 @@
%% forest-doc.sty
%% `forest-doc.sty` is an auxiliary package needed to compile the documentation of package `forest`.
%%
%% Copyright (c) 2015 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic@guest.arnes.si
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%%
%% http://www.latex-project.org/lppl.txt
%%
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `author-maintained'.
%%
%% This file is a part of package `forest'. For the list of files
%% constituting the package see main source file of the package,
%% `forest.dtx', or the derived `forest.sty'.
%%
\ProvidesPackage{forest-doc}
\RequirePackage{lstdoc}
\RequirePackage{pgfkeys}
\RequirePackage{forest-index}
% if you want index support, load package "forest-index", but later
\lstset{language={[LaTeX]TeX},tabsize=4,gobble=2,%
basicstyle=\small\ttfamily,basewidth=0.51em,boxpos=c,pointstyle=\pstyle,moredelim=[is][\pstyle]{~}{~}}
%\lst@InstallKeywords{p}{point}{pointstyle}\relax{keywordstyle}{}ld
\def\pstyle{\color{darkgreen}}
\def\itemnosep{\vspace{-1.4ex}}
\lstset{
rangebeginprefix=\ \ \%\%\%\ begin\ listing\ region:\ ,
rangebeginsuffix=,
rangeendprefix=\ \ \%\%\%\ end\ listing\ region:\ ,
rangeendsuffix=,
includerangemarker=false,
keepspaces=true,
}
\newcommand\lstinputregion[3][]{\lstinputlisting[linerange=#3-#3,#1]{#2}}
\def\lst@outputspace{{\ifx\lst@bkgcolor\empty\color{white}\else\lst@bkgcolor\fi\lst@visiblespace}}% this works for acroread, but not for atril :-(
\lstnewenvironment{forestexample}[1][]{%
\PackageWarning{forest-doc}{Compiling example}{}%
\global\let\lst@intname\@empty
\gdef\lst@sample{}%
\def\forestexample@layout{tree on left}%
\def\forestexample@treebin{box}%
\pgfqkeys{/forestexample}{label format,#1}%
\pgfkeysgetvalue{/forestexample/counter}\forestexample@temp
\ifdefempty\forestexample@temp{}{\addtocounter{\forestexample@temp}{1}}%
\setbox\lst@samplebox=\hbox\bgroup
\pgfkeysvalueof{/forestexample/tree prefix}%
\lst@BeginAlsoWriteFile{\jobname.tmp}%
}{%
\lst@EndWriteFile
\pgfkeysvalueof{/forestexample/tree suffix}%
\egroup
\global\setbox\codebox=\box\lst@samplebox
\global\setbox
\treebox
\csname forestexample@treebin@\forestexample@treebin\endcsname
\pgfkeys{/forestexample/do layout/.expanded=\forestexample@layout}%
}
\pgfqkeys{/forestexample}{%
.unknown/.code={\lstset{\pgfkeyscurrentname={#1}}},
index/.code={\indexex[not print]{#1}},
index>/.code={\indexex[not print]>{#1}},
code prefix/.code={\gdef\lst@sample{#1}},
tree prefix/.initial={},
tree suffix/.initial={},
counter/.initial=lstlisting,
no label/.style={counter={}},
label format/.store in=\@currentlabel,
label format/.default={\arabic{\pgfkeysvalueof{/forestexample/counter}}},
tree width/.initial={\dimexpr\linewidth-\wd\codebox-
\glueexpr\pgfkeysvalueof{/forestexample/center skip}\relax\relax},
layout/.store in=\forestexample@layout,
tree bin/.store in=\forestexample@treebin,
do layout/.is choice,
do layout/export/.code={%
\pgfkeysgetvalue{/forestexample/counter}\forestexample@temp
\ifdefempty\forestexample@temp{}{\addtocounter{\forestexample@temp}{-1}}%
},
left skip/.initial={\glueexpr 0pt plus .4\linewidth minus \marginparsep + 0pt minus \@totalleftmargin + 0pt minus .75\marginparwidth},
center skip/.initial={3em plus 0.1\linewidth minus 2em},
right skip/.initial={0pt plus .4\linewidth},
tree left skip/.initial=0pt,
tree right skip/.initial=0pt,
code left skip/.initial=0pt,
code right skip/.initial=0pt,
label y offset/.initial={\height-1ex}, % looks better to me this way
do layout/tree on left/.code={%
\begin{list}{}{\leftmargin 0pt}
\item
\@tempdima=\ifdim\totalht\treebox>\totalht\codebox
\dimexpr0.5 \totalht\treebox\relax
\else
\dimexpr0.5 \totalht\codebox\relax
\fi
\mbox{%
\mbox{\hbox to \linewidth{%
\hskip\pgfkeysvalueof{/forestexample/left skip}\relax
\textvcenter{\box\treebox}%
\hskip\pgfkeysvalueof{/forestexample/center skip}\relax
\hbox{\hskip-\@totalleftmargin\box\codebox\hskip\@totalleftmargin}%
\hskip\pgfkeysvalueof{/forestexample/right skip}\relax
}}%
\forestexample@label
}%
\end{list}
},
v sep/.initial={1ex},
align/.initial=center,
do layout/tree on top/.code={%
\begin{list}{}{\leftmargin 0pt \parsep 0pt \itemsep \pgfkeysvalueof{/forestexample/v sep}\relax}
\item \forestexample@align{tree}\forestexample@label
\item \forestexample@align{code}
\end{list}
},
do layout/tree on bottom/.code={%
\begin{list}{}{\leftmargin 0pt \parsep 0pt \itemsep \pgfkeysvalueof{/forestexample/v sep}\relax}
\item \forestexample@align{code}\forestexample@label
\item \forestexample@align{tree}
\end{list}
},
do layout/only tree/.code={%
\forestexample@align{tree}\forestexample@label
},
do layout/only code/.code={%
\forestexample@align{code}\forestexample@label
},
}
\newbox\treebox
\newbox\codebox
\def\forestexample@treebin@box{%
\hbox{\lst@sampleInput}%
}
\def\forestexample@treebin@minipage{%
\hbox{%
\begin{minipage}{\pgfkeysvalueof{/forestexample/tree width}}%
\lst@sampleInput
\end{minipage}%
}%
}
\def\forestexample@label{%
\pgfkeysgetvalue{/forestexample/counter}\forestexample@temp
\ifdefempty\forestexample@temp{}{%
\makebox[0pt][l]{%
\hskip-\linewidth
\hskip-\@totalleftmargin
\hskip\textwidth
\hskip\marginparsep
\raisebox
{\dimexpr\@tempdima+\depth-\pgfkeysvalueof{/forestexample/label y offset}}%
{\hbox to 0pt{\scriptsize(\@currentlabel)}}%
}%
}%
}
\def\forestexample@align#1{%
\pgfkeysgetvalue{/forestexample/align}\forestexample@temp
\mbox{\hbox to \linewidth{%
\csname forestexample@align@left@\forestexample@temp\endcsname
\hspace*{\pgfkeysvalueof{/forestexample/#1 left skip}}%
\mbox{\expandafter\box\csname #1box\endcsname}%
\hspace*{\pgfkeysvalueof{/forestexample/#1 right skip}}%
\csname forestexample@align@right@\forestexample@temp\endcsname
}}%
}
\def\forestexample@align@left@left{}
\def\forestexample@align@right@left{}
\def\forestexample@align@left@right{\hfill}
\def\forestexample@align@right@right{}
\def\forestexample@align@left@center{\hfill}
\def\forestexample@align@right@center{\hfill}
\newcommand\forestexampleimport[1][]{%
\def\forestexample@layout{tree on left}%
\pgfkeysgetvalue{/forestexample/counter}\forestexample@temp
\ifdefempty\forestexample@temp{}{\addtocounter{\forestexample@temp}{1}}%
\pgfqkeys{/forestexample}{%
label format,
do layout/.expanded=\forestexample@layout
}%
}
\def\totalht#1{\dimexpr\ht#1 + \dp#1\relax}
\def\textvcenter#1{\raisebox{\dimexpr .5\depth-.5\height}{#1}}
% For some reason, lstdoc's version kills all spaces in defaults ...
\def\lst@syntaxlabel@#1>#2\relax
%{\edef\lst@temp{\zap@space#2 \@empty}}
{\edef\lst@temp{#2}}
\def\getforestversion#1/#2/#3 v#4 #5\getforestversion{v#4}
\edef\forestversion{%
\expandafter\expandafter\expandafter\getforestversion
\csname ver@forest.sty\endcsname\getforestversion}
\def\settodayfromforestdateA#1/#2/#3 v#4 #5\settodayfromforestdateA{\def\year{#1}\def\month{#2}\def\day{#3}}
\def\settodayfromforestdate{\expandafter\expandafter\expandafter\settodayfromforestdateA\csname ver@forest.sty\endcsname\settodayfromforestdateA}
\def\TikZ;{{\rm Ti\emph{k}Z}}
\def\PGF;{\textsc{pgf}}
\def\foRest;{\textsc{Forest}}
\def\FoRest;{\textsc{Forest}}
\let\keyname\texttt
\newcommand\cmdname[1]{\texttt{\char\escapechar#1}}
\gdef\greaterthan{>}
\def\gobbleone#1{}
\newcommand{\Repeat}[1]{% from tex.se http://tex.stackexchange.com/a/16194/16819
\expandafter\@Repeat\expandafter{\the\numexpr #1\relax}%
}
\def\@Repeat#1{%
\ifnum#1>0
\expandafter\@@Repeat\expandafter{\the\numexpr #1-1\expandafter\relax\expandafter}%
\else
\expandafter\@gobble
\fi
}
\def\@@Repeat#1#2{%
\@Repeat{#1}{#2}#2%
}
\def\spaces#1{\Repeat{#1}\space}
%%% Local Variables:
%%% mode: latex
%%% fill-column: 100
%%% TeX-command-default: "Make PDF"
%%% TeX-master: "forest-doc"
%%% End:

74
forest-lib-edges.sty Normal file
View File

@ -0,0 +1,74 @@
%%
%% This is file `forest-lib-edges.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% forest-libs.dtx (with options: `edges')
%%
%% `forest-libs' is a collection of libraries for package `forest'.
%%
%% Copyright (c) 2015 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic@guest.arnes.si
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%%
%% http://www.latex-project.org/lppl.txt
%%
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `author-maintained'.
%%
%% This file is a part of package `forest'. For the list of files
%% constituting the package see main source file of the package,
%% `forest.dtx', or the derived `forest.sty'.
%%
\RequirePackage{forest}
\ProvidesForestLibrary{edges}[2015/11/14 v0.1]
\forestset{
declare dimen={fork sep}{0.5em},
forked edge/.style={
edge={rotate/.pgfmath=grow()},
edge path'={(!u.parent anchor) -- ++(\forestoption{fork sep},0) |- (.child anchor)},
},
forked edges/.style={
for tree={parent anchor=children},
for descendants={child anchor=parent,forked edge}
},
}
\forestset{
declare dimen register=folder indent,
folder indent=.45em,
folder/.style={
parent anchor=parent last,
anchor=parent first,
calign=child,
calign primary child=1,
for children={
child anchor=parent,
anchor=parent first,
edge={rotate/.pgfmath=grow()},
edge path'/.expanded={
([xshift=\forestregister{folder indent}]!u.parent anchor) |- (.child anchor)
},
},
after packing node={
if n children=0{}{
tempdiml=l_sep()-l("!1"),
tempdims={-abs(max_s("","")-min_s("",""))-s_sep()},
for children={
l+=tempdiml,
s+=tempdims()*(reversed()-0.5)*2,
},
},
},
}
}
\endinput
%%
%% End of file `forest-lib-edges.sty'.

133
forest-lib-linguistics.sty Normal file
View File

@ -0,0 +1,133 @@
%%
%% This is file `forest-lib-linguistics.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% forest-libs.dtx (with options: `linguistics')
%%
%% `forest-libs' is a collection of libraries for package `forest'.
%%
%% Copyright (c) 2015 Saso Zivanovic
%% (Sa\v{s}o \v{Z}ivanovi\'{c})
%% saso.zivanovic@guest.arnes.si
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%%
%% http://www.latex-project.org/lppl.txt
%%
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `author-maintained'.
%%
%% This file is a part of package `forest'. For the list of files
%% constituting the package see main source file of the package,
%% `forest.dtx', or the derived `forest.sty'.
%%
\RequirePackage{forest}
\ProvidesForestLibrary{linguistics}[2015/11/14 v0.1]
\forestset{
libraries/linguistics/defaults/.style={
default preamble={
sn edges,
baseline,
for tree={align=center},
},
},
}
\forestset{
define long step={c-commanded}{style}{branch'={siblings,descendants}},
define long step={c-commanders}{style}{while nodewalk valid={parent}{siblings,fake=parent}},
}
\forestset{
sn edges/.style={
for tree={
parent anchor=children, child anchor=parent
}
},
}
\forestset{
roof/.style={edge path'={%
(.parent first)--(!u.children)--(.parent last)--cycle
}
},
}
\forestset{
nice empty nodes/.style={
for tree={calign=fixed edge angles},
delay={where content={}{shape=coordinate,for parent={
for children={anchor=north}}}{}}
},
}
\providecommand\text[1]{\mbox{\scriptsize#1}}
\forestset{
draw brackets compact/.code={\let\drawbracketsspace\relax},
draw brackets wide/.code={\let\drawbracketsspace\space},
draw brackets/.style={
for tree'={
TeX={[%
\edef\forestdrawbracketscontentformat{\foresteoption{content format}}%
},
if n children=0{
TeX={\drawbracketsspace\forestdrawbracketscontentformat\drawbracketsspace}
}{
TeX={\textsubscript{\text{\forestdrawbracketscontentformat}}\drawbracketsspace}
},
}{
TeX={]\drawbracketsspace},
}
},
draw brackets wide
}
\newbox\standardnodestrutbox
\setbox\standardnodestrutbox=\hbox to 0pt{\phantom{\forestOve{standard node}{content}}}
\def\standardnodestrut{\copy\standardnodestrutbox}
\forestset{
GP1/.style 2 args={
for n={1}{baseline},
s sep=0pt, l sep=0pt,
for descendants={
l sep=0pt, l={#1},
anchor=base,calign=first,child anchor=north,
inner xsep=1pt,inner ysep=2pt,outer sep=0pt,s sep=0pt,
},
delay={
if content={}{phantom}{for children={no edge}},
for tree={
if content={O}{tier=OR}{},
if content={R}{tier=OR}{},
if content={N}{tier=N}{},
if content={x}{
tier=x,content={$\times$},outer xsep={#2},
for tree={calign=center},
for descendants={content format={\noexpand\standardnodestrut\forestoption{content}}},
before drawing tree={outer xsep=0pt,delay={typeset node}},
s sep=4pt
}{},
},
},
before drawing tree={where content={}{parent anchor=center,child anchor=center}{}},
},
GP1/.default={5ex}{8.0pt},
associate/.style={%
tikz+={\draw[densely dotted](!)--(!#1);}},
spread/.style={
before drawing tree={tikz+={\draw[dotted](!)--(!#1);}}},
govern/.style={
before drawing tree={tikz+={\draw[->](!)--(!#1);}}},
p-govern/.style={
before drawing tree={tikz+={\draw[->](.north) to[out=150,in=30] (!#1.north);}}},
no p-govern/.style={
before drawing tree={tikz+={\draw[->,loosely dashed](.north) to[out=150,in=30] (!#1.north);}}},
encircle/.style={before drawing tree={circle,draw,inner sep=0pt}},
fen/.style={pin={[font=\footnotesize,inner sep=1pt,pin edge=<-]10:\textsc{Fen}}},
el/.style={content=\textsc{\textbf{##1}}},
head/.style={content=\textsc{\textbf{\underline{##1}}}}
}
\endinput
%%
%% End of file `forest-lib-linguistics.sty'.

7497
forest.sty Normal file

File diff suppressed because it is too large Load Diff

125
growingwave.sty Normal file
View File

@ -0,0 +1,125 @@
\def\pgfdecorationgrowthstart{0cm}
\def\pgfdecorationgrowthendsizelist{0cm}
\def\pgfdecorationgrowthwavelengthlist{0cm}
\def\pgfdecorationgrowthendstepslist{1}
\def\pgfdecorationgrowthendstep{1}
\newif\ifpgfdecorationgrowthsine
\newif\ifpgfdecorationgrowthcosine
\newif\ifpgfdecorationonewavelength
\pgfdecorationgrowthcosinefalse
\pgfdecorationgrowthsinetrue
\pgfkeys{%
/pgf/decoration/.cd,
growth start size/.initial=0.5cm,
growth end size/.initial=3cm,
growth end steps/.initial=1,
growth wave length/.initial=3pt,
growth sine/.code={\pgfdecorationgrowthsinetrue\pgfdecorationgrowthcosinefalse},
growth cosine/.code={\pgfdecorationgrowthsinefalse\pgfdecorationgrowthcosinetrue}
}
\def\pgfdecorationgrowthsetup{%
\global\edef\pgfdecorationgrowthstart{\pgfkeysvalueof{/pgf/decoration/growth start size}}%
\global\edef\pgfdecorationgrowthendsizelist{\pgfkeysvalueof{/pgf/decoration/growth end size}}%
\global\edef\pgfdecorationgrowthendstepslist{\pgfkeysvalueof{/pgf/decoration/growth end steps}}%
\global\edef\pgfdecorationgrowthwavelengthlist{\pgfkeysvalueof{/pgf/decoration/growth wave length}}%
}
\def\pgfdecorationgrowthsteps{1} % To keep track of steps from ending
\def\pgfdecorationliststeps{2} % To keep track of list items from ending, has to start from 2
\pgfdeclaredecoration{growth wave}{initial}%
{
\state{initial}[width=0pt,next state=first] {%
\pgfdecorationgrowthsetup%
\pgfpathlineto{\pgfqpoint{0pt}{0pt}}%
\global\edef\pgfdecorationgrowthsteps{0}%
\global\edef\pgfdecorationliststeps{2}%
\foreach \endsize in \pgfdecorationgrowthendsizelist {%
\global\edef\pgfdecorationgrowthendsize{\endsize}%
\breakforeach%
}%
\foreach \growthstep in \pgfdecorationgrowthendstepslist {%
\global\edef\pgfdecorationgrowthendstep{\growthstep}%
\breakforeach%
}%
\foreach \wavelength in \pgfdecorationgrowthwavelengthlist {%
\global\edef\pgfdecorationgrowthwavelength{\wavelength}%
\breakforeach%
}%
\pgfmathparse{(\pgfdecorationgrowthendsize - \pgfdecorationgrowthstart) * 2 * %
\pgfdecorationgrowthwavelength / ( \pgfdecoratedremainingdistance * \pgfdecorationgrowthendstep)}%
\global\edef\pgfdecorationgrowth{\pgfmathresult}%
}%
\state{first}[width=2*\pgfdecorationgrowthwavelength,next state=second] {%
\pgfdecorationgrowthstepcounters%
\pgfmathparse{\pgfdecorationgrowthstart + \pgfdecorationgrowthsteps * \pgfdecorationgrowth}%
% The wave starts
\ifpgfdecorationgrowthsine%
\pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}%
\pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}%
\fi%
\ifpgfdecorationgrowthcosine%
\pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}%
\pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}%
\fi%
\pgfdecorationgrowthstateend%
}%
\state{second}[width=2*\pgfdecorationgrowthwavelength,next state=first] {%
\pgfdecorationgrowthstepcounters%
\pgfmathparse{\pgfdecorationgrowthstart + \pgfdecorationgrowthsteps * \pgfdecorationgrowth}%
% The wave continues
\ifpgfdecorationgrowthsine%
\pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}%
\pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}%
\fi%
\ifpgfdecorationgrowthcosine%
\pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}%
\pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}%
\fi%
\pgfdecorationgrowthstateend%
}
\state{final} {%
\pgfpathlineto{\pgfpointdecoratedpathlast}%
}%
}
\def\pgfdecorationgrowthstateend{%
\pgfmathadd{\pgfdecorationgrowthsteps}{1}%
\global\edef\pgfdecorationgrowthsteps{\pgfmathresult} % Redefine the steps counter, globally.
}
\def\pgfdecorationgrowthstepcounters{%
\pgfmathparse{\pgfdecorationgrowthendstep * \pgfdecoratedpathlength}
\ifdim\pgfdecoratedcompleteddistance>\pgfmathresult pt%
\foreach \endsize [count=\count] in \pgfdecorationgrowthendsizelist {%
\ifnum\count=\pgfdecorationliststeps%
\global\edef\pgfdecorationgrowthendsize{\endsize}%
\breakforeach%
\else%
\global\edef\pgfdecorationgrowthstart{\endsize}%
\fi%
}%
\global\edef\tempa{0}%
\foreach \growthstep [count=\count] in \pgfdecorationgrowthendstepslist {%
\ifnum\count=\pgfdecorationliststeps%
\global\edef\pgfdecorationgrowthendstep{\growthstep}%
\breakforeach%
\else%
\global\edef\tempa{\growthstep}%
\fi%
}%
\foreach \wavelength [count=\count] in \pgfdecorationgrowthwavelengthlist {%
\ifnum\count=\pgfdecorationliststeps%
\global\edef\pgfdecorationgrowthwavelength{\wavelength}%
\breakforeach%
\fi%
}%
\pgfmathparse{int(\pgfdecorationliststeps+1)}%
\global\edef\pgfdecorationliststeps{\pgfmathresult}%
\global\edef\pgfdecorationgrowthsteps{0}% Redefine the steps counter, globally.
\pgfmathparse{(\pgfdecorationgrowthendsize-\pgfdecorationgrowthstart) * 2 %
* \pgfdecorationgrowthwavelength / (\pgfdecoratedpathlength * (\pgfdecorationgrowthendstep -\tempa))}%
\global\edef\pgfdecorationgrowth{\pgfmathresult}%
\fi%
}

165
justtrees.sty Normal file
View File

@ -0,0 +1,165 @@
x%% Copyright 2016 Clea F. Rees
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
% http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Clea F. Rees.
%
% This work consists of the file justtrees.sty.
%%
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{svn-prov}
\ProvidesPackageSVN{$Id: justtrees.sty 4959 2016-05-27 23:00:49Z cfrees $}[v0.08 \revinfo]
\RequirePackage{forest}
\newlength{\justtrees@tempa}
\tikzset{%
justifier format/.style={font=\justtrees@justifier@font},
justifier font/.store in=\justtrees@justifier@font,
justifier font=\normalfont\normalsize,
left justifier format/.style={},
right justifier format/.style={},
}
\forestset{%
declare boolean register={left justifiers},% left justifications
not left justifieers,
declare boolean register={right justifiers},% right justifications
not right justifiers,
declare dimen register={left justifiers width},
left justifiers width'=0pt,
declare dimen register={right justifiers width},
right justifiers width'=0pt,
declare toks register={left justifiers align},
left justifiers align={right},
declare toks register={right justifiers align},
right justifiers align={left},
declare boolean register={empty nodes},
empty nodes,
just format/.style={%
/tikz/justifier format/.append style={#1},
},
left just format/.style={%
/tikz/left justifier format/.append style={#1},
},
right just format/.style={%
/tikz/right justifier format/.append style={#1},
},
left justifications/.style={%
left justifiers,
},
right justifications/.style={%
right justifiers,
},
left just align/.style={%
left justifiers align=#1,
if={strequal(left_justifiers_align,"right")}{}
{%
left just/.append style={%
TeX={\settowidth\justtrees@tempa{\justtrees@justifier@font ##1}},
if={\justtrees@tempa>left_justifiers_width}
{%
left justifiers width=\justtrees@tempa,
}{}
},
},
},
right just align/.style={%
right justifiers align=#1,
if={strequal(right_justifiers_align,"left")}{}
{%
right just/.append style={%
TeX={\settowidth\justtrees@tempa{\justtrees@justifier@font ##1}},
if={\justtrees@tempa>right_justifiers_width}
{%
right justifiers width=\justtrees@tempa,
}{}
},
},
},
right just/.style={%
right justifiers,
tikz+/.wrap pgfmath arg={%
\node (right just ##1) [anchor=base west, justifier format, right justifier format] at (.base -| just tree east) {#1};
}{level()}
},
left just/.style={%
left justifiers,
tikz+/.wrap pgfmath arg={%
\node (left just ##1) [anchor=base east, justifier format, left justifier format] at (.base -| just tree west) {#1};
}{level()}
},
just/.style={%
if right justifiers={%
right just={#1}
}{%
if left justifiers={%
left just={#1},
}{%
right just={#1},
},
},
},
just tree/.style={%
for tree={%
parent anchor=children,
before typesetting nodes={%
if empty nodes={%
where content={}{%
shape=coordinate,
}{}
}{},
},
},
where level=0{%
tikz+={%
\coordinate (just tree north) at (current bounding box.north);
\coordinate (just tree south) at (current bounding box.south);
\coordinate (just tree west) at (current bounding box.west);
\coordinate (just tree east) at (current bounding box.east);
},
for children={%
no edge,
},
before typesetting nodes={%
if content={}{phantom}{},
},
}{},
before packing={%
for tree={%
tier/.wrap pgfmath arg={tier ##1}{level()},
},
},
before drawing tree={%
if={strequal(left_justifiers_align,"right")}{}
{%
left just format={%
text width/.register=left justifiers width,
align/.register=left justifiers align,
},
},
if={strequal(right_justifiers_align,"left")}{}
{%
right just format={%
text width/.register=right justifiers width,
align/.register=right justifiers align,
},
},
},
},
}
\environbodyname\justtreebody
\bracketset{action character=@}
\NewEnviron{justtree}[1]{% \forest/\endforest from egreg's answer at http://tex.stackexchange.com/a/229608/
\forest
just tree,
#1,
[@\justtreebody]
\endforest}
\endinput
%% end justtrees.sty

246
main.tex
View File

@ -1,7 +1,6 @@
\documentclass[11pt]{article}
\usepackage{a4wide}
\usepackage[T1]{fontenc}
\usepackage[scaled=.7]{beramono}
@ -33,8 +32,8 @@
\usepackage{forest}
\usepackage{tikz,datetime}
\usetikzlibrary{decorations.pathreplacing,trees,calc,fit,positioning,chains,arrows,arrows.meta,automata,shapes,graphs,shapes.geometric,shapes.symbols,
decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math}
%,triangle-fit,decorations.growingwave,oni-squiggly}
decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math,
triangle-fit,decorations.growingwave,oni-squiggly}
\usepackage{pgf}
\usepackage{pgfplots}
\usepackage{graphicx}
@ -53,20 +52,19 @@ decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math}
\restoresymbol{bb}{Cross}% Restore original \Cross from marvosym + rename bbding's \Cross to \bbCross.
\usepackage{relsize}
\usepackage{wasysym}
%\usepackage{growingwave}
\usepackage{growingwave}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}
\usepackage{epigraph}
%\usepackage{oni-trees}
%\usepackage{oni-tree-defaults}
\usepackage{oni-trees}
\usepackage{oni-tree-defaults}
%\usepackage[backend=bibtex,style=authoryear,natbib=true,maxbibnames=99]{biblatex}
%% User the bibtex backend with the authoryear citation style (which
%% resembles APA)
\usepackage{tikz,datetime}
\usetikzlibrary{decorations.pathreplacing,trees,calc,fit,positioning,chains,arrows,arrows.meta,automata,shapes,graphs,shapes.geometric,shapes.symbols,
decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math}
%,triangle-fit,decorations.growingwave,oni-squiggly}
decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math,triangle-fit,decorations.growingwave,oni-squiggly}
\usepackage{pgf}
\usepackage{pgfplots}
\usepackage{graphicx}
@ -113,6 +111,8 @@ decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math}
%Valuation
\def\env{\ensuremath{E}}
%% Types
\def\primtyp{\tau}
@ -413,6 +413,7 @@ subset that is disjoint from an operation's \emph{frame}, i.e. the
state subset it modifies.
\subsection{Methodology}
\label{sec:methodology}
To this end, we propose a solution based on static analysis which does not
require any additional frame annotations. By detecting the subset
@ -2241,6 +2242,235 @@ ti $\mapsto$ $\top$\\
\subsection{An inter-procedural extension}
\section{Correlation analysis}
\input{correlation-macros}
Recall from Section~\ref{sec:methodology} that our overall methodology
for tackling the frame problem consists in combining a dependency
analysis with a correlation analysis, that identifies what part of the
input is copied to the output without being modified.
%
In this section, we present a static
\emph{correlation} analysis which, when given a predicate that manipulates a
structured input, determines automatically the subset of the input that remains
unchanged and is further propagated into the output. Thus, the behaviour of a
predicate is summarised by computing relations between parts of the input and
parts of the output.
%The computed \emph{correlation summaries} are a safe
%approximation of what part of an input state of a predicate is copied to the
%output state.
The correlation analysis is a conservative static analysis inferring what is
modified by an operation and to what extent. It approximates the flow of input
values into output values, by uncovering \emph{equalities} and computing
\emph{correlations} as pairs between input parts and the output parts
into which these are injected. What is marked as being equal is
definitely equal. As equalities iin general only pertain to parts of a data
structure, we shall formalize them as \emph{partial equivalence
relations} on structured data.
\begin{figure}[!h]
\minipage[c]{\textwidth}
\centering
\centering
\begin{forest}
oni tree defaults,
[, % Start directly with a comma: no node contents
phantom,% phantom == invisible node, just here for the layout. It is the fake "common ancestor" to both trees shown in this diagram
s sep=3.5cm,% Trees have two axes for layout s (sibling), the "horizontal" axis, and l (level), the "vertical" axis. Make the two trees separated by a centimeter
%
% Do not leave blank lines, always put a % when you want to skip a line, otherwise it crashes forest
%First
[, dot tree,name=ba1, triangle fit whole subtree={bottom space=.15cm},% start squiggly tree,
[,zag=6mm,
[;$\pi$, zig=3mm,
[,name=o1, zag=3mm, triangle fit whole subtree={triangle sep=1mm, bottom space=0.01cm, iburg,}, %pattern=north east lines, pattern color=iburg},
[, name=d1, invisible tree,
]
]
]
]
[,zig=5mm,
[,zag=2mm,
[, zig=1mm,
[;$\rho$,name=g1, zag=2mm,triangle fit whole subtree={triangle sep=0.5mm, bottom space=0.01cm,draw=caribbeangreen, fill=caribbeangreen},
[, invisible tree,
]
]
]
]
]
]
%Second
[, dot tree,name=ba2, triangle fit whole subtree={bottom space=.1cm},% start squiggly tree,
[,zag=8mm
[, zig=2mm,
[,name=ax2, zag=7mm,
[,zig =2mm,
[;$\pi'$, name=o2, zag=6mm,triangle fit whole subtree={triangle sep=1mm, bottom space=0.01cm,thick, iburg},
[, name=d2, invisible tree,
]
]
]
]
]
]
[,zig=4mm
[, zag=2mm,
[;$\rho'$,name=g2, zig=1mm, triangle fit whole subtree={triangle sep=0.5mm, bottom space=0.01cm, draw=caribbeangreen, fill=caribbeangreen},
[, invisible tree,
]
]
]
]
]
]
\draw[<->, shorten=2pt, thick, caribbeangreen] (g1) edge[bend left] node[above]{$\rel'$} (g2);
\draw[<->, shorten=2pt, thick, iburg] (o1) edge[bend right, out=60] node[below]{$\rel$} (o2);
\end{forest}
\endminipage\hfill
\caption{Intraprocedural Correlations -- General Representation}
\label{cor:fig:intra}
\end{figure}
Outputs are often complex compounds of different subparts of different
input variables: a subset of the input is modified, while the rest is
injected as is. We track the origin of subparts of the output and
relate it to subparts of the input. As previously illustrated on our
\disp{stop_thread} example predicate, in order to prevent avoidable
over-approximations, we need to avoid dealing with data in a
monolithic manner. To this end, it is imperative to consider pairs of
different types and granularities as well. As a consequence, we are
forced to introduce an additional level of granularity allowing us to
refer not only to variables, but also to substructures within them. At
the intraprocedural level, illustrated in Figure~\ref{cor:fig:intra},
we define correlations as mappings between pairs of inputs and outputs
to which we associate mappings between pairs of valid inner paths and
the relations binding them. Correlations for arrays and variants are
exemplified in
Figures~\ref{fig:cor:examples}-a)~and~\ref{fig:cor:examples}-b).
\begin{figure}[!hbt]\centering
\begin{tabular}{@{}cc@{}}
\toprule
\minipage{0.38\textwidth}
\centering
\begin{tikzpicture}[thick,scale=0.5, every node/.style={scale=0.5}]
% \node[shape=multipart rectangle,parts=2] {a\second b};
\matrix[matrix of nodes, row sep=0pt, column sep=0pt] (m) {
\phantom{i} &
\phantom{i} &
|[fill=gray!20!white,alias=mi]| \large{i} &
\phantom{i} &
\phantom{i} &
\phantom{i} &
\phantom{i} &
\phantom{i} \\
};
\draw (m-1-1.north west) -- (m-1-8.north east) -- (m-1-8.south east) -- (m-1-1.south west) -- cycle;
\foreach \i in {1,...,7} {% 8 - 1 to not have double line on the last cell.
\draw (m-1-\i.north east) -- (m-1-\i.south east);
}
\matrix[matrix of nodes, row sep=0pt, column sep=0pt, right=0.5cm of m] (n) {
\phantom{i} &
\phantom{i} &
|[fill=gray!20!white,alias=ni]| \large{i} &
\phantom{i} &
\phantom{i} &
\phantom{i} &
\phantom{i} &
\phantom{i} \\
};
\draw (n-1-1.north west) -- (n-1-8.north east) -- (n-1-8.south east) -- (n-1-1.south west) -- cycle;
\foreach \i in {1,...,7} {% 8 - 1 to not have double line on the last cell.
\draw (n-1-\i.north east) -- (n-1-\i.south east);
}
\def\braceAmplitude{6pt}
\def\braceRaise{2pt}
% decoration={…,mirror,…} to have the brace the other way round
\draw (m-1-1.south west) edge[decorate,decoration={brace,amplitude=\braceAmplitude,raise=\braceRaise,mirror}] node[coordinate,yshift=8pt] (mx) {} (m-1-8.south east);
\draw (n-1-1.south west) edge[decorate,decoration={brace,amplitude=\braceAmplitude,raise=\braceRaise,mirror}] node[coordinate,yshift=8pt] (nx) {} (n-1-8.south east);
% \draw (mi.south) edge[<->,>=stealth,looseness=.5,out=-70,in=-110,shorten <=1.5pt, shorten >=1.5pt] node[below]{\large$\mathcal{R}$} (ni.south);
\draw ([yshift=-1cm]mx) edge[<->,>=stealth,looseness=.5,out=-70,in=-110] node[below]{\large$\rel$} ([yshift=-1cm]nx);
% Background:
\path[fill=white,opacity=.3]
($(mi.north west) + (0, \braceAmplitude*0.5+\braceRaise) + (0,1pt)$)
rectangle
($(mi.north east) + (0, \braceAmplitude*0.5+\braceRaise) - (0,1pt)$);
\coordinate (miX) at ($(mi.north west) + (0, \braceAmplitude*0.5+\braceRaise) + (1pt,0)$);
\coordinate (miY) at ($(mi.north east) + (0, \braceAmplitude*0.5+\braceRaise) - (.5pt,0)$);
% \foreach \i in {0,0.2,...,1} {
% \draw[black!70] ($(miX)!\i!(miY)-(1pt,1pt)$) -- ($(miX)!\i!(miY)+(1pt,1pt)$);
% }
%%%%
% Background:
\path[fill=white,opacity=.3]
($(ni.north west) + (0, \braceAmplitude*0.5+\braceRaise) + (0,1pt)$)
rectangle
($(ni.north east) + (0, \braceAmplitude*0.5+\braceRaise) - (0,1pt)$);
\coordinate (niX) at ($(ni.north west) + (0, \braceAmplitude*0.5+\braceRaise) + (1pt,0)$);
\coordinate (niY) at ($(ni.north east) + (0, \braceAmplitude*0.5+\braceRaise) - (.5pt,0)$);
\end{tikzpicture}
\endminipage
\minipage{0.35\textwidth}
\centering
\begin{tikzpicture} [thick,scale=0.55, every node/.style={scale=0.55}]
\pgfmathsetseed{\rndseed}
\triangleArray{n}{(0,0)}
\pgfmathsetseed{\rndseed}
\triangleArray{m}{($(n-0.south west) + (.5cm,-1cm)$)}
% Arrows:
\foreach \i in {0,...,\nbnodes} {%
% Centers: tc
% Top: tt, left: tl, right: tr, bottom: tb
\draw (n-tb-\i) edge[<->,>=stealth,out=-90,in=90, shorten <=.5pt, shorten >=.5pt] (m-tt-\i);
}
\end{tikzpicture}
\endminipage%
\\
\hspace{-0.1\textwidth}\minipage{0.48\textwidth}
\centering\small a) Arrays: $\;\forall i, \; a{\left[i\right]} \mathbin{\rel} b{\left[i\right]}$
\endminipage\hspace{-0.1\textwidth}
\minipage{0.25\textwidth}
\centering\small b) Variants
\endminipage
\\
\bottomrule
\end{tabular}
\caption{Intraprocedural Domain -- Examples}
\label{fig:cor:examples}
\end{figure}
Similarly to our dependency analysis presented in Chapter~\ref{chapter5}, the
correlation analysis is an interprocedural, flow-sensitive, field-sensitive,
label-sensitive analysis that handles associative arrays, structures and variant
data types. However, unlike the dependency analysis for which we introduced a
relaxed form of context-sensitivity in Chapter~\ref{chapter6}, the correlation
analysis is context-insensitive. Fine-grained equivalence relations between the
inputs and outputs of a predicate are computed once and subsequently propagated
to its callers.
Our correlation analysis is meant to be used in an interactive verification
context. Precise correlation summaries must be computed quickly in order to
answer effectively, when combined with dependency summaries, queries
regarding the preservation of certain invariants.
\subsection{Introductory example}

35
oni-tree-defaults.sty Normal file
View File

@ -0,0 +1,35 @@
\forestset{
oni tree defaults/.style={
% These options apply to all nodes in the tree
for tree={
fit=band,% Use fit=tight for a more compact tree (see the docs at http://mirrors.ctan.org/graphics/pgf/contrib/forest/forest-doc.pdf )
label style+={% style for labels next to dots:
label distance=1pt,
ellipse,
inner sep=0.5pt,
fill=white!80!black,
fill opacity=0.4,% draw a semi-transparent background
text opacity=1,% but draw the text fully opaque
},
edge label distance={1mm},
edge label node style+={% Style for labels next to edges
ellipse,
inner sep=0.5pt,
fill=white!80!black,
fill opacity=0.4,% draw a semi-transparent background
text opacity=1,% but draw the text fully opaque
},
edge label pin style={
draw=none,
% draw,
% if edge label swap={bend left}{bend right},
% densely dotted,
},
l sep=5mm,% default inter-line separation
},
for level<={3}{l sep=2mm},% Make the first three rows much thinner
% Adjust a bit the horizontal (sibbling) spacing, because the labels currently are not taken into account.
for level={4}{s sep=.5cm},
for level={5}{s sep=.5cm},
}
}

308
oni-trees.sty Normal file
View File

@ -0,0 +1,308 @@
\usetikzlibrary{decorations.markings}
% From http://tex.stackexchange.com/questions/20425/z-level-in-tikz, does not work in this case.
% \makeatletter
% \pgfkeys{%
% /tikz/on layer/.code={
% \def\tikz@path@do@at@end{\endpgfonlayer\endgroup\tikz@path@do@at@end}%
% \pgfonlayer{#1}\begingroup%
% }%
% }
% \makeatother
%%%%%%%%%%%
% Hairy stuff copied from the manual, nothing interesting to see…
\forestStandardNode[.]{%
\forestOve{\csname forest@id@of@standard node\endcsname}{content},%
\the\ht\strutbox,\the\pgflinewidth,%
\pgfkeysvalueof{/pgf/inner ysep},\pgfkeysvalueof{/pgf/outer ysep},%
\pgfkeysvalueof{/pgf/inner xsep},\pgfkeysvalueof{/pgf/outer xsep}%
}{
l sep={0},%\the\ht\strutbox+\pgfkeysvalueof{/pgf/inner ysep}},
l={l_sep()+abs(max_y()-min_y())+2*\pgfkeysvalueof{/pgf/outer ysep}},
s sep={2*\pgfkeysvalueof{/pgf/inner xsep}}
}{
l sep,l,s sep
}
%%%%%%%%%%%
% Beamer animation stuff:
\forestset{
all opacities/.style={opacity=#1,draw opacity=#1,fill opacity=#1,text opacity=#1,},
invisible/.style={
all opacities=0,
edge={/forest/all opacities=0,},
label style={/forest/all opacities=0,},
edge label node style={opacity=0,draw opacity=0,fill opacity=0,text opacity=0,},
edge label pin style={opacity=0,draw opacity=0,fill opacity=0,text opacity=0,},
},
invisible tree/.style={for tree={invisible},},
alt/.code args={<#1>#2#3}{
\alt<#1>{
\pgfkeysalso{#2}
}{
\pgfkeysalso{#3}
}
},
only/.code args={<#1>#2}{
\only<#1>{
\pgfkeysalso{#2}
}
},
only not/.code args={<#1>#2}{
\alt<#1>{
}{
\pgfkeysalso{#2}
}
},
}
\tikzset{
% only/.forward to={/forest/only},
% only not/.forward to={/forest/only not},
% all opacities/.forward to={/forest/all opacities},
all opacities/.style={opacity=#1,draw opacity=#1,fill opacity=#1,text opacity=#1,},
invisible/.style={all opacities=0,},
alt/.code args={<#1>#2#3}{
\alt<#1>{
\pgfkeysalso{#2}
}{
\pgfkeysalso{#3}
}
},
only/.code args={<#1>#2}{
\only<#1>{
\pgfkeysalso{#2}
}
},
only not/.code args={<#1>#2}{
\alt<#1>{
}{
\pgfkeysalso{#2}
}
},
}
% Handy node walk from one node to some ancestor
\forestset{
define long step={current if not name}{n args=1}{if={strequal(name("!current"),"#1")}{}{current}},
define long step={ancestors from after name until before name}{n args=2}{if={strequal("#1","#2")}{}{fake={name=#1},ancestors until before name=#2}},
define long step= {ancestors until before name}{n args=1}{if={strequal(name("!parent"),"#1")}{}{parent,ancestors until before name=#1,last valid}},
define long step={current and ancestors until before name}{n args=1}{current if not name=#1,ancestors until before name=#1},
define long step= {ancestors until name}{n args=1}{ancestors until before name=#1,name=#1},
define long step={current and ancestors until name}{n args=1}{current if not name=#1,ancestors until before name=#1,name=#1},
declare toks={highlight path/from}{},
declare toks={highlight path/to}{},
declare toks={highlight path/first}{},
declare toks={highlight path/mid}{},
declare toks={highlight path/last}{},
declare toks={highlight path/edges}{},
highlight path/.style={
highlight path/.cd,
#1
/forest/.cd,
if={strequal(\forestoption{highlight path/from}, "")}{
/utils/exec={\pgfmathsetmacro\highlightPathFrom{name()}},
highlight path/from={\highlightPathFrom},
}{
},
for name/.expanded={\forestoption{highlight path/from}}{
\forestoption{highlight path/first},
if={strequal("\foresteoption{highlight path/from}","\foresteoption{highlight path/to}")}{
}{
edge+={\forestoption{highlight path/edges},},
},
},
% For some reason, putting \foresteoption{highlight path/to} directly in
% the second argument of "for ancestors from after name until before name"
% causes an error, so we're expanding it first into a macro.
/utils/exec={\edef\highlightPathTo{\foresteoption{highlight path/to}}},
for ancestors from after name until before name/.expanded={\foresteoption{highlight path/from}}{\highlightPathTo}{
\forestoption{highlight path/mid},
edge+={\forestoption{highlight path/edges},},
},
for name/.expanded={\forestoption{highlight path/to}}{\forestoption{highlight path/last}},
},
}
% These keys are available by default only in "\begin{forest}…\end{forest}",
% but not in "\begin{tikzpicture}…\end{tikzpicture}". This is because the
% full key name is "/forest/foo", instead of "/tikz/foo", and
% "\begin{forest}" searches inside "/forest/" by default, whereas
% "\begin{tikzpicture}" searches inside "/tikz/" by default.
\tikzset{
shorten/.style={shorten <=#1, shorten >=#1,},% Convenient alias to shorten the edge on both sides by the same amount
edge label distance/.forward to={/forest/edge label distance},% Alias for the forest-specific edge label distance declared below
}
\forestset{
% Circumvent bug in if={strequal("a","b")}{}{} when a or b contain math accents.
% Because math accents are expressed with \mathaccent "1234, the extra " character
% breaks the string, and I don't see an obvious way to escape it. This bug probably
% still lurks in all uses of strequal() in this and other files.
% Note this is defined as the /forest/ifstrequal key, not as /tikz/ifstrequal
ifstrequal/.code n args={4}{
\ifthenelse{\equal{#1}{#2}}{%
\forestset{#3}%
}{%
\forestset{#4}%
}%
},%
%
% Copied and adjusted from the forest manual, section "5.1 Decision tree" page 73 of manual version 2.0.3:
% http://mirrors.ctan.org/graphics/pgf/contrib/forest/forest-doc.pdf
anchors/.style={anchor=#1, child anchor=#1, parent anchor=#1},
declare keylist={label style}{},
declare keylist={edge label node style}{},
declare keylist={edge label pin style}{},
% edge label node/.style={},
% edge label pin/.style={},
declare boolean={edge label swapped}{false},
edge label swap/.style={
if={\forestoption{edge label swapped}}{
edge label swapped=false,
}{
edge label swapped=true,
}
},
if edge label swap/.style 2 args={
if={\forestoption{edge label swapped}}{
#1
}{
#2
}
},
/tikz/if edge label swap/.style 2 args={
/forest/if={\forestoption{edge label swapped}}{
#1
}{
#2
}
},
declare dimen={edge label distance}{0pt},
dot/.default=2pt,
label content/.style={
ifstrequal={#1}{}{
% Nothing to do, label is empty.
}{
% The label is implicitly named (xxx-label), where xxx is the node's name as given with [some label, name=xxx, …]
% But it currently doesn't work
/utils/exec={\pgfmathsetmacro{\dottreenode}{name()}},
label/.expanded={[alias=\dottreenode-label,\forestoption{label style}]:#1},% #1 is the label content.
},
},
%
edge label content/.style={
% edge label/.expanded={node[\forestoption{edge label style}] {#1}},
ifstrequal={#1}{}{
% No label, nothing to do.
}{
edge={
postaction={
draw,
decorate,
decoration={
markings,
mark=at position 0.5 with {
\tikzmath{
real \edgeLabelDirection;
if \forestoption{edge label swapped} then {
\edgeLabelDirection = 1;
} else {
\edgeLabelDirection = -1;
};
}
\coordinate (-mark1) at (0,0);
\coordinate (-mark2) at (0,-\edgeLabelDirection);
\pgftransformresetnontranslations
\tikzmath{
coordinate \markdiff,\marknorm;
real \markangle;
%%
%%
\markdiff=(-mark2) - (-mark1);
\marknormx=\markdiffx / sqrt(\markdiffx*\markdiffx + \markdiffy*\markdiffy);
\marknormy=\markdiffy / sqrt(\markdiffx*\markdiffx + \markdiffy*\markdiffy);
if \markdiffy == 0 then {
if \markdiffx > 0 then {
if \forestoption{edge label swapped} then {
\markangle = 0;
} else {
\markangle = 180;
};
} else {
if \forestoption{edge label swapped} then {
\markangle = 0;
} else {
\markangle = 180;
};
};
} else {
if \markdiffy > 0 then {
\markangle = acos(\marknormx);
} else {
\markangle = 180+acos(-\marknormx);
};
};
}
\tikzset{
edge label node style exp/.style/.expanded={\forestoption{edge label node style}},
edge label pin style exp/.style/.expanded={\forestoption{edge label pin style}},
}
\path (-mark1) ++(\markangle:\forestoption{edge label distance}) node[anchor=180+\markangle, edge label node style exp] (edge label) {#1};
\path (-mark1) edge[edge label pin style exp] (edge label);%++(\markangle:\forestoption{edge label distance});
},
},
},
},
},
},
dot/.style={
% This is delayed into a second processing pass, otheriwse the "content" is re-overridden by the explicitly set content
delay={
split option={content}{;}{label content,edge label content},
content={},% Remove the content from the node, as it is typeset into a separate label node.
},
ellipse,
fill,
inner sep=0pt,
minimum size=2*#1,% You can use […, dot] to get the default radius ("dot/.default=2pt", see just above), or […, dot=5pt] to choose the radius.
},
dot tree/.style={
for tree={% These options apply to all nodes in the (sub-)tree
dot,% Draw as a dot, defined above
% Position of the label:
if n children=0{% Leaf node, has "0 children"
label style+={label position=below},
}{% Non-leaf node
if n=1{% First (leftmost) child, has "current node index = 1"
label style+={label position=left},
}{% Other child
label style+={label position=right},
},
},
% Position of the edge label:
if n=1{% First (leftmost) child, has "current node index = 1"
edge label swap,
}{% Other child
edge label swap,
},
},
label style+={label position=above},% Override the label position for the label of the root node (for this subtree).
% There is no edge label style to override for the root, as it has no incoming edge label.
},
% Zig-zag distances
declare dimen={zig distance}{.3cm},
declare dimen={Zig distance}{.5cm},
declare dimen={ZIG distance}{.7cm},
% Zigs and zags can easily be swapped globally by puting the minus "-" sign in the zigs instead of the zags, if needed.
zig/.style={edge label swap, calign with current={#1},},
zig/.default={\forestoption{zig distance}},
Zig/.style={edge label swap, calign with current={\forestoption{Zig distance}},},
ZIG/.style={edge label swap, calign with current={\forestoption{ZIG distance}}, for parent={l sep+=.2cm,},},
%
zag/.style={calign with current={-#1},},
zag/.default={\forestoption{zig distance}},
Zag/.style={calign with current={-\forestoption{Zig distance}},},
ZAG/.style={calign with current={-\forestoption{ZIG distance}}, for parent={l sep+=.2cm,},},
}

View File

@ -0,0 +1,126 @@
\usetikzlibrary{decorations.pathreplacing}
\def\pgfdecorationgrowthstart{0cm}
\def\pgfdecorationgrowthendsizelist{0cm}
\def\pgfdecorationgrowthwavelengthlist{0cm}
\def\pgfdecorationgrowthendstepslist{1}
\def\pgfdecorationgrowthendstep{1}
\newif\ifpgfdecorationgrowthsine
\newif\ifpgfdecorationgrowthcosine
\newif\ifpgfdecorationonewavelength
\pgfdecorationgrowthcosinefalse
\pgfdecorationgrowthsinetrue
\pgfkeys{%
/pgf/decoration/.cd,
growth start size/.initial=0.5cm,
growth end size/.initial=3cm,
growth end steps/.initial=1,
growth wave length/.initial=3pt,
growth sine/.code={\pgfdecorationgrowthsinetrue\pgfdecorationgrowthcosinefalse},
growth cosine/.code={\pgfdecorationgrowthsinefalse\pgfdecorationgrowthcosinetrue}
}
\def\pgfdecorationgrowthsetup{%
\global\edef\pgfdecorationgrowthstart{\pgfkeysvalueof{/pgf/decoration/growth start size}}%
\global\edef\pgfdecorationgrowthendsizelist{\pgfkeysvalueof{/pgf/decoration/growth end size}}%
\global\edef\pgfdecorationgrowthendstepslist{\pgfkeysvalueof{/pgf/decoration/growth end steps}}%
\global\edef\pgfdecorationgrowthwavelengthlist{\pgfkeysvalueof{/pgf/decoration/growth wave length}}%
}
\def\pgfdecorationgrowthsteps{1} % To keep track of steps from ending
\def\pgfdecorationliststeps{2} % To keep track of list items from ending, has to start from 2
\pgfdeclaredecoration{growth wave}{initial}%
{
\state{initial}[width=0pt,next state=first] {%
\pgfdecorationgrowthsetup%
\pgfpathlineto{\pgfqpoint{0pt}{0pt}}%
\global\edef\pgfdecorationgrowthsteps{0}%
\global\edef\pgfdecorationliststeps{2}%
\foreach \endsize in \pgfdecorationgrowthendsizelist {%
\global\edef\pgfdecorationgrowthendsize{\endsize}%
\breakforeach%
}%
\foreach \growthstep in \pgfdecorationgrowthendstepslist {%
\global\edef\pgfdecorationgrowthendstep{\growthstep}%
\breakforeach%
}%
\foreach \wavelength in \pgfdecorationgrowthwavelengthlist {%
\global\edef\pgfdecorationgrowthwavelength{\wavelength}%
\breakforeach%
}%
\pgfmathparse{(\pgfdecorationgrowthendsize - \pgfdecorationgrowthstart) * 2 * %
\pgfdecorationgrowthwavelength / ( \pgfdecoratedremainingdistance * \pgfdecorationgrowthendstep)}%
\global\edef\pgfdecorationgrowth{\pgfmathresult}%
}%
\state{first}[width=2*\pgfdecorationgrowthwavelength,next state=second] {%
\pgfdecorationgrowthstepcounters%
\pgfmathparse{\pgfdecorationgrowthstart + \pgfdecorationgrowthsteps * \pgfdecorationgrowth}%
% The wave starts
\ifpgfdecorationgrowthsine%
\pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}%
\pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}%
\fi%
\ifpgfdecorationgrowthcosine%
\pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}%
\pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}%
\fi%
\pgfdecorationgrowthstateend%
}%
\state{second}[width=2*\pgfdecorationgrowthwavelength,next state=first] {%
\pgfdecorationgrowthstepcounters%
\pgfmathparse{\pgfdecorationgrowthstart + \pgfdecorationgrowthsteps * \pgfdecorationgrowth}%
% The wave continues
\ifpgfdecorationgrowthsine%
\pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}%
\pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}%
\fi%
\ifpgfdecorationgrowthcosine%
\pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}%
\pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}%
\fi%
\pgfdecorationgrowthstateend%
}
\state{final} {%
\pgfpathlineto{\pgfpointdecoratedpathlast}%
}%
}
\def\pgfdecorationgrowthstateend{%
\pgfmathadd{\pgfdecorationgrowthsteps}{1}%
\global\edef\pgfdecorationgrowthsteps{\pgfmathresult} % Redefine the steps counter, globally.
}
\def\pgfdecorationgrowthstepcounters{%
\pgfmathparse{\pgfdecorationgrowthendstep * \pgfdecoratedpathlength}
\ifdim\pgfdecoratedcompleteddistance>\pgfmathresult pt%
\foreach \endsize [count=\count] in \pgfdecorationgrowthendsizelist {%
\ifnum\count=\pgfdecorationliststeps%
\global\edef\pgfdecorationgrowthendsize{\endsize}%
\breakforeach%
\else%
\global\edef\pgfdecorationgrowthstart{\endsize}%
\fi%
}%
\global\edef\tempa{0}%
\foreach \growthstep [count=\count] in \pgfdecorationgrowthendstepslist {%
\ifnum\count=\pgfdecorationliststeps%
\global\edef\pgfdecorationgrowthendstep{\growthstep}%
\breakforeach%
\else%
\global\edef\tempa{\growthstep}%
\fi%
}%
\foreach \wavelength [count=\count] in \pgfdecorationgrowthwavelengthlist {%
\ifnum\count=\pgfdecorationliststeps%
\global\edef\pgfdecorationgrowthwavelength{\wavelength}%
\breakforeach%
\fi%
}%
\pgfmathparse{int(\pgfdecorationliststeps+1)}%
\global\edef\pgfdecorationliststeps{\pgfmathresult}%
\global\edef\pgfdecorationgrowthsteps{0}% Redefine the steps counter, globally.
\pgfmathparse{(\pgfdecorationgrowthendsize-\pgfdecorationgrowthstart) * 2 %
* \pgfdecorationgrowthwavelength / (\pgfdecoratedpathlength * (\pgfdecorationgrowthendstep -\tempa))}%
\global\edef\pgfdecorationgrowth{\pgfmathresult}%
\fi%
}

View File

@ -0,0 +1,83 @@
\usetikzlibrary{decorations.growingwave}
\tikzset{
small squiggly line fade in/.style={
-,% No arrow head
shorten >=0pt,%%%%%%%%%%%%%%%%%%%%%%%%%
decorate,
decoration={
growth wave,
growth start size=0pt,
growth end size=-1pt,%{-1pt,-1pt,0pt},%%%%%%%%%
% growth end steps={0.6,.7},
%growth end steps={0.2,0.6,1},%%%%%%%%
growth wave length=1pt,%{1pt,1pt,1pt},%%%%%
growth cosine,
% pre length=5mm,
post length=0mm,%%%%%%%%%%%%%%%%%%%%%%
},
},
small squiggly line no fade/.style={
-,% No arrow head
shorten >=0pt,%%%%%%%%%%%%%%%%%%%%%%%%%
decorate,
decoration={
growth wave,
growth start size=-1pt,
growth end size=-1pt,%{-1pt,-1pt,0pt},%%%%%%%%%
% growth end steps={0.6,.7},
% growth end steps={0.2,0.6,1},
growth wave length=1pt,%{1pt,1pt,1pt},%%%%%
growth cosine,
pre length=1pt,%%%%%%%%%%%%%%%%
post length=1pt,%%%%%%%%%%%%%%%%%%%%%%
},
},
squiggly line/.style={
-,% No arrow head
shorten >=0pt,%%%%%%%%%%%%%%%%%%%%%%%%%
decorate,
decoration={
growth wave,
growth start size=0pt,
growth end size=2pt,%{3pt,0pt},
% growth end steps={0.6,.7},
% growth end steps={0.8,1},
growth wave length=2pt,%{2pt,1pt},
growth cosine,
% pre length=5mm,
post length=0mm%%%%%%%%%%%%%%%%%%%%%%
},
},
squiggly arrow/.style={
->,
shorten >=1.5pt,
decorate,
decoration={
growth wave,
growth start size=0pt,
growth end size=2pt,%{3pt,0pt},
% growth end steps={0.6,.7},
% growth end steps={0.8,1},
growth wave length=2pt,%{2pt,1pt},
growth cosine,
% pre length=5mm,
post length=2mm
},
},
}
\tikzset{
/forest/.cd, % Set forest styles
start squiggly tree/.style={
for children={
edge={small squiggly line fade in,},
continue squiggly tree,
}
},
continue squiggly tree/.style={
for children={
edge={small squiggly line no fade,},
continue squiggly tree,
}
}
}

View File

@ -0,0 +1,184 @@
% %%%%%%%
% % From http://tex.stackexchange.com/questions/314053/how-to-declare-a-tikz-directory-or-group-of-keys/314065?noredirect=1#comment765927_314065
% \pgfkeys{
% /handlers/.is directory/.code={
% \pgfkeysedef{\pgfkeyscurrentpath}{
% \noexpand\pgfkeys{\pgfkeyscurrentpath/.cd,##1}
% }
% }
% }
% %%%%%%%
\ifx\pgfmathsign\relax%
\tikzmath{
function sign(\x) {
if (\x < 0) then {
return -1;
} else {
if (\x > 0) then {
return 1;
} else {
return 0;
};
};
};
}
\fi%
\newif\iftrianglefitisosceles
\newif\iftrianglefitbackground
\tikzset{
triangle fit current style/.style={},
triangle fit current background style/.style={},
triangle fit/.unknown/.code={
% \message{triangle fit unknown:\pgfkeyscurrentkeyRAW=#1^^J}
\let\trianglefitstorekey=\pgfkeyscurrentkeyRAW
\edef\triangleExp{
\noexpand\tikzset{
/tikz/triangle fit current style/.append style={
\trianglefitstorekey=\noexpand#1
}
}
}
\triangleExp
%\pgfqkeys{/tikz}{}
},
triangle fit/triangle sep/.initial=0.15em,
triangle fit/triangle sep/.default=0.15em,
triangle fit/top space/.initial=1.5ex,
triangle fit/top space/.default=1.5ex,
triangle fit/bottom space/.initial=0ex,
triangle fit/bottom space/.default=0ex,
triangle fit/top/.initial=,
triangle fit/nodes/.initial=,
triangle fit/no rounded corners/.style={/tikz/rounded corners=0pt},
every triangle fit/.style={
triangle sep=.15em,
rounded corners=5pt,
isosceles,
},
triangle fit/isosceles/.is if=trianglefitisosceles,
triangle fit/not isosceles/.style={isosceles=false},
triangle fit/bg/.code={
\tikzset{
triangle fit current background style/.style={#1},
}
},
triangle fit/.code={
\tikzset{
/tikz/triangle fit current style/.style={},
/tikz/triangle fit/.cd,
/tikz/every triangle fit,
#1,
}
% \node[draw, /tikz/every triangle fit] {EEE}
% \edef\currenttrianglestyle{\pgfkeysvalueof{/tikz/triangle fit/style}}
% \message{\currenttrianglestyle}
% \tikzset{
% triangle fit current style/.style=\currenttrianglestyle,
% }
% Compute the minimum and maxiumum slope, as well as the maximum y (i.e. height) for the triangle.
\tikzmath{
coordinate \pt,\ttop;
% int \found;
% \found{top} = 0;
% \found{bot} = 0;
\ttop=([yshift=\pgfkeysvalueof{/tikz/triangle fit/top space}]\pgfkeysvalueof{/tikz/triangle fit/top});
\slopeleft = 0;
\sloperight = 0;
\maxdy = 0;
}
% Foreach loop over all nodes, which computes the max and min slopes and triangle height
\edef\triangleFitItems{\pgfkeysvalueof{/tikz/triangle fit/nodes}}
\foreach \i in \triangleFitItems{
\foreach \ii in {(\i.north east),(\i.south east),(\i.south west),(\i.north west)} {
\tikzmath{
\pt = \ii;
\dx = \ptx - \ttopx;
\dx = \dx + \pgfkeysvalueof{/tikz/triangle fit/triangle sep} * sign(\dx);
\dy = \ttopy - \pty;
\dy = \dy + \pgfkeysvalueof{/tikz/triangle fit/triangle sep} * sign(\dy);
\slope = \dx / \dy;
if \slope > \sloperight then {
\sloperight = \slope;
};
if \slope < \slopeleft then {
\slopeleft = \slope;
};
if \dy > \maxdy then {
\maxdy = \dy;
};
}
\global\let\sloperight\sloperight%
\global\let\slopeleft\slopeleft%
\global\let\maxdy\maxdy%
% \message{\ii, ptx=\ptx, pty=\pty, dx=\dx, dy=\dy, slope=\slope, sloperight=\sloperight, slopeleft=\slopeleft, maxdy=\maxdy^^J}
}
}
\tikzmath{
\maxdy = \maxdy + \pgfkeysvalueof{/tikz/triangle fit/bottom space};
}
\iftrianglefitisosceles
\tikzmath{
if -\sloperight < \slopeleft then {
\slopeleft = -\sloperight;
};
if -\slopeleft > \sloperight then {
\sloperight = -\slopeleft;
};
}
\fi
% Draw the triangle:
\draw[/tikz/triangle fit current style]
(\ttopx,\ttopy)
-- +(\sloperight*\maxdy pt,-\maxdy pt)
-- +(\slopeleft*\maxdy pt,-\maxdy pt)
-- cycle;
% Draw the background
\begin{pgfonlayer}{background}
\path[/tikz/triangle fit current background style]
(\ttopx,\ttopy)
-- +(\sloperight*\maxdy pt,-\maxdy pt)
-- +(\slopeleft*\maxdy pt,-\maxdy pt)
-- cycle;
\end{pgfonlayer}
}
}
\def\nodx{
node[draw, every triangle fit, triangle fit={top={\fittriangletop},nodes={\fittriangletop\foresteoption{fit these}}}] {nodes:\fittriangletop\foresteoption{fit these}}
}
% \forestset{
% % every triangle fit/.forward to=/tikz/every triangle fit,
% every triangle fit/append/.forward to=/tikz/every triangle fit/append,
% every triangle fit/style/.forward to=/tikz/every triangle fit/style,
% declare toks={fit these}{},
% triangle fit whole subtree/.style={
% delay={
% temptoksa=,
% for descendants={%
% temptoksa+/.wrap pgfmath arg={,##1}{name()},
% },
% fit these/.register=temptoksa,
% delay={
% % /utils/exec={
% % \pgfmathsetmacro{\fittriangletop}{name()}
% % \message{^^JFIT THESE=\foresteoption{fit these}, NAME=\fittriangletop^^J}
% % },
% % append after command={
% % \nodx
% % },
% tikz+={
% \pgfmathsetmacro{\fittriangletop}{name()}
% % \message{\foresteoption{fit these}}
% \path[triangle fit={
% top=\fittriangletop.north,
% nodes={\fittriangletop\foresteoption{fit these}},
% #1
% }];
% },
% },
% },
% },
% }

View File

@ -0,0 +1,191 @@
% %%%%%%%
% % From http://tex.stackexchange.com/questions/314053/how-to-declare-a-tikz-directory-or-group-of-keys/314065?noredirect=1#comment765927_314065
% \pgfkeys{
% /handlers/.is directory/.code={
% \pgfkeysedef{\pgfkeyscurrentpath}{
% \noexpand\pgfkeys{\pgfkeyscurrentpath/.cd,##1}
% }
% }
% }
% %%%%%%%
\ifx\pgfmathsign\relax%
\tikzmath{
function sign(\x) {
if (\x < 0) then {
return -1;
} else {
if (\x > 0) then {
return 1;
} else {
return 0;
};
};
};
}
\fi%
\newif\iftrianglefitisosceles
\newif\iftrianglefitbackground
\tikzset{
triangle fit current style/.style={},
triangle fit current background style/.style={},
triangle fit/.unknown/.code={
% \message{triangle fit unknown:\pgfkeyscurrentkeyRAW=#1^^J}
\let\trianglefitstorekey=\pgfkeyscurrentkeyRAW
\edef\triangleExp{
\noexpand\tikzset{
/tikz/triangle fit current style/.append style={
\trianglefitstorekey=\noexpand#1
}
}
}
\triangleExp
%\pgfqkeys{/tikz}{}
},
triangle fit/triangle sep/.initial=0.15em,
triangle fit/triangle sep/.default=0.15em,
triangle fit/top space/.initial=1.5ex,
triangle fit/top space/.default=1.5ex,
triangle fit/top xshift/.initial=0pt,
triangle fit/top xshift/.default=0pt,
triangle fit/bottom space/.initial=0ex,
triangle fit/bottom space/.default=0ex,
triangle fit/top/.initial=,
triangle fit/nodes/.initial=,
triangle fit/no rounded corners/.style={/tikz/rounded corners=0pt},
every triangle fit/.style={
triangle sep=.15em,
rounded corners=5pt,
isosceles,
},
triangle fit/isosceles/.is if=trianglefitisosceles,
triangle fit/not isosceles/.style={isosceles=false},
triangle fit/bg+/.code={
\tikzset{
triangle fit current background style/.style={#1},
}
},
triangle fit/.code={
\tikzset{
/tikz/triangle fit current style/.style={},
/tikz/triangle fit/.cd,
/tikz/every triangle fit,
#1,
}
% \node[draw, /tikz/every triangle fit] {EEE}
% \edef\currenttrianglestyle{\pgfkeysvalueof{/tikz/triangle fit/style}}
% \message{\currenttrianglestyle}
% \tikzset{
% triangle fit current style/.style=\currenttrianglestyle,
% }
% Compute the minimum and maxiumum slope, as well as the maximum y (i.e. height) for the triangle.
\tikzmath{
coordinate \pt,\ttop;
% int \found;
% \found{top} = 0;
% \found{bot} = 0;
\ttop=(\pgfkeysvalueof{/tikz/triangle fit/top}) + (\pgfkeysvalueof{/tikz/triangle fit/top xshift},\pgfkeysvalueof{/tikz/triangle fit/top space}+\pgfkeysvalueof{/tikz/triangle fit/triangle sep});
\slopeleft = 0;
\sloperight = 0;
\maxdy = 0;
}
% Foreach loop over all nodes, which computes the max and min slopes and triangle height
\edef\triangleFitItems{\pgfkeysvalueof{/tikz/triangle fit/nodes}}
\foreach \i in \triangleFitItems{
\foreach \ii/\sgx/\sgy in {(\i.north east)/1/1,(\i.south east)/1/-1,(\i.south west)/-1/-1,(\i.north west)/-1/1} {
\tikzmath{
\pt = \ii;
\dx = \ptx - \ttopx;
\dx = \dx + \pgfkeysvalueof{/tikz/triangle fit/triangle sep} * \sgx;%sign(\dx);
\dy = \ttopy - \pty;
\dy = \dy + \pgfkeysvalueof{/tikz/triangle fit/triangle sep} * \sgy;%sign(\dy);
\slope = \dx / \dy;
if \slope > \sloperight then {
\sloperight = \slope;
};
if \slope < \slopeleft then {
\slopeleft = \slope;
};
if \dy > \maxdy then {
\maxdy = \dy;
};
}
% \begin{pgfonlayer}{foreground}
% \path (\ttopx,\ttopy) ++(\dx pt,-\dy pt) node[fill=blue,circle,inner sep=0.3pt] {};
% \end{pgfonlayer}
\global\let\sloperight\sloperight%
\global\let\slopeleft\slopeleft%
\global\let\maxdy\maxdy%
% \message{\ii, ptx=\ptx, pty=\pty, dx=\dx, dy=\dy, slope=\slope, sloperight=\sloperight, slopeleft=\slopeleft, maxdy=\maxdy^^J}
}
}
\tikzmath{
\maxdy = \maxdy + \pgfkeysvalueof{/tikz/triangle fit/bottom space};
}
\iftrianglefitisosceles
\tikzmath{
if -\sloperight < \slopeleft then {
\slopeleft = -\sloperight;
};
if -\slopeleft > \sloperight then {
\sloperight = -\slopeleft;
};
}
\fi
% Draw the background
\begin{pgfonlayer}{background}
\path[/tikz/triangle fit current style, /tikz/triangle fit current background style]
(\ttopx,\ttopy)
-- +(\sloperight*\maxdy pt,-\maxdy pt)
-- +(\slopeleft*\maxdy pt,-\maxdy pt)
-- cycle;
\end{pgfonlayer}
%
% Draw the triangle:
\begin{pgfonlayer}{background}% Draw it on the background, it gives better results for now.
\draw[/tikz/triangle fit current style]
(\ttopx,\ttopy)
-- +(\sloperight*\maxdy pt,-\maxdy pt)
-- +(\slopeleft*\maxdy pt,-\maxdy pt)
-- cycle;
\end{pgfonlayer}
}
}
\def\nodx{
node[draw, every triangle fit, triangle fit={top={\fittriangletop},nodes={\fittriangletop\foresteoption{fit these}}}] {nodes:\fittriangletop\foresteoption{fit these}}
}
\forestset{
% every triangle fit/.forward to=/tikz/every triangle fit,
every triangle fit/append/.forward to=/tikz/every triangle fit/append,
every triangle fit/style/.forward to=/tikz/every triangle fit/style,
declare toks={fit these}{},
triangle fit whole subtree/.style={
delay={
temptoksa=,
for descendants={%
temptoksa+/.wrap pgfmath arg={,##1}{name()},
},
fit these/.register=temptoksa,
delay={
% /utils/exec={
% \pgfmathsetmacro{\fittriangletop}{name()}
% \message{^^JFIT THESE=\foresteoption{fit these}, NAME=\fittriangletop^^J}
% },
% append after command={
% \nodx
% },
tikz+={
\pgfmathsetmacro{\fittriangletop}{name()}
% \message{\foresteoption{fit these}}
\path[triangle fit={
top=\fittriangletop.parent anchor,
nodes={\fittriangletop\foresteoption{fit these}},
#1
}];
},
},
},
},
}

Binary file not shown.