PageSourceSearch

https://skewed.de/lab/blog.html

html skewed.de collected 2026-10-01 11:38:33 UTC 59,713 bytes, 1,302 lines download raw bytes

1<!DOCTYPE html>
2<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
3
4<meta charset="utf-8">
5<meta name="generator" content="quarto-1.9.38">
6
7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
8
9
10<title>Inverse Complexity Blog – Inverse Complexity Lab</title>
11<style>
12/* Default styles provided by pandoc.
13** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
14*/
15code{white-space: pre-wrap;}
16span.smallcaps{font-variant: small-caps;}
17div.columns{display: flex; gap: min(4vw, 1.5em);}
18div.column{flex: auto; overflow-x: auto;}
19div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
20ul.task-list{list-style: none;}
21ul.task-list li input[type="checkbox"] {
22  width: 0.8em;
23  margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 
24  vertical-align: middle;
25}
26</style>
27
28
29<script src="site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 29
29
30<script src="site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 30
30
31<script src="site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 31
31
32<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 32
32
33<script src="site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 33
33
34<script src="site_libs/quarto-search/quarto-search.js"></script>
34
35<meta name="quarto:offset" content="./">
36<link href="./static/z-bob.png" rel="icon" type="image/png">
37<script src="site_libs/quarto-listing/list.min.js"></script>
vendor: 1 bytes, line 37
37
38<script src="site_libs/quarto-listing/quarto-listing.js"></script>
vendor: 1 bytes, line 38
38
39<script src="site_libs/quarto-html/quarto.js" type="module"></script>
vendor: 1 bytes, line 39
39
40<script src="site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
vendor: 1 bytes, line 40
40
41<script src="site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 41
41
42<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
vendor: 1 bytes, line 42
42
43<script src="site_libs/quarto-html/anchor.min.js"></script>
43
44<link href="site_libs/quarto-html/tippy.css" rel="stylesheet">
45<link href="site_libs/quarto-html/quarto-syntax-highlighting-15634bcf2e68342d4ad2dfa704d543f6.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
46<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark-0a6b7249c26820e032cb0bd839ff02b1.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
47<script src="site_libs/bootstrap/bootstrap.min.js"></script>
47
48<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
49<link href="site_libs/bootstrap/bootstrap-b3ab709b0f252e93e09bc847c3e05092.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
50<link href="site_libs/bootstrap/bootstrap-dark-559642fb5ad3f5d0a8c1e1b3b723f4e8.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
51<script id="quarto-search-options" type="application/json">{
52  "location": "navbar",
53  "copy-button": false,
54  "collapse-after": 3,
55  "panel-placement": "end",
56  "type": "overlay",
57  "limit": 50,
58  "keyboard-shortcut": [
59    "f",
60    "/",
61    "s"
62  ],
63  "show-item-context": false,
64  "language": {
65    "search-no-results-text": "No results",
66    "search-matching-documents-text": "matching documents",
67    "search-copy-link-title": "Copy link to search",
68    "search-hide-matches-text": "Hide additional matches",
69    "search-more-match-text": "more match in this document",
70    "search-more-matches-text": "more matches in this document",
71    "search-clear-button-title": "Clear",
72    "search-text-placeholder": "",
73    "search-detached-cancel-button-title": "Cancel",
74    "search-submit-button-title": "Submit",
75    "search-label": "Search"
76  }
77}</script>
vendor: 1 bytes, line 77
77
78<script>
79
80  window.document.addEventListener("DOMContentLoaded", function (_event) {
81    const listingTargetEl = window.document.querySelector('#listing-listing .list');
82    if (!listingTargetEl) {
83      // No listing discovered, do not attach.
84      return; 
85    }
86
87    const options = {
88      valueNames: ['listing-title','listing-author','listing-date','listing-image','listing-description','listing-categories',{ data: ['index'] },{ data: ['categories'] },{ data: ['listing-date-sort'] },{ data: ['listing-file-modified-sort'] }],
89      
90      searchColumns: ["listing-title","listing-author","listing-date","listing-image","listing-description","listing-categories"],
91    };
92
93    window['quarto-listings'] = window['quarto-listings'] || {};
94    window['quarto-listings']['listing-listing'] = new List('listing-listing', options);
95
96    if (window['quarto-listing-loaded']) {
97      window['quarto-listing-loaded']();
98    }
99  });
100
101  window.addEventListener('hashchange',() => {
102    if (window['quarto-listing-loaded']) {
103      window['quarto-listing-loaded']();
104    }
105  })
106  </script>
106
107<style>html{ scroll-behavior: smooth; }</style>
108<meta name="fediverse:creator" content="@[email protected]">
109<link rel="alternate" type="application/rss+xml" title="Inverse Complexity Lab" href="blog.xml" data-external="1"><meta property="og:title" content="Inverse Complexity Blog – Inverse Complexity Lab">
110<meta property="og:description" content="Research group on inverse problems in complex systems and network science.">
111<meta property="og:image" content="https://skewed.de/lab/static/research/foodweb-wsbm-lognormal.png">
112<meta property="og:site_name" content="Inverse Complexity Lab">
113<meta property="og:image:height" content="800">
114<meta property="og:image:width" content="800">
115<meta name="twitter:title" content="Inverse Complexity Blog – Inverse Complexity Lab">
116<meta name="twitter:description" content="Research group on inverse problems in complex systems and network science.">
117<meta name="twitter:image" content="https://skewed.de/lab/static/research/foodweb-wsbm-lognormal.png">
118<meta name="twitter:creator" content="@tiagopeixoto">
119<meta name="twitter:site" content="@tiagopeixoto">
120<meta name="twitter:image-height" content="800">
121<meta name="twitter:image-width" content="800">
122<meta name="twitter:card" content="summary_large_image">
123</head><body class="nav-fixed quarto-dark">
123<script id="quarto-html-before-body" type="application/javascript">
124    const toggleBodyColorMode = (bsSheetEl) => {
125      const mode = bsSheetEl.getAttribute("data-mode");
126      const bodyEl = window.document.querySelector("body");
127      if (mode === "dark") {
128        bodyEl.classList.add("quarto-dark");
129        bodyEl.classList.remove("quarto-light");
130      } else {
131        bodyEl.classList.add("quarto-light");
132        bodyEl.classList.remove("quarto-dark");
133      }
134    }
135    const toggleBodyColorPrimary = () => {
136      const bsSheetEl = window.document.querySelector("link#quarto-bootstrap:not([rel=disabled-stylesheet])");
137      if (bsSheetEl) {
138        toggleBodyColorMode(bsSheetEl);
139      }
140    }
141    const setColorSchemeToggle = (alternate) => {
142      const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
143      for (let i=0; i < toggles.length; i++) {
144        const toggle = toggles[i];
145        if (toggle) {
146          if (alternate) {
147            toggle.classList.add("alternate");
148          } else {
149            toggle.classList.remove("alternate");
150          }
151        }
152      }
153    };
154    const toggleColorMode = (alternate) => {
155      // Switch the stylesheets
156      const primaryStylesheets = window.document.querySelectorAll('link.quarto-color-scheme:not(.quarto-color-alternate)');
157      const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
158      manageTransitions('#quarto-margin-sidebar .nav-link', false);
159      if (alternate) {
160        // note: dark is layered on light, we don't disable primary!
161        enableStylesheet(alternateStylesheets);
162        for (const sheetNode of alternateStylesheets) {
163          if (sheetNode.id === "quarto-bootstrap") {
164            toggleBodyColorMode(sheetNode);
165          }
166        }
167      } else {
168        disableStylesheet(alternateStylesheets);
169        enableStylesheet(primaryStylesheets)
170        toggleBodyColorPrimary();
171      }
172      manageTransitions('#quarto-margin-sidebar .nav-link', true);
173      // Switch the toggles
174      setColorSchemeToggle(alternate)
175      // Hack to workaround the fact that safari doesn't
176      // properly recolor the scrollbar when toggling (#1455)
177      if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
178        manageTransitions("body", false);
179        window.scrollTo(0, 1);
180        setTimeout(() => {
181          window.scrollTo(0, 0);
182          manageTransitions("body", true);
183        }, 40);
184      }
185    }
186    const disableStylesheet = (stylesheets) => {
187      for (let i=0; i < stylesheets.length; i++) {
188        const stylesheet = stylesheets[i];
189        stylesheet.rel = 'disabled-stylesheet';
190      }
191    }
192    const enableStylesheet = (stylesheets) => {
193      for (let i=0; i < stylesheets.length; i++) {
194        const stylesheet = stylesheets[i];
195        if(stylesheet.rel !== 'stylesheet') { // for Chrome, which will still FOUC without this check
196          stylesheet.rel = 'stylesheet';
197        }
198      }
199    }
200    const manageTransitions = (selector, allowTransitions) => {
201      const els = window.document.querySelectorAll(selector);
202      for (let i=0; i < els.length; i++) {
203        const el = els[i];
204        if (allowTransitions) {
205          el.classList.remove('notransition');
206        } else {
207          el.classList.add('notransition');
208        }
209      }
210    }
211    const isFileUrl = () => {
212      return window.location.protocol === 'file:';
213    }
214    const hasAlternateSentinel = () => {
215      let styleSentinel = getColorSchemeSentinel();
216      if (styleSentinel !== null) {
217        return styleSentinel === "alternate";
218      } else {
219        return false;
220      }
221    }
222    const setStyleSentinel = (alternate) => {
223      const value = alternate ? "alternate" : "default";
224      if (!isFileUrl()) {
225        window.localStorage.setItem("quarto-color-scheme", value);
226      } else {
227        localAlternateSentinel = value;
228      }
229    }
230    const getColorSchemeSentinel = () => {
231      if (!isFileUrl()) {
232        const storageValue = window.localStorage.getItem("quarto-color-scheme");
233        return storageValue != null ? storageValue : localAlternateSentinel;
234      } else {
235        return localAlternateSentinel;
236      }
237    }
238    const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => {
239      const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
240      const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
241      let newTheme = '';
242      if(authorPrefersDark) {
243        newTheme = isAlternate ? baseTheme : alternateTheme;
244      } else {
245        newTheme = isAlternate ? alternateTheme : baseTheme;
246      }
247      const changeGiscusTheme = () => {
248        // From: https://github.com/giscus/giscus/issues/336
249        const sendMessage = (message) => {
250          const iframe = document.querySelector('iframe.giscus-frame');
251          if (!iframe) return;
252          iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
253        }
254        sendMessage({
255          setConfig: {
256            theme: newTheme
257          }
258        });
259      }
260      const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null;
261      if (isGiscussLoaded) {
262        changeGiscusTheme();
263      }
264    };
265    const authorPrefersDark = true;
266    const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
267    const darkModeDefault = queryPrefersDark.matches;
268    let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
269    // Dark / light mode switch
270    window.quartoToggleColorScheme = () => {
271      // Read the current dark / light value
272      let toAlternate = !hasAlternateSentinel();
273      toggleColorMode(toAlternate);
274      setStyleSentinel(toAlternate);
275      toggleGiscusIfUsed(toAlternate, darkModeDefault);
276      window.dispatchEvent(new Event('resize'));
277    };
278    queryPrefersDark.addEventListener("change", e => {
279      if(window.localStorage.getItem("quarto-color-scheme") !== null)
280        return;
281      const alternate = e.matches
282      toggleColorMode(alternate);
283      localAlternateSentinel = e.matches ? 'alternate' : 'default'; // this is used alongside local storage!
284      toggleGiscusIfUsed(alternate, darkModeDefault);
285    });
286    // Switch to dark mode if need be
287    if (hasAlternateSentinel()) {
288      toggleColorMode(true);
289    } else {
290      toggleColorMode(false);
291    }
292  </script>
292<span class="syndications"><link rel="webmention" href="https://webmention.io/skewed.de/webmention"></span>
293<link rel="authorization_endpoint" href="https://indieauth.com/auth">
294<link rel="token_endpoint" href="https://tokens.indieauth.com/token">
295
296  
296<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=es6"></script>
296
297  
297<script defer="" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" type="text/javascript"></script>
297
298
299<script type="text/javascript">
300const typesetMath = (el) => {
301  if (window.MathJax) {
302    // MathJax Typeset
303    window.MathJax.typeset([el]);
304  } else if (window.katex) {
305    // KaTeX Render
306    var mathElements = el.getElementsByClassName("math");
307    var macros = [];
308    for (var i = 0; i < mathElements.length; i++) {
309      var texText = mathElements[i].firstChild;
310      if (mathElements[i].tagName == "SPAN" && texText && texText.data) {
311        window.katex.render(texText.data, mathElements[i], {
312          displayMode: mathElements[i].classList.contains('display'),
313          throwOnError: false,
314          macros: macros,
315          fleqn: false
316        });
317      }
318    }
319  }
320}
321window.Quarto = {
322  typesetMath
323};
324</script>
324
325
326<link rel="stylesheet" href="styles.css">
327<link rel="stylesheet" href="static/css/fonts.css">
328<link rel="stylesheet" href="site_libs/quarto-contrib/quarto-project/bethanyhgardner/fontawesome/assets/css/all.css">
329<link rel="stylesheet" href="site_libs/quarto-contrib/quarto-project/schochastics/academicons/assets/css/all.css">
330
331
332
333
334<div id="quarto-search-results"></div>
335  <header id="quarto-header" class="headroom fixed-top">
336    <nav class="navbar navbar-expand-lg " data-bs-theme="dark">
337      <div class="navbar-container container-fluid">
338      <div class="navbar-brand-container mx-auto">
339    <a href="./index.html" class="navbar-brand navbar-brand-logo">
340    <img src="./static/research/foodweb-wsbm-lognormal.svg" alt="" class="navbar-logo light-content">
341    <img src="./static/research/foodweb-wsbm-lognormal.svg" alt="" class="navbar-logo dark-content">
342    </a>
343    <a class="navbar-brand" href="./index.html">
344    <span class="navbar-title">Inverse Complexity Lab</span>
345    </a>
346  </div>
347            <div id="quarto-search" class="" title="Search"></div>
348          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
349  <span class="navbar-toggler-icon"></span>
350</button>
351          <div class="collapse navbar-collapse" id="navbarCollapse">
352            <ul class="navbar-nav navbar-nav-scroll ms-auto">
353  <li class="nav-item">
354    <a class="nav-link" href="./tiago.html"> 
355<span class="menu-text">Tiago P. Peixoto</span></a>
356  </li>  
357  <li class="nav-item">
358    <a class="nav-link" href="./research.html"> 
359<span class="menu-text">Research</span></a>
360  </li>  
361  <li class="nav-item">
362    <a class="nav-link" href="./publications.html"> 
363<span class="menu-text">Publications</span></a>
364  </li>  
365  <li class="nav-item">
366    <a class="nav-link" href="./group.html"> 
367<span class="menu-text">Group members</span></a>
368  </li>  
369  <li class="nav-item">
370    <a class="nav-link" href="./software.html"> 
371<span class="menu-text">Software &amp; data</span></a>
372  </li>  
373  <li class="nav-item">
374    <a class="nav-link" href="./courses.html"> 
375<span class="menu-text">Courses</span></a>
376  </li>  
377  <li class="nav-item">
378    <a class="nav-link active" href="./blog.html" aria-current="page"> 
379<span class="menu-text">Blog</span></a>
380  </li>  
381  <li class="nav-item">
382    <a class="nav-link" href="./manual"> 
383<span class="menu-text">Manual</span></a>
384  </li>  
385  <li class="nav-item compact">
386    <a class="nav-link" href="./blog.xml"> <i class="bi bi-rss" role="img">
387</i> 
388<span class="menu-text"></span></a>
389  </li>  
390  <li class="nav-item">
391    <a class="nav-link" href="https://graph-tool.skewed.de"> 
392<span class="menu-text"><img src="./static/graph-tool-logo-circle.svg" style="vertical-align: -.3em;height:1.3em"></span></a>
393  </li>  
394</ul>
395          </div> <!-- /navcollapse -->
396            <div class="quarto-navbar-tools">
397  <a href="" class="quarto-color-scheme-toggle quarto-navigation-tool  px-1" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a>
398</div>
399      </div> <!-- /container-fluid -->
400    </nav>
401</header>
402<!-- content -->
403<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
404<!-- sidebar -->
405<!-- margin-sidebar -->
406    <div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
407        
408    <h5 class="quarto-listing-category-title">Categories</h5><div class="quarto-listing-category category-default"><div class="category" data-category="">All <span class="quarto-category-count">(12)</span></div><div class="category" data-category="YXBvcGhlbmlh">apophenia <span class="quarto-category-count">(1)</span></div><div class="category" data-category="QmF5ZXM=">Bayes <span class="quarto-category-count">(8)</span></div><div class="category" data-category="Y29tbXVuaXR5JTIwZGV0ZWN0aW9u">community detection <span class="quarto-category-count">(9)</span></div><div class="category" data-category="Y29tcHJlc3Npb24=">compression <span class="quarto-category-count">(4)</span></div><div class="category" data-category="ZGVzY3JpcHRpb24=">description <span class="quarto-category-count">(2)</span></div><div class="category" data-category="ZnJlZSUyMGx1bmNo">free lunch <span class="quarto-category-count">(2)</span></div><div class="category" data-category="aGFpcmJhbGw=">hairball <span class="quarto-category-count">(1)</span></div><div class="category" data-category="aGV1cmlzdGljcw==">heuristics <span class="quarto-category-count">(1)</span></div><div class="category" data-category="aGlnaGVyLW9yZGVy">
408higher-order <span class="quarto-category-count">(1)</span></div><div class="category" data-category="aHlwZQ==">hype <span class="quarto-category-count">(1)</span></div><div class="category" data-category="aHlwZXJncmFwaHM=">hypergraphs <span class="quarto-category-count">(1)</span></div><div class="category" data-category="aHlwZXJzbG9w">hyperslop <span class="quarto-category-count">(1)</span></div><div class="category" data-category="aW5mZXJlbmNl">inference <span class="quarto-category-count">(6)</span></div><div class="category" data-category="TURM">MDL <span class="quarto-category-count">(4)</span></div><div class="category" data-category="bWVhbi1maWVsZA==">mean-field <span class="quarto-category-count">(1)</span></div><div class="category" data-category="bWVtZXM=">memes <span class="quarto-category-count">(1)</span></div><div class="category" data-category="bWV0aG9kb2xvZ2ljYWwlMjBpbXBlcmlhbGlzbQ==">methodological imperialism <span class="quarto-category-count">(1)</span></div><div class="category" data-category="bW9kdWxhcml0eQ==">modularity <span class="quarto-category-count">(2)</span></div><div class="category" data-category="bmV0d29yayUyMHZpc3VhbGl6YXRpb24=">network visualization <span class="quarto-category-count">(1)</span></div><div class="category" data-category="b3ZlcmZpdHRpbmc=">overfitting <span class="quarto-category-count">(3)</span></div><div class="category" data-category="cmVjb25zdHJ1Y3Rpb24=">reconstruction <span class="quarto-category-count">(1)</span></div><div class="category" data-category="cmlkaWN1bG9ncmFt">ridiculogram <span class="quarto-category-count">(1)</span></div><div class="category" data-category="U0JN">SBM <span class="quarto-category-count">(4)</span></div><div class="category" data-category="c3RhdGlzdGljYWwlMjBzaWduaWZpY2FuY2U=">statistical significance <span class="quarto-category-count">(1)</span></div><div class="category" data-category="c3ViamVjdGl2aXR5">subjectivity <span class="quarto-category-count">(1)</span></div></div></div>
409<!-- main -->
410<main class="content" id="quarto-document-content">
411
412
413<header id="title-block-header" class="quarto-title-block default">
414<div class="quarto-title">
415<h1 class="title">Inverse Complexity Blog</h1>
416</div>
417
418
419
420<div class="quarto-title-meta">
421
422    
423  
424    
425  </div>
426  
427
428
429</header>
430
431
432
433
434
435
436<div class="quarto-listing quarto-listing-container-grid" id="listing-listing">
437<div class="list grid quarto-listing-cols-3">
438<div class="g-col-1" data-index="0" data-categories="aHlwZXJzbG9wJTJDaHlwZXJncmFwaHMlMkNoaWdoZXItb3JkZXIlMkNoeXBlJTJDbWVhbi1maWVsZA==" data-listing-date-sort="1771801200000" data-listing-file-modified-sort="1777876002032" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="16" data-listing-word-count-sort="3142">
439<a href="./posts/higher-standards/index.html" class="quarto-grid-link">
440<div class="quarto-grid-item card h-100 card-left">
441<p class="card-img-top">
442<img loading="lazy" src="./posts/higher-standards/diagram_func.png" class="thumbnail-image card-img" style="height: 150px;">
443</p>
444<div class="card-body post-contents">
445<h5 class="no-anchor card-title listing-title">
446Higher orders need higher standards
447</h5>
448<div class="listing-categories">
449
450<div class="listing-category" onclick="window.quartoListingCategory('aHlwZXJzbG9w'); return false;">hyperslop</div>
451
452<div class="listing-category" onclick="window.quartoListingCategory('aHlwZXJncmFwaHM='); return false;">hypergraphs</div>
453
454<div class="listing-category" onclick="window.quartoListingCategory('aGlnaGVyLW9yZGVy'); return false;">higher-order</div>
455
456<div class="listing-category" onclick="window.quartoListingCategory('aHlwZQ=='); return false;">hype</div>
457
458<div class="listing-category" onclick="window.quartoListingCategory('bWVhbi1maWVsZA=='); return false;">mean-field</div>
459
460</div>
461<div class="card-text listing-description delink">
462TL;DR — Contrary to widespread claims in recent years, it’s not true that graphs encode “pairwise” interactions. Graphs encode neighborhoods—sets of nodes incident to other…<span class="citation" data-cites="peixoto_graphs_2026"></span>
463</div>
464<div class="card-attribution card-text-small justify">
465<div class="listing-author">
466Tiago P. Peixoto
467</div>
468<div class="listing-date">
469Feb 23, 2026
470</div>
471</div>
472</div>
473</div></a>
474</div>
475<div class="g-col-1" data-index="1" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDaGV1cmlzdGljcyUyQ292ZXJmaXR0aW5nJTJDbWVtZXM=" data-listing-date-sort="1764802800000" data-listing-file-modified-sort="1767007380865" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="7" data-listing-word-count-sort="1328">
476<a href="./posts/connected-clusters/index.html" class="quarto-grid-link">
477<div class="quarto-grid-item card h-100 card-left">
478<p class="card-img-top">
479<img loading="lazy" src="./posts/connected-clusters/clusters.png" class="thumbnail-image card-img" style="height: 150px;">
480</p>
481<div class="card-body post-contents">
482<h5 class="no-anchor card-title listing-title">
483The perplexing “connected cluster axiom”
484</h5>
485<div class="listing-categories">
486
487<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
488
489<div class="listing-category" onclick="window.quartoListingCategory('aGV1cmlzdGljcw=='); return false;">heuristics</div>
490
491<div class="listing-category" onclick="window.quartoListingCategory('b3ZlcmZpdHRpbmc='); return false;">overfitting</div>
492
493<div class="listing-category" onclick="window.quartoListingCategory('bWVtZXM='); return false;">memes</div>
494
495</div>
496<div class="card-text listing-description delink">
497TL;DR — There’s no good reason to always expect communities in networks to be made of strictly connected nodes. On the contrary, doing so leads to conceptual inconsistencies…
498</div>
499<div class="card-attribution card-text-small justify">
500<div class="listing-author">
501Tiago P. Peixoto
502</div>
503<div class="listing-date">
504Dec 4, 2025
505</div>
506</div>
507</div>
508</div></a>
509</div>
510<div class="g-col-1" data-index="2" data-categories="bmV0d29yayUyMHZpc3VhbGl6YXRpb24lMkNpbmZlcmVuY2UlMkNoYWlyYmFsbCUyQ2Fwb3BoZW5pYSUyQ3JpZGljdWxvZ3JhbSUyQ21ldGhvZG9sb2dpY2FsJTIwaW1wZXJpYWxpc20=" data-listing-date-sort="1716156000000" data-listing-file-modified-sort="1756756335152" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="19" data-listing-word-count-sort="3694">
511<a href="./posts/hairball/index.html" class="quarto-grid-link">
512<div class="quarto-grid-item card h-100 card-left">
513<p class="card-img-top">
514<img loading="lazy" src="./posts/hairball/polblogs-sbm.png" class="thumbnail-image card-img" style="height: 150px;">
515</p>
516<div class="card-body post-contents">
517<h5 class="no-anchor card-title listing-title">
518Untangling the hairball using statistical inference
519</h5>
520<div class="listing-categories">
521
522<div class="listing-category" onclick="window.quartoListingCategory('bmV0d29yayUyMHZpc3VhbGl6YXRpb24='); return false;">network visualization</div>
523
524<div class="listing-category" onclick="window.quartoListingCategory('aW5mZXJlbmNl'); return false;">inference</div>
525
526<div class="listing-category" onclick="window.quartoListingCategory('aGFpcmJhbGw='); return false;">hairball</div>
527
528<div class="listing-category" onclick="window.quartoListingCategory('YXBvcGhlbmlh'); return false;">apophenia</div>
529
530<div class="listing-category" onclick="window.quartoListingCategory('cmlkaWN1bG9ncmFt'); return false;">ridiculogram</div>
531
532<div class="listing-category" onclick="window.quartoListingCategory('bWV0aG9kb2xvZ2ljYWwlMjBpbXBlcmlhbGlzbQ=='); return false;">methodological imperialism</div>
533
534</div>
535<div class="card-text listing-description delink">
536TL;DR — Network visualization is often done in the wrong way: first a network layout is produced using a heuristic, and then follow-up analyses are performed and evaluated…
537</div>
538<div class="card-attribution card-text-small justify">
539<div class="listing-author">
540Tiago P. Peixoto
541</div>
542<div class="listing-date">
543May 20, 2024
544</div>
545</div>
546</div>
547</div></a>
548</div>
549<div class="g-col-1" data-index="3" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDQmF5ZXMlMkNjb21wcmVzc2lvbiUyQ01ETCUyQ292ZXJmaXR0aW5nJTJDZnJlZSUyMGx1bmNo" data-listing-date-sort="1711922400000" data-listing-file-modified-sort="1756757716138" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="10" data-listing-word-count-sort="1878">
550<a href="./posts/hidden-models/index.html" class="quarto-grid-link">
551<div class="quarto-grid-item card h-100 card-left">
552<p class="card-img-top">
553<img loading="lazy" src="./posts/hidden-models/diagram.png" class="thumbnail-image card-img" style="height: 150px;">
554</p>
555<div class="card-body post-contents">
556<h5 class="no-anchor card-title listing-title">
557Hidden models and latent compression in community detection
558</h5>
559<div class="listing-categories">
560
561<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
562
563<div class="listing-category" onclick="window.quartoListingCategory('QmF5ZXM='); return false;">Bayes</div>
564
565<div class="listing-category" onclick="window.quartoListingCategory('Y29tcHJlc3Npb24='); return false;">compression</div>
566
567<div class="listing-category" onclick="window.quartoListingCategory('TURM'); return false;">MDL</div>
568
569<div class="listing-category" onclick="window.quartoListingCategory('b3ZlcmZpdHRpbmc='); return false;">overfitting</div>
570
571<div class="listing-category" onclick="window.quartoListingCategory('ZnJlZSUyMGx1bmNo'); return false;">free lunch</div>
572
573</div>
574<div class="card-text listing-description delink">
575This is an overdue post on a paper published last year with Alec Kirkley, named <em>“Implicit Models, Latent Compression, Intrinsic Biases, and Cheap Lunches in Community…</em><span class="citation" data-cites="peixoto_implicit_2023"></span>
576</div>
577<div class="card-attribution card-text-small justify">
578<div class="listing-author">
579Tiago P. Peixoto
580</div>
581<div class="listing-date">
582Apr 1, 2024
583</div>
584</div>
585</div>
586</div></a>
587</div>
588<div class="g-col-1" data-index="4" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDQmF5ZXMlMkNjb21wcmVzc2lvbiUyQ01ETCUyQ3N1YmplY3Rpdml0eQ==" data-listing-date-sort="1641250800000" data-listing-file-modified-sort="1724019705417" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="12" data-listing-word-count-sort="2386">
589<a href="./posts/objective-inference/index.html" class="quarto-grid-link">
590<div class="quarto-grid-item card h-100 card-left">
591<p class="card-img-top">
592<img loading="lazy" src="./posts/objective-inference/compressed.png" class="thumbnail-image card-img" style="height: 150px;">
593</p>
594<div class="card-body post-contents">
595<h5 class="no-anchor card-title listing-title">
596Is Bayesian inference subjective?
597</h5>
598<div class="listing-categories">
599
600<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
601
602<div class="listing-category" onclick="window.quartoListingCategory('QmF5ZXM='); return false;">Bayes</div>
603
604<div class="listing-category" onclick="window.quartoListingCategory('Y29tcHJlc3Npb24='); return false;">compression</div>
605
606<div class="listing-category" onclick="window.quartoListingCategory('TURM'); return false;">MDL</div>
607
608<div class="listing-category" onclick="window.quartoListingCategory('c3ViamVjdGl2aXR5'); return false;">subjectivity</div>
609
610</div>
611<div class="card-text listing-description delink">
612In a previous blog post (covering<span class="citation" data-cites="peixoto_descriptive_2023">&nbsp;[1]</span>
612) I discussed how inferential approaches to community detection are based on the formulation of generative models, via the definition of…<span class="math inline"></span><span class="math inline"></span><span class="math inline"></span>
613</div>
614<div class="card-attribution card-text-small justify">
615<div class="listing-author">
616Tiago P. Peixoto
617</div>
618<div class="listing-date">
619Jan 4, 2022
620</div>
621</div>
622</div>
623</div></a>
624</div>
625<div class="g-col-1" data-index="5" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDbW9kdWxhcml0eSUyQ292ZXJmaXR0aW5nJTJDc3RhdGlzdGljYWwlMjBzaWduaWZpY2FuY2U=" data-listing-date-sort="1639350000000" data-listing-file-modified-sort="1712932182257" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="5" data-listing-word-count-sort="813">
626<a href="./posts/significant-modularity/index.html" class="quarto-grid-link">
627<div class="quarto-grid-item card h-100 card-left">
628<p class="card-img-top">
629<img loading="lazy" src="./posts/significant-modularity/modularity-test.png" class="thumbnail-image card-img" style="height: 150px;">
630</p>
631<div class="card-body post-contents">
632<h5 class="no-anchor card-title listing-title">
633Significant community structure via statistical tests?
634</h5>
635<div class="listing-categories">
636
637<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
638
639<div class="listing-category" onclick="window.quartoListingCategory('bW9kdWxhcml0eQ=='); return false;">modularity</div>
640
641<div class="listing-category" onclick="window.quartoListingCategory('b3ZlcmZpdHRpbmc='); return false;">overfitting</div>
642
643<div class="listing-category" onclick="window.quartoListingCategory('c3RhdGlzdGljYWwlMjBzaWduaWZpY2FuY2U='); return false;">statistical significance</div>
644
645</div>
646<div class="card-text listing-description delink">
647In a previous blog post I explained how modularity maximization tends to overfit and find spurious community structure even in random graphs.
648</div>
649<div class="card-attribution card-text-small justify">
650<div class="listing-author">
651Tiago P. Peixoto
652</div>
653<div class="listing-date">
654Dec 13, 2021
655</div>
656</div>
657</div>
658</div></a>
659</div>
660<div class="g-col-1" data-index="6" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDQmF5ZXMlMkNjb21wcmVzc2lvbiUyQ01ETA==" data-listing-date-sort="1638918000000" data-listing-file-modified-sort="1712932182401" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="4" data-listing-word-count-sort="737">
661<a href="./posts/hypothesis-is-not-belief/index.html" class="quarto-grid-link">
662<div class="quarto-grid-item card h-100 card-left">
663<p class="card-img-top">
664<img loading="lazy" src="./static/research/add_health_comm26-marginal-triadic_sbm-modesbm.png" class="thumbnail-image card-img" style="height: 150px;">
665</p>
666<div class="card-body post-contents">
667<h5 class="no-anchor card-title listing-title">
668Do we need to believe in generative models?
669</h5>
670<div class="listing-categories">
671
672<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
673
674<div class="listing-category" onclick="window.quartoListingCategory('QmF5ZXM='); return false;">Bayes</div>
675
676<div class="listing-category" onclick="window.quartoListingCategory('Y29tcHJlc3Npb24='); return false;">compression</div>
677
678<div class="listing-category" onclick="window.quartoListingCategory('TURM'); return false;">MDL</div>
679
680</div>
681<div class="card-text listing-description delink">
682In two previous blog posts (first and second) I advocated for the use of statistical inference for community detection in networks, whenever our objective is of an…
683</div>
684<div class="card-attribution card-text-small justify">
685<div class="listing-author">
686Tiago P. Peixoto
687</div>
688<div class="listing-date">
689Dec 8, 2021
690</div>
691</div>
692</div>
693</div></a>
694</div>
695<div class="g-col-1" data-index="7" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDZnJlZSUyMGx1bmNoJTJDaW5mZXJlbmNlJTJDY29tcHJlc3Npb24lMkNCYXllcw==" data-listing-date-sort="1638831600000" data-listing-file-modified-sort="1724056134274" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="18" data-listing-word-count-sort="3438">
696<a href="./posts/free-lunch/index.html" class="quarto-grid-link">
697<div class="quarto-grid-item card h-100 card-left">
698<p class="card-img-top">
699<img loading="lazy" src="./posts/free-lunch/nfl-trade-off.png" class="thumbnail-image card-img" style="height: 150px;">
700</p>
701<div class="card-body post-contents">
702<h5 class="no-anchor card-title listing-title">
703No free lunch in community detection?
704</h5>
705<div class="listing-categories">
706
707<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
708
709<div class="listing-category" onclick="window.quartoListingCategory('ZnJlZSUyMGx1bmNo'); return false;">free lunch</div>
710
711<div class="listing-category" onclick="window.quartoListingCategory('aW5mZXJlbmNl'); return false;">inference</div>
712
713<div class="listing-category" onclick="window.quartoListingCategory('Y29tcHJlc3Npb24='); return false;">compression</div>
714
715<div class="listing-category" onclick="window.quartoListingCategory('QmF5ZXM='); return false;">Bayes</div>
716
717</div>
718<div class="card-text listing-description delink">
719For a wide class of optimization and learning problems there exist so-called “no-free-lunch” (NFL) theorems, which broadly state that when averaged over all possible problem…<span class="citation" data-cites="wolpert_no_1995 wolpert_lack_1996 wolpert_no_1997"></span><em></em><span class="citation" data-cites="peel_ground_2017"></span>
720</div>
721<div class="card-attribution card-text-small justify">
722<div class="listing-author">
723Tiago P. Peixoto
724</div>
725<div class="listing-date">
726Dec 7, 2021
727</div>
728</div>
729</div>
730</div></a>
731</div>
732<div class="g-col-1" data-index="8" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDbW9kdWxhcml0eSUyQ2luZmVyZW5jZSUyQ0JheWVzJTJDU0JN" data-listing-date-sort="1638745200000" data-listing-file-modified-sort="1748947679242" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="19" data-listing-word-count-sort="3780">
733<a href="./posts/modularity-harmful/index.html" class="quarto-grid-link">
734<div class="quarto-grid-item card h-100 card-left">
735<p class="card-img-top">
736<img loading="lazy" src="./posts/modularity-harmful/modularity_fail.png" class="thumbnail-image card-img" style="height: 150px;">
737</p>
738<div class="card-body post-contents">
739<h5 class="no-anchor card-title listing-title">
740Modularity maximization considered harmful
741</h5>
742<div class="listing-categories">
743
744<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
745
746<div class="listing-category" onclick="window.quartoListingCategory('bW9k
746dWxhcml0eQ=='); return false;">modularity</div>
747
748<div class="listing-category" onclick="window.quartoListingCategory('aW5mZXJlbmNl'); return false;">inference</div>
749
750<div class="listing-category" onclick="window.quartoListingCategory('QmF5ZXM='); return false;">Bayes</div>
751
752<div class="listing-category" onclick="window.quartoListingCategory('U0JN'); return false;">SBM</div>
753
754</div>
755<div class="card-text listing-description delink">
756The most widespread method for community detection is modularity maximization <span class="citation" data-cites="newman_modularity_2006">&nbsp;[2]</span>, which happens also to be one of the most problematic. This method is based on the…
757</div>
758<div class="card-attribution card-text-small justify">
759<div class="listing-author">
760Tiago P. Peixoto
761</div>
762<div class="listing-date">
763Dec 6, 2021
764</div>
765</div>
766</div>
767</div></a>
768</div>
769<div class="g-col-1" data-index="9" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDZGVzY3JpcHRpb24lMkNpbmZlcmVuY2UlMkNCYXllcyUyQ01ETCUyQ1NCTQ==" data-listing-date-sort="1638486000000" data-listing-file-modified-sort="1724314341284" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="16" data-listing-word-count-sort="3160">
770<a href="./posts/inference-compression/index.html" class="quarto-grid-link">
771<div class="quarto-grid-item card h-100 card-left">
772<p class="card-img-top">
773<img loading="lazy" src="./posts/inference-compression/generative.png" class="thumbnail-image card-img" style="height: 150px;">
774</p>
775<div class="card-body post-contents">
776<h5 class="no-anchor card-title listing-title">
777Inferring, explaining, and compressing
778</h5>
779<div class="listing-categories">
780
781<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
782
783<div class="listing-category" onclick="window.quartoListingCategory('ZGVzY3JpcHRpb24='); return false;">description</div>
784
785<div class="listing-category" onclick="window.quartoListingCategory('aW5mZXJlbmNl'); return false;">inference</div>
786
787<div class="listing-category" onclick="window.quartoListingCategory('QmF5ZXM='); return false;">Bayes</div>
788
789<div class="listing-category" onclick="window.quartoListingCategory('TURM'); return false;">MDL</div>
790
791<div class="listing-category" onclick="window.quartoListingCategory('U0JN'); return false;">SBM</div>
792
793</div>
794<div class="card-text listing-description delink">
795Inferential approaches to community detection (see <span class="citation" data-cites="peixoto_bayesian_2019">&nbsp;[2]</span> for a detailed introduction) are designed to provide explanations for network data in a principled manner. They are…<span class="math inline"></span><span class="math inline"></span><span class="math inline"></span>
796</div>
797<div class="card-attribution card-text-small justify">
798<div class="listing-author">
799Tiago P. Peixoto
800</div>
801<div class="listing-date">
802Dec 3, 2021
803</div>
804</div>
805</div>
806</div></a>
807</div>
808<div class="g-col-1" data-index="10" data-categories="Y29tbXVuaXR5JTIwZGV0ZWN0aW9uJTJDZGVzY3JpcHRpb24lMkNpbmZlcmVuY2UlMkNCYXllcyUyQ1NCTQ==" data-listing-date-sort="1638399600000" data-listing-file-modified-sort="1712932182557" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="11" data-listing-word-count-sort="2163">
809<a href="./posts/descriptive-inferential/index.html" class="quarto-grid-link">
810<div class="quarto-grid-item card h-100 card-left">
811<p class="card-img-top">
812<img loading="lazy" src="./posts/descriptive-inferential/descriptive.png" class="thumbnail-image card-img" style="height: 150px;">
813</p>
814<div class="card-body post-contents">
815<h5 class="no-anchor card-title listing-title">
816Descriptive vs.&nbsp;inferential community detection
817</h5>
818<div class="listing-categories">
819
820<div class="listing-category" onclick="window.quartoListingCategory('Y29tbXVuaXR5JTIwZGV0ZWN0aW9u'); return false;">community detection</div>
821
822<div class="listing-category" onclick="window.quartoListingCategory('ZGVzY3JpcHRpb24='); return false;">description</div>
823
824<div class="listing-category" onclick="window.quartoListingCategory('aW5mZXJlbmNl'); return false;">inference</div>
825
826<div class="listing-category" onclick="window.quartoListingCategory('QmF5ZXM='); return false;">Bayes</div>
827
828<div class="listing-category" onclick="window.quartoListingCategory('U0JN'); return false;">SBM</div>
829
830</div>
831<div class="card-text listing-description delink">
832Community detection is the task of dividing a network — typically one which is large — into many smaller groups of nodes that have a similar contribution to the overall…
833</div>
834<div class="card-attribution card-text-small justify">
835<div class="listing-author">
836Tiago P. Peixoto
837</div>
838<div class="listing-date">
839Dec 2, 2021
840</div>
841</div>
842</div>
843</div></a>
844</div>
845<div class="g-col-1" data-index="11" data-categories="aW5mZXJlbmNlJTJDcmVjb25zdHJ1Y3Rpb24lMkNCYXllcyUyQ1NCTQ==" data-listing-date-sort="1635458400000" data-listing-file-modified-sort="1756755275297" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="5" data-listing-word-count-sort="977">
846<a href="./posts/thats-unpossible/index.html" class="quarto-grid-link">
847<div class="quarto-grid-item card h-100 card-left">
848<p class="card-img-top">
849<img loading="lazy" src="./posts/thats-unpossible/reconstructed.svg" class="thumbnail-image card-img" style="height: 150px;">
850</p>
851<div class="card-body post-contents">
852<h5 class="no-anchor card-title listing-title">
853Is network reconstruction impossible?
854</h5>
855<div class="listing-categories">
856
857<div class="listing-category" onclick="window.quartoListingCategory('aW5mZXJlbmNl'); return false;">inference</div>
858
859<div class="listing-category" onclick="window.quartoListingCategory('cmVjb25zdHJ1Y3Rpb24='); return false;">reconstruction</div>
860
861<div class="listing-category" onclick="window.quartoListingCategory('QmF5ZXM='); return false;">Bayes</div>
862
863<div class="listing-category" onclick="window.quartoListingCategory('U0JN'); return false;">SBM</div>
864
865</div>
866<div class="card-text listing-description delink">
867I have been getting some questions about a 2018 paper <span class="citation" data-cites="chang_estimation_2020">&nbsp;[1]</span> by Jinyuan Chang, Eric D. Kolaczyk, and Qiwei Yao that deals with reconstruction of noisy networks, i.e.&nbsp;networks…
868</div>
869<div class="card-attribution card-text-small justify">
870<div class="listing-author">
871Tiago P. Peixoto
872</div>
873<div class="listing-date">
874Oct 29, 2021
875</div>
876</div>
877</div>
878</div></a>
879</div>
880</div>
881<div class="listing-no-matching d-none">No matching items</div>
882</div></main> <!-- /main -->
883<script id="quarto-html-after-body" type="application/javascript">
884  window.document.addEventListener("DOMContentLoaded", function (event) {
885    // Ensure there is a toggle, if there isn't float one in the top right
886    if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
887      const a = window.document.createElement('a');
888      a.classList.add('top-right');
889      a.classList.add('quarto-color-scheme-toggle');
890      a.href = "";
891      a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
892      const i = window.document.createElement("i");
893      i.classList.add('bi');
894      a.appendChild(i);
895      window.document.body.appendChild(a);
896    }
897    setColorSchemeToggle(hasAlternateSentinel())
898    const icon = "";
899    const anchorJS = new window.AnchorJS();
900    anchorJS.options = {
901      placement: 'right',
902      icon: icon
903    };
904    anchorJS.add('.anchored');
905    const isCodeAnnotation = (el) => {
906      for (const clz of el.classList) {
907        if (clz.startsWith('code-annotation-')) {                     
908          return true;
909        }
910      }
911      return false;
912    }
913    const onCopySuccess = function(e) {
914      // button target
915      const button = e.trigger;
916      // don't keep focus
917      button.blur();
918      // flash "checked"
919      button.classList.add('code-copy-button-checked');
920      var currentTitle = button.getAttribute("title");
921      button.setAttribute("title", "Copied!");
922      let tooltip;
923      if (window.bootstrap) {
924        button.setAttribute("data-bs-toggle", "tooltip");
925        button.setAttribute("data-bs-placement", "left");
926        button.setAttribute("data-bs-title", "Copied!");
927        tooltip = new bootstrap.Tooltip(button, 
928          { trigger: "manual", 
929            customClass: "code-copy-button-tooltip",
930            offset: [0, -8]});
931        tooltip.show();    
932      }
933      setTimeout(function() {
934        if (tooltip) {
935          tooltip.hide();
936          button.removeAttribute("data-bs-title");
937          button.removeAttribute("data-bs-toggle");
938          button.removeAttribute("data-bs-placement");
939        }
940        button.setAttribute("title", currentTitle);
941        button.classList.remove('code-copy-button-checked');
942      }, 1000);
943      // clear code selection
944      e.clearSelection();
945    }
946    const getTextToCopy = function(trigger) {
947      const outerScaffold = trigger.parentElement.cloneNode(true);
948      const codeEl = outerScaffold.querySelector('code');
949      for (const childEl of codeEl.children) {
950        if (isCodeAnnotation(childEl)) {
951          childEl.remove();
952        }
953      }
954      return codeEl.innerText;
955    }
956    const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
957      text: getTextToCopy
958    });
959    clipboard.on('success', onCopySuccess);
960    if (window.document.getElementById('quarto-embedded-source-code-modal')) {
961      const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
962        text: getTextToCopy,
963        container: window.document.getElementById('quarto-embedded-source-code-modal')
964      });
965      clipboardModal.on('success', onCopySuccess);
966    }
967      var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
968      var mailtoRegex = new RegExp(/^mailto:/);
969        var filterRegex = new RegExp("https:\/\/skewed\.de\/lab");
970      var isInternal = (href) => {
971          return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
972      }
973      // Inspect non-navigation links and adorn them if external
974     var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
975      for (var i=0; i<links.length; i++) {
976        const link = links[i];
977        if (!isInternal(link.href)) {
978          // undo the damage that might have been done by quarto-nav.js in the case of
979          // links that we want to consider external
980          if (link.dataset.originalHref !== undefined) {
981            link.href = link.dataset.originalHref;
982          }
983        }
984      }
985    function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
986      const config = {
987        allowHTML: true,
988        maxWidth: 500,
989        delay: 100,
990        arrow: false,
991        appendTo: function(el) {
992            return el.parentElement;
993        },
994        interactive: true,
995        interactiveBorder: 10,
996        theme: 'quarto',
997        placement: 'bottom-start',
998      };
999      if (contentFn) {
1000        config.content = contentFn;
1001      }
1002      if (onTriggerFn) {
1003        config.onTrigger = onTriggerFn;
1004      }
1005      if (onUntriggerFn) {
1006        config.onUntrigger = onUntriggerFn;
1007      }
1008      window.tippy(el, config); 
1009    }
1010    const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
1011    for (var i=0; i<noterefs.length; i++) {
1012      const ref = noterefs[i];
1013      tippyHover(ref, function() {
1014        // use id or data attribute instead here
1015        let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
1016        try { href = new URL(href).hash; } catch {}
1017        const id = href.replace(/^#\/?/, "");
1018        const note = window.document.getElementById(id);
1019        if (note) {
1020          return note.innerHTML;
1021        } else {
1022          return "";
1023        }
1024      });
1025    }
1026    const xrefs = window.document.querySelectorAll('a.quarto-xref');
1027    const processXRef = (id, note) => {
1028      // Strip column container classes
1029      const stripColumnClz = (el) => {
1030        el.classList.remove("page-full", "page-columns");
1031        if (el.children) {
1032          for (const child of el.children) {
1033            stripColumnClz(child);
1034          }
1035        }
1036      }
1037      stripColumnClz(note)
1038      if (id === null || id.startsWith('sec-')) {
1039        // Special case sections, only their first couple elements
1040        const container = document.createElement("div");
1041        if (note.children && note.children.length > 2) {
1042          container.appendChild(note.children[0].cloneNode(true));
1043          for (let i = 1; i < note.children.length; i++) {
1044            const child = note.children[i];
1045            if (child.tagName === "P" && child.innerText === "") {
1046              continue;
1047            } else {
1048              container.appendChild(child.cloneNode(true));
1049              break;
1050            }
1051          }
1052          if (window.Quarto?.typesetMath) {
1053            window.Quarto.typesetMath(container);
1054          }
1055          return container.innerHTML
1056        } else {
1057          if (window.Quarto?.typesetMath) {
1058            window.Quarto.typesetMath(note);
1059          }
1060          return note.innerHTML;
1061        }
1062      } else {
1063        // Remove any anchor links if they are present
1064        const anchorLink = note.querySelector('a.anchorjs-link');
1065        if (anchorLink) {
1066          anchorLink.remove();
1067        }
1068        if (window.Quarto?.typesetMath) {
1069          window.Quarto.typesetMath(note);
1070        }
1071        if (note.classList.contains("callout")) {
1072          return note.outerHTML;
1073        } else {
1074          return note.innerHTML;
1075        }
1076      }
1077    }
1078    for (var i=0; i<xrefs.length; i++) {
1079      const xref = xrefs[i];
1080      tippyHover(xref, undefined, function(instance) {
1081        instance.disable();
1082        let url = xref.getAttribute('href');
1083        let hash = undefined; 
1084        if (url.startsWith('#')) {
1085          hash = url;
1086        } else {
1087          try { hash = new URL(url).hash; } catch {}
1088        }
1089        if (hash) {
1090          const id = hash.replace(/^#\/?/, "");
1091          const note = window.document.getElementById(id);
1092          if (note !== null) {
1093            try {
1094              const html = processXRef(id, note.cloneNode(true));
1095              instance.setContent(html);
1096            } finally {
1097              instance.enable();
1098              instance.show();
1099            }
1100          } else {
1101            // See if we can fetch this
1102            fetch(url.split('#')[0])
1103            .then(res => res.text())
1104            .then(html => {
1105              const parser = new DOMParser();
1106              const htmlDoc = parser.parseFromString(html, "text/html");
1107              const note = htmlDoc.getElementById(id);
1108              if (note !== null) {
1109                const html = processXRef(id, note);
1110                instance.setContent(html);
1111              } 
1112            }).finally(() => {
1113              instance.enable();
1114              instance.show();
1115            });
1116          }
1117        } else {
1118          // See if we can fetch a full url (with no hash to target)
1119          // This is a special case and we should probably do some content thinning / targeting
1120          fetch(url)
1121          .then(res => res.text())
1122          .then(html => {
1123            const parser = new DOMParser();
1124            const htmlDoc = parser.parseFromString(html, "text/html");
1125            const note = htmlDoc.querySelector('main.content');
1126            if (note !== null) {
1127              // This should only happen for chapter cross references
1128              // (since there is no id in the URL)
1129              // remove the first header
1130              if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
1131                note.children[0].remove();
1132              }
1133              const html = processXRef(null, note);
1134              instance.setContent(html);
1135            } 
1136          }).finally(() => {
1137            instance.enable();
1138            instance.show();
1139          });
1140        }
1141      }, function(instance) {
1142      });
1143    }
1144        let selectedAnnoteEl;
1145        const selectorForAnnotation = ( cell, annotation) => {
1146          let cellAttr = 'data-code-cell="' + cell + '"';
1147          let lineAttr = 'data-code-annotation="' +  annotation + '"';
1148          const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
1149          return selector;
1150        }
1151        const selectCodeLines = (annoteEl) => {
1152          const doc = window.document;
1153          const targetCell = annoteEl.getAttribute("data-target-cell");
1154          const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
1155          const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
1156          const lines = annoteSpan.getAttribute("data-code-lines").split(",");
1157          const lineIds = lines.map((line) => {
1158            return targetCell + "-" + line;
1159          })
1160          let top = null;
1161          let height = null;
1162          let parent = null;
1163          if (lineIds.length > 0) {
1164              //compute the position of the single el (top and bottom and make a div)
1165              const el = window.document.getElementById(lineIds[0]);
1166              top = el.offsetTop;
1167              height = el.offsetHeight;
1168              parent = el.parentElement.parentElement;
1169            if (lineIds.length > 1) {
1170              const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
1171              const bottom = lastEl.offsetTop + lastEl.offsetHeight;
1172              height = bottom - top;
1173            }
1174            if (top !== null && height !== null && parent !== null) {
1175              // cook up a div (if necessary) and position it 
1176              let div = window.document.getElementById("code-annotation-line-highlight");
1177              if (div === null) {
1178                div = window.document.createElement("div");
1179                div.setAttribute("id", "code-annotation-line-highlight");
1180                div.style.position = 'absolute';
1181                parent.appendChild(div);
1182              }
1183              div.style.top = top - 2 + "px";
1184              div.style.height = height + 4 + "px";
1185              div.style.left = 0;
1186              let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
1187              if (gutterDiv === null) {
1188                gutterDiv = window.document.createElement("div");
1189                gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
1190                gutterDiv.style.position = 'absolute';
1191                const codeCell = window.document.getElementById(targetCell);
1192                const gutter = codeCell.querySelector('.code-annotation-gutter');
1193                gutter.appendChild(gutterDiv);
1194              }
1195              gutterDiv.style.top = top - 2 + "px";
1196              gutterDiv.style.height = height + 4 + "px";
1197            }
1198            selectedAnnoteEl = annoteEl;
1199          }
1200        };
1201        const unselectCodeLines = () => {
1202          const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
1203          elementsIds.forEach((elId) => {
1204            const div = window.document.getElementById(elId);
1205            if (div) {
1206              div.remove();
1207            }
1208          });
1209          selectedAnnoteEl = undefined;
1210        };
1211          // Handle positioning of the toggle
1212      window.addEventListener(
1213        "resize",
1214        throttle(() => {
1215          elRect = undefined;
1216          if (selectedAnnoteEl) {
1217            selectCodeLines(selectedAnnoteEl);
1218          }
1219        }, 10)
1220      );
1221      function throttle(fn, ms) {
1222      let throttle = false;
1223      let timer;
1224        return (...args) => {
1225          if(!throttle) { // first call gets through
1226              fn.apply(this, args);
1227              throttle = true;
1228          } else { // all the others get throttled
1229              if(timer) clearTimeout(timer); // cancel #2
1230              timer = setTimeout(() => {
1231                fn.apply(this, args);
1232                timer = throttle = false;
1233              }, ms);
1234          }
1235        };
1236      }
1237        // Attach click handler to the DT
1238        const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
1239        for (const annoteDlNode of annoteDls) {
1240          annoteDlNode.addEventListener('click', (event) => {
1241            const clickedEl = event.target;
1242            if (clickedEl !== selectedAnnoteEl) {
1243              unselectCodeLines();
1244              const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
1245              if (activeEl) {
1246                activeEl.classList.remove('code-annotation-active');
1247              }
1248              selectCodeLines(clickedEl);
1249              clickedEl.classList.add('code-annotation-active');
1250            } else {
1251              // Unselect the line
1252              unselectCodeLines();
1253              clickedEl.classList.remove('code-annotation-active');
1254            }
1255          });
1256        }
1257    const findCites = (el) => {
1258      const parentEl = el.parentElement;
1259      if (parentEl) {
1260        const cites = parentEl.dataset.cites;
1261        if (cites) {
1262          return {
1263            el,
1264            cites: cites.split(' ')
1265          };
1266        } else {
1267          return findCites(el.parentElement)
1268        }
1269      } else {
1270        return undefined;
1271      }
1272    };
1273    var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
1274    for (var i=0; i<bibliorefs.length; i++) {
1275      const ref = bibliorefs[i];
1276      const citeInfo = findCites(ref);
1277      if (citeInfo) {
1278        tippyHover(citeInfo.el, function() {
1279          var popup = window.document.createElement('div');
1280          citeInfo.cites.forEach(function(cite) {
1281            var citeDiv = window.document.createElement('div');
1282            citeDiv.classList.add('hanging-indent');
1283            citeDiv.classList.add('csl-entry');
1284            var biblioDiv = window.document.getElementById('ref-' + cite);
1285            if (biblioDiv) {
1286              citeDiv.innerHTML = biblioDiv.innerHTML;
1287            }
1288            popup.appendChild(citeDiv);
1289          });
1290          return popup.innerHTML;
1291        });
1292      }
1293    }
1294  });
1295  </script>
1295
1296</div> <!-- /content -->
1297
1298
1299
1300
1301<script src="site_libs/quarto-html/zenscroll-min.js"></script>
1301
1302</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.