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.4.557"> 6 7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 8 9 10<title>Manopt - Getting started</title> 11<style> 12code{white-space: pre-wrap;} 13span.smallcaps{font-variant: small-caps;} 14div.columns{display: flex; gap: min(4vw, 1.5em);} 15div.column{flex: auto; overflow-x: auto;} 16div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 17ul.task-list{list-style: none;} 18ul.task-list li input[type="checkbox"] { 19 width: 0.8em; 20 margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 21 vertical-align: middle; 22} 23</style> 24 25
26<script src="site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 26
26
27<script src="site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 27
27
28<script src="site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 28
28
29<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 29
29
30<script src="site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 30
30
31<script src="site_libs/quarto-search/quarto-search.js"></script>
31 32<meta name="quarto:offset" content="./"> 33<link href="./icon.png" rel="icon" type="image/png">
34<script src="site_libs/cookie-consent/cookie-consent.js"></script>
34 35<link href="site_libs/cookie-consent/cookie-consent.css" rel="stylesheet">
36<script src="site_libs/quarto-html/quarto.js"></script>
vendor: 1 bytes, line 36
36
37<script src="site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 37
37
38<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
vendor: 1 bytes, line 38
38
39<script src="site_libs/quarto-html/anchor.min.js"></script>
39 40<link href="site_libs/quarto-html/tippy.css" rel="stylesheet"> 41<link href="site_libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles"> 42<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark.css" rel="prefetch" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
43<script src="site_libs/bootstrap/bootstrap.min.js"></script>
43 44<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet"> 45<link href="site_libs/bootstrap/bootstrap.min.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light"> 46<link href="site_libs/bootstrap/bootstrap-dark.min.css" rel="prefetch" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
47<script id="quarto-search-options" type="application/json">{ 48 "location": "navbar", 49 "copy-button": false, 50 "collapse-after": 3, 51 "panel-placement": "end", 52 "type": "overlay", 53 "limit": 50, 54 "keyboard-shortcut": [ 55 "f", 56 "/", 57 "s" 58 ], 59 "language": { 60 "search-no-results-text": "No results", 61 "search-matching-documents-text": "matching documents", 62 "search-copy-link-title": "Copy link to search", 63 "search-hide-matches-text": "Hide additional matches", 64 "search-more-match-text": "more match in this document", 65 "search-more-matches-text": "more matches in this document", 66 "search-clear-button-title": "Clear", 67 "search-text-placeholder": "", 68 "search-detached-cancel-button-title": "Cancel", 69 "search-submit-button-title": "Submit", 70 "search-label": "Search" 71 } 72}</script>
vendor: 67 bytes, lines 72-73
72 73<script async="" src="https://www.googletagmanager.com/gtag/js?id=
73G-71FCE8T97E
vendor: 13 bytes, lines 73-74
73"></script> 74
75<script type="text/plain" cookie-consent="tracking"> 76
vendor: 127 bytes, lines 77-80
77window.dataLayer = window.dataLayer || []; 78function gtag(){dataLayer.push(arguments);} 79gtag('js', new Date()); 80gtag('config', '
80G-71FCE8T97E
vendor: 29 bytes, line 80
80', { 'anonymize_ip': true});
81</script>
81 82
83<script type="text/javascript" charset="UTF-8"> 84document.addEventListener('DOMContentLoaded', function () { 85cookieconsent.run({ 86 "notice_banner_type":"simple", 87 "consent_type":"express", 88 "palette":"light", 89 "language":"en", 90 "page_load_consent_levels":["strictly-necessary"], 91 "notice_banner_reject_button_hide":false, 92 "preferences_center_close_button_hide":false, 93 "website_name":"" 94 , 95"language":"en" 96 }); 97}); 98</script>
98 99 100<style>html{ scroll-behavior: smooth; }</style>
101<script> 102 103window.MathJax = { 104 105 tex: { 106 107 inlineMath: [['$', '$'], ['\\(', '\\)']], 108 109 macros: { 110 111 reals: "\\mathbb{R}", 112 113 inner: ["\\left\\langle #1, #2 \\right\\rangle", 2], 114 115 smallinner: ["\\langle #1, #2 \\rangle", 2], 116 117 innersmall: ["\\langle #1, #2 \\rangle", 2], 118 119 innerbig: ["\\big\\langle #1, #2 \\big\\rangle", 2], 120 121 sqfrobnorm: ["\\left\\|#1\\right\\|_{\\mathrm{F}}^2", 1], 122 123 sqfrobnormsmall: ["\\|#1\\|_{\\mathrm{F}}^2", 1], 124 125 sqfrobnormbig: ["\\big\\|#1\\big\\|_{\\mathrm{F}}^2", 1], 126 127 calM: "\\mathcal{M}", 128 129 calN: "\\mathcal{N}", 130 131 calA: "\\mathcal{A}", 132 133 calX: "\\mathcal{X}", 134 135 T: "\\mathrm{T}", 136 137 skeww: "\\mathrm{skew}", 138 139 symm: "\\mathrm{sym}", 140 141 Sym: "\\mathrm{Sym}", 142 143 Proj: "\\mathrm{Proj}", 144 145 grad: "\\mathrm{grad}", 146 147 Hess: "\\mathrm{Hess}", 148 149 Retr: "\\mathrm{R}", 150 151 D: "\\mathrm{D}", 152 153 calE: "\\mathcal{E}", 154 155 Stnp: "\\mathrm{St}(n,p)", 156 157 Rnp: "\\mathbb{R}^{n \\times p}", 158 159 Rmp: "\\mathbb{R}^{m \\times p}", 160 161 Rnr: "\\mathbb{R}^{n \\times r}", 162 163 Rrn: "\\mathbb{R}^{r \\times n}", 164 165 Rmr: "\\mathbb{R}^{m \\times r}", 166 167 Rnn: "\\mathbb{R}^{n \\times n}", 168 169 Rmn: "\\mathbb{R}^{m \\times n}", 170 171 Rnm: "\\mathbb{R}^{n \\times m}", 172 173 Rpp: "\\mathbb{R}^{p \\times p}", 174 175 Rmnr: "\\mathbb{R}^{m \\times n}_r", 176 177 Rmnlr: "\\mathbb{R}^{m \\times n}_{\\leq r}", 178 179 Rn: "\\mathbb{R}^{n}", 180 181 Rm: "\\mathbb{R}^{m}", 182 183 Rp: "\\mathbb{R}^{p}", 184 185 Rd: "\\mathbb{R}^{d}", 186 187 Rk: "\\mathbb{R}^{k}", 188 189 Sn: "\\mathbb{S}^{n-1}", 190 191 Sm: "\\mathbb{S}^{m-1}", 192 193 Sd: "\\mathbb{S}^{d-1}", 194 195 trace: "\\mathrm{Tr}", 196 197 Trace: "\\mathrm{Tr}", 198 199 diag: "\\mathrm{diag}", 200 201 sign: "\\mathrm{sign}", 202 203 Od: "\\mathrm{O}(d)", 204 205 On: "\\mathrm{O}(n)", 206 207 Om: "\\mathrm{O}(m)", 208 209 SOd: "\\mathrm{SO}(d)", 210 211 SOn: "\\mathrm{SO}(n)", 212 213 rank: "\\mathrm{rank}", 214 215 frakX: "\\mathfrak{X}", 216 217 frakF: "\\mathfrak{F}", 218 219 One: "\\mathbf{1}", 220 221 dist: "\\mathrm{dist}", 222 223 calP: "\\mathcal{P}", 224 225 calK: "\\mathcal{K}", 226 227 Rdd: "\\mathbb{R}^{d \\times d}", 228 229 calU: "\\mathcal{U}", 230 231 calV: "\\mathcal{V}", 232 233 calW: "\\mathcal{W}", 234 235 Exp: "\\mathrm{Exp}", 236 237 Log: "\\mathrm{Log}", 238 239 inj: "\\mathrm{inj}", 240 241 dom: "\\operatorname{dom}", 242 243 bigger: "<", 244 245 dt: "\\mathrm{d}t", 246 247 transpose: "^\\top\\! ", 248 249 sigmamax: "\\sigma_{\\mathrm{max}}", 250 251 sigmamin: "\\sigma_{\\mathrm{min}}", 252 253 lambdamax: "\\lambda_{\\mathrm{max}}", 254 255 lambdamin: "\\lambda_{\\mathrm{min}}", 256 257 TODO: ["\\textcolor{red}{[\\textrm{#1}]}", 1] 258 259 } 260 261 }, 262 263 svg: { 264 265 fontCache: 'global' 266 267 } 268 269 }; 270 271</script>
271 272 273 274
275<script> 276 277 window.addEventListener('load', function() { 278 279 document.getElementById("cc-nb-title").innerHTML = "May we use cookies for anonymized analytics?"; 280 281 // to improve your browsing experience on our website, 282 283 document.getElementById("cc-nb-text").innerHTML = "We would like to use cookies to analyze our website traffic, and to understand where our visitors are coming from."; 284 285 }); 286 287</script>
287 288 289 290 291<link rel="stylesheet" href="styles.css"> 292<meta property="og:title" content="Manopt - Getting started"> 293<meta property="og:description" content=""> 294<meta property="og:site_name" content="Manopt"> 295</head> 296 297<body class="nav-sidebar docked nav-fixed fullcontent"> 298 299<div id="quarto-search-results"></div> 300 <header id="quarto-header" class="headroom fixed-top"> 301 <nav class="navbar navbar-expand-lg " data-bs-theme="dark"> 302 <div class="navbar-container container-fluid"> 303 <div class="navbar-brand-container mx-auto"> 304 <a class="navbar-brand" href="./index.html"> 305 <span class="navbar-title">Manopt</span> 306 </a> 307 </div> 308 <div id="quarto-search" class="" title="Search"></div> 309 <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }"> 310 <span class="navbar-toggler-icon"></span> 311</button> 312 <div class="collapse navbar-collapse" id="navbarCollapse"> 313 <ul class="navbar-nav navbar-nav-scroll me-auto"> 314 <li class="nav-item"> 315 <a class="nav-link" href="./index.html"> 316<span class="menu-text">Home</span></a> 317 </li> 318 <li class="nav-item dropdown "> 319 <a class="nav-link dropdown-toggle" href="#" id="nav-menu-tutorial" role="button" data-bs-toggle="dropdown" aria-expanded="false"> 320 <span class="menu-text">Tutorial</span> 321 </a> 322 <ul class="dropdown-menu" aria-labelledby="nav-menu-tutorial"> 323 <li> 324 <a class="dropdown-item" href="./gettingstarted.html"> 325 <span class="dropdown-text">Getting started</span></a> 326 </li> 327 <li> 328 <a class="dropdown-item" href="./firstexample.html"> 329 <span class="dropdown-text">A first example</span></a> 330 </li> 331 <li> 332 <a class="dropdown-item" href="./manifolds.html"> 333 <span class="dropdown-text">Manifolds</span></a> 334 </li> 335 <li> 336 <a class="dropdown-item" href="./costdescription.html"> 337 <span class="dropdown-text">Cost functions</span></a> 338 </li> 339 <li> 340 <a class="dropdown-item" href="./solvers.html"> 341 <span class="dropdown-text">Solvers</span></a> 342 </li> 343 <li> 344 <a class="dropdown-item" href="./tools.html"> 345 <span class="dropdown-text">Helpful tools</span></a> 346 </li> 347 <li> 348 <a class="dropdown-item" href="./lifts.html"> 349 <span class="dropdown-text">Lifts</span></a> 350 </li> 351 <li> 352 <a class="dropdown-item" href="./core.html"> 353 <span class="dropdown-text">Core tools</span></a> 354 </li> 355 </ul> 356 </li> 357 <li class="nav-item"> 358 <a class="nav-link" href="./learning.html"> 359<span class="menu-text">Learning</span></a> 360 </li> 361 <li class="nav-item"> 362 <a class="nav-link" href="./downloads.html"> 363<span class="menu-text">Downloads</span></a> 364 </li> 365 <li class="nav-item"> 366 <a class="nav-link" href="./forum.html"> 367<span class="menu-text">Forum</span></a> 368 </li> 369 <li class="nav-item"> 370 <a class="nav-link" href="./about.html"> 371<span class="menu-text">About</span></a> 372 </li> 373</ul> 374 <ul class="navbar-nav navbar-nav-scroll ms-auto"> 375 <li class="nav-item compact"> 376 <a class="nav-link" href="https://github.com/NicolasBoumal/manopt" target="_blank"> <i class="bi bi-github" role="img"> 377</i> 378<span class="menu-text"></span></a> 379 </li> 380 <li class="nav-item compact"> 381 <a class="nav-link" href="mailto:[email protected]"> <i class="bi bi-envelope-at" role="img" aria-label="E-mail"> 382</i> 383<span class="menu-text"></span></a> 384 </li> 385</ul> 386 </div> <!-- /navcollapse --> 387 <div class="quarto-navbar-tools"> 388 <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> 389</div> 390 </div> <!-- /container-fluid --> 391 </nav> 392 <nav class="quarto-secondary-nav"> 393 <div class="container-fluid d-flex"> 394 <button type="button" class="quarto-btn-toggle btn" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }"> 395 <i class="bi bi-layout-text-sidebar-reverse"></i> 396 </button> 397 <nav class="quarto-page-breadcrumbs" aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="./gettingstarted.html">Getting started</a></li></ol></nav> 398 <a class="flex-grow-1" role="button" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }"> 399 </a> 400 </div> 401 </nav> 402</header> 403<!-- content -->
404<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar"> 405<!-- sidebar --> 406 <nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto"> 407 <div class="sidebar-menu-container"> 408 <ul class="list-unstyled mt-1"> 409 <li class="sidebar-item"> 410 <div class="sidebar-item-container"> 411 <a href="./gettingstarted.html" class="sidebar-item-text sidebar-link active"> 412 <span class="menu-text">Getting started</span></a> 413 </div> 414</li> 415 <li class="sidebar-item"> 416 <div class="sidebar-item-container"> 417 <a href="./firstexample.html" class="sidebar-item-text sidebar-link"> 418 <span class="menu-text">A first example</span></a> 419 </div> 420</li> 421 <li class="sidebar-item"> 422 <div class="sidebar-item-container"> 423 <a href="./manifolds.html" class="sidebar-item-text sidebar-link"> 424 <span class="menu-text">Manifolds</span></a> 425 </div> 426</li> 427 <li class="sidebar-item"> 428 <div class="sidebar-item-container"> 429 <a href="./costdescription.html" class="sidebar-item-text sidebar-link"> 430 <span class="menu-text">Cost functions</span></a> 431 </div> 432</li> 433 <li class="sidebar-item"> 434 <div class="sidebar-item-container"> 435 <a href="./solvers.html" class="sidebar-item-text sidebar-link"> 436 <span class="menu-text">Solvers</span></a> 437 </div> 438</li> 439 <li class="sidebar-item"> 440 <div class="sidebar-item-container"> 441 <a href="./tools.html" class="sidebar-item-text sidebar-link"> 442 <span class="menu-text">Helpful tools</span></a> 443 </div> 444</li> 445 <li class="sidebar-item"> 446 <div class="sidebar-item-container"> 447 <a href="./lifts.html" class="sidebar-item-text sidebar-link"> 448 <span class="menu-text">Lifts</span></a> 449 </div> 450</li> 451 <li class="sidebar-item"> 452 <div class="sidebar-item-container"> 453 <a href="./core.html" class="sidebar-item-text sidebar-link"> 454 <span class="menu-text">Core tools</span></a> 455 </div> 456</li> 457 </ul> 458 </div> 459</nav> 460<div id="quarto-sidebar-glass" class="quarto-sidebar-collapse-item" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item"></div> 461<!-- margin-sidebar --> 462 463<!-- main --> 464<main class="content" id="quarto-document-content"> 465 466<header id="title-block-header" class="quarto-title-block default"> 467<div class="quarto-title"> 468<h1 class="title">Getting started</h1> 469</div> 470 471 472 473<div class="quarto-title-meta"> 474 475 476 477 478 </div> 479 480 481 482</header> 483 484 485<section id="manopts-purpose-and-design" class="level2"> 486<h2 class="anchored" data-anchor-id="manopts-purpose-and-design">Manoptâs purpose and design</h2> 487<p>With Manopt, you can solve optimization problems on manifolds and on linear spaces (e.g., matrix spaces) using state-of-the-art algorithms, with minimal effort. The toolbox targets great flexibility in the problem description and comes with advanced features, such as caching and automatic differentiation.</p> 488<p>The toolbox architecture is based on a separation of the manifolds, the solvers and the problem descriptions. For basic use, one only needs to pick a manifold from the library, describe the cost function (and possible derivatives) and pass it on to a solver. Accompanying tools help the user in common tasks such as numerically checking the derivatives, plotting the cost function, computing eigenvalues of the Hessian etc.</p> 489<p>This is a prototyping toolbox, built on the premise that the costly part of solving an optimization problem is querying the cost function, and not the inner machinery of the solver. It is also work in progress: feedback and contributions are welcome!</p> 490<p><a href="https://docs.google.com/forms/d/1U9Ntex_rWI8NfCLPP_b8uE5xDnKXgXG-HVvpHdq1PFo/viewform?usp=send_form" class="btn btn-info">Mailing list</a> Consider registering as a user to hear about updates.</p> 491</section> 492<section id="download" class="level2"> 493<h2 class="anchored" data-anchor-id="download">Download</h2> 494<p>There are two ways to get Manopt:</p> 495<p><a href="./download.html" class="btn btn-primary">Download</a> Download the latest packaged version (v8.0, July 5, 2024).</p> 496<p><a href="https://github.com/NicolasBoumal/manopt" class="btn btn-secondary"><i class="bi bi-github"></i> GitHub</a> Clone the GitHub repository to use the latest updates as they roll out.</p> 497</section> 498<section id="install" class="level2"> 499<h2 class="anchored" data-anchor-id="install">Install</h2> 500<ol type="1"> 501<li>Either git-clone or unzip the whole <code>manopt</code> directory you just downloaded in a location of your choice, say, in <code>/my/directory/</code>.</li> 502<li>Go to <code>/my/directory/manopt/</code> at the Matlab prompt and execute <code>importmanopt</code>.</li> 503<li>You will be asked whether you want to save this path for your next Matlab sessions. If you reply <code>Y</code> (yes) and you have the rights to run <code>savepath</code>, then you wonât need to go through these steps next time you open Matlab.</li> 504</ol> 505</section> 506<section id="check" class="level2"> 507<h2 class="anchored" data-anchor-id="check">Check</h2> 508<p>Go to <code>/my/directory/manopt/</code> and run the script <code>checkinstall.m</code>. If there are no errors, you are done! Otherwise, feel free to <a href="./forum.html">report issues on the forum</a>.</p> 509</section> 510<section id="move-on-to-the-first-example" class="level2"> 511<h2 class="anchored" data-anchor-id="move-on-to-the-first-example">Move on to the first example</h2> 512<p>This tutorial provides detailed instructions from zero to the advanced features of Manopt. Check out <a href="./firstexample.html">
512a first example</a> to get a feel for how things work, then continue through the detailed documentation.</p> 513</section> 514<section id="dig-into-more-advanced-examples" class="level2"> 515<h2 class="anchored" data-anchor-id="dig-into-more-advanced-examples">Dig into more advanced examples</h2> 516<p>You may find it helpful to look through the <a href="https://github.com/NicolasBoumal/manopt/tree/master/examples">examples</a> that ship with Manopt.</p> 517</section> 518<section id="learn-more-of-the-math" class="level2"> 519<h2 class="anchored" data-anchor-id="learn-more-of-the-math">Learn more of the math</h2> 520<p>See our pointers for helpful <a href="./learning.html">learning resources</a> including video lectures and books.</p> 521 522 523</section> 524 525</main> <!-- /main -->
526<script id="quarto-html-after-body" type="application/javascript"> 527window.document.addEventListener("DOMContentLoaded", function (event) { 528 const toggleBodyColorMode = (bsSheetEl) => { 529 const mode = bsSheetEl.getAttribute("data-mode"); 530 const bodyEl = window.document.querySelector("body"); 531 if (mode === "dark") { 532 bodyEl.classList.add("quarto-dark"); 533 bodyEl.classList.remove("quarto-light"); 534 } else { 535 bodyEl.classList.add("quarto-light"); 536 bodyEl.classList.remove("quarto-dark"); 537 } 538 } 539 const toggleBodyColorPrimary = () => { 540 const bsSheetEl = window.document.querySelector("link#quarto-bootstrap"); 541 if (bsSheetEl) { 542 toggleBodyColorMode(bsSheetEl); 543 } 544 } 545 toggleBodyColorPrimary(); 546 const disableStylesheet = (stylesheets) => { 547 for (let i=0; i < stylesheets.length; i++) { 548 const stylesheet = stylesheets[i]; 549 stylesheet.rel = 'prefetch'; 550 } 551 } 552 const enableStylesheet = (stylesheets) => { 553 for (let i=0; i < stylesheets.length; i++) { 554 const stylesheet = stylesheets[i]; 555 stylesheet.rel = 'stylesheet'; 556 } 557 } 558 const manageTransitions = (selector, allowTransitions) => { 559 const els = window.document.querySelectorAll(selector); 560 for (let i=0; i < els.length; i++) { 561 const el = els[i]; 562 if (allowTransitions) { 563 el.classList.remove('notransition'); 564 } else { 565 el.classList.add('notransition'); 566 } 567 } 568 } 569 const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => { 570 const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light'; 571 const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark'; 572 let newTheme = ''; 573 if(darkModeDefault) { 574 newTheme = isAlternate ? baseTheme : alternateTheme; 575 } else { 576 newTheme = isAlternate ? alternateTheme : baseTheme; 577 } 578 const changeGiscusTheme = () => { 579 // From: https://github.com/giscus/giscus/issues/336 580 const sendMessage = (message) => { 581 const iframe = document.querySelector('iframe.giscus-frame'); 582 if (!iframe) return; 583 iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app'); 584 } 585 sendMessage({ 586 setConfig: { 587 theme: newTheme 588 } 589 }); 590 } 591 const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null; 592 if (isGiscussLoaded) { 593 changeGiscusTheme(); 594 } 595 } 596 const toggleColorMode = (alternate) => { 597 // Switch the stylesheets 598 const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate'); 599 manageTransitions('#quarto-margin-sidebar .nav-link', false); 600 if (alternate) { 601 enableStylesheet(alternateStylesheets); 602 for (const sheetNode of alternateStylesheets) { 603 if (sheetNode.id === "quarto-bootstrap") { 604 toggleBodyColorMode(sheetNode); 605 } 606 } 607 } else { 608 disableStylesheet(alternateStylesheets); 609 toggleBodyColorPrimary(); 610 } 611 manageTransitions('#quarto-margin-sidebar .nav-link', true); 612 // Switch the toggles 613 const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle'); 614 for (let i=0; i < toggles.length; i++) { 615 const toggle = toggles[i]; 616 if (toggle) { 617 if (alternate) { 618 toggle.classList.add("alternate"); 619 } else { 620 toggle.classList.remove("alternate"); 621 } 622 } 623 } 624 // Hack to workaround the fact that safari doesn't 625 // properly recolor the scrollbar when toggling (#1455) 626 if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) { 627 manageTransitions("body", false); 628 window.scrollTo(0, 1); 629 setTimeout(() => { 630 window.scrollTo(0, 0); 631 manageTransitions("body", true); 632 }, 40); 633 } 634 } 635 const isFileUrl = () => { 636 return window.location.protocol === 'file:'; 637 } 638 const hasAlternateSentinel = () => { 639 let styleSentinel = getColorSchemeSentinel(); 640 if (styleSentinel !== null) { 641 return styleSentinel === "alternate"; 642 } else { 643 return false;
644 } 645 } 646 const setStyleSentinel = (alternate) => { 647 const value = alternate ? "alternate" : "default"; 648 if (!isFileUrl()) { 649 window.localStorage.setItem("quarto-color-scheme", value); 650 } else { 651 localAlternateSentinel = value; 652 } 653 } 654 const getColorSchemeSentinel = () => { 655 if (!isFileUrl()) { 656 const storageValue = window.localStorage.getItem("quarto-color-scheme"); 657 return storageValue != null ? storageValue : localAlternateSentinel; 658 } else { 659 return localAlternateSentinel; 660 } 661 } 662 const darkModeDefault = false; 663 let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default'; 664 // Dark / light mode switch 665 window.quartoToggleColorScheme = () => { 666 // Read the current dark / light value 667 let toAlternate = !hasAlternateSentinel(); 668 toggleColorMode(toAlternate); 669 setStyleSentinel(toAlternate); 670 toggleGiscusIfUsed(toAlternate, darkModeDefault); 671 }; 672 // Ensure there is a toggle, if there isn't float one in the top right 673 if (window.document.querySelector('.quarto-color-scheme-toggle') === null) { 674 const a = window.document.createElement('a'); 675 a.classList.add('top-right'); 676 a.classList.add('quarto-color-scheme-toggle'); 677 a.href = ""; 678 a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; }; 679 const i = window.document.createElement("i"); 680 i.classList.add('bi'); 681 a.appendChild(i); 682 window.document.body.appendChild(a); 683 } 684 // Switch to dark mode if need be 685 if (hasAlternateSentinel()) { 686 toggleColorMode(true); 687 } else { 688 toggleColorMode(false); 689 } 690 const icon = "î§"; 691 const anchorJS = new window.AnchorJS(); 692 anchorJS.options = { 693 placement: 'right', 694 icon: icon 695 }; 696 anchorJS.add('.anchored'); 697 const isCodeAnnotation = (el) => { 698 for (const clz of el.classList) { 699 if (clz.startsWith('code-annotation-')) { 700 return true; 701 } 702 } 703 return false; 704 } 705 const clipboard = new window.ClipboardJS('.code-copy-button', { 706 text: function(trigger) { 707 const codeEl = trigger.previousElementSibling.cloneNode(true); 708 for (const childEl of codeEl.children) { 709 if (isCodeAnnotation(childEl)) { 710 childEl.remove(); 711 } 712 } 713 return codeEl.innerText; 714 } 715 }); 716 clipboard.on('success', function(e) { 717 // button target 718 const button = e.trigger; 719 // don't keep focus 720 button.blur(); 721 // flash "checked" 722 button.classList.add('code-copy-button-checked'); 723 var currentTitle = button.getAttribute("title"); 724 button.setAttribute("title", "Copied!"); 725 let tooltip; 726 if (window.bootstrap) { 727 button.setAttribute("data-bs-toggle", "tooltip"); 728 button.setAttribute("data-bs-placement", "left"); 729 button.setAttribute("data-bs-title", "Copied!"); 730 tooltip = new bootstrap.Tooltip(button, 731 { trigger: "manual", 732 customClass: "code-copy-button-tooltip", 733 offset: [0, -8]}); 734 tooltip.show(); 735 } 736 setTimeout(function() { 737 if (tooltip) { 738 tooltip.hide(); 739 button.removeAttribute("data-bs-title"); 740 button.removeAttribute("data-bs-toggle"); 741 button.removeAttribute("data-bs-placement"); 742 } 743 button.setAttribute("title", currentTitle); 744 button.classList.remove('code-copy-button-checked'); 745 }, 1000); 746 // clear code selection 747 e.clearSelection(); 748 }); 749 var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//); 750 var mailtoRegex = new RegExp(/^mailto:/); 751 var filterRegex = new RegExp("https:\/\/www\.manopt\.org"); 752 var isInternal = (href) => { 753 return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href); 754 } 755 // Inspect non-navigation links and adorn them if external 756 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)'); 757 for (var i=0; i<links.length; i++) { 758 const link = links[i]; 759 if (!isInternal(link.href)) { 760 // undo the damage that might have been done by quarto-nav.js in the case of 761 // links that we want to consider external 762 if (link.dataset.originalHref !== undefined) { 763 link.href = link.dataset.originalHref; 764 } 765 // target, if specified 766 link.setAttribute("target", "_blank"); 767 if (link.getAttribute("rel") === null) { 768 link.setAttribute("rel", "noopener"); 769 } 770 } 771 } 772 function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) { 773 const config = { 774 allowHTML: true, 775 maxWidth: 500, 776 delay: 100,
777 arrow: false, 778 appendTo: function(el) { 779 return el.parentElement; 780 }, 781 interactive: true, 782 interactiveBorder: 10, 783 theme: 'quarto', 784 placement: 'bottom-start', 785 }; 786 if (contentFn) { 787 config.content = contentFn; 788 } 789 if (onTriggerFn) { 790 config.onTrigger = onTriggerFn; 791 } 792 if (onUntriggerFn) { 793 config.onUntrigger = onUntriggerFn; 794 } 795 window.tippy(el, config); 796 } 797 const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]'); 798 for (var i=0; i<noterefs.length; i++) { 799 const ref = noterefs[i]; 800 tippyHover(ref, function() { 801 // use id or data attribute instead here 802 let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href'); 803 try { href = new URL(href).hash; } catch {} 804 const id = href.replace(/^#\/?/, ""); 805 const note = window.document.getElementById(id); 806 if (note) { 807 return note.innerHTML; 808 } else { 809 return ""; 810 } 811 }); 812 } 813 const xrefs = window.document.querySelectorAll('a.quarto-xref'); 814 const processXRef = (id, note) => { 815 // Strip column container classes 816 const stripColumnClz = (el) => { 817 el.classList.remove("page-full", "page-columns"); 818 if (el.children) { 819 for (const child of el.children) { 820 stripColumnClz(child); 821 } 822 } 823 } 824 stripColumnClz(note) 825 if (id === null || id.startsWith('sec-')) { 826 // Special case sections, only their first couple elements 827 const container = document.createElement("div"); 828 if (note.children && note.children.length > 2) { 829 container.appendChild(note.children[0].cloneNode(true)); 830 for (let i = 1; i < note.children.length; i++) { 831 const child = note.children[i]; 832 if (child.tagName === "P" && child.innerText === "") { 833 continue; 834 } else { 835 container.appendChild(child.cloneNode(true)); 836 break; 837 } 838 } 839 if (window.Quarto?.typesetMath) { 840 window.Quarto.typesetMath(container); 841 } 842 return container.innerHTML 843 } else { 844 if (window.Quarto?.typesetMath) { 845 window.Quarto.typesetMath(note); 846 } 847 return note.innerHTML; 848 } 849 } else { 850 // Remove any anchor links if they are present 851 const anchorLink = note.querySelector('a.anchorjs-link'); 852 if (anchorLink) { 853 anchorLink.remove(); 854 } 855 if (window.Quarto?.typesetMath) { 856 window.Quarto.typesetMath(note); 857 } 858 // TODO in 1.5, we should make sure this works without a callout special case 859 if (note.classList.contains("callout")) { 860 return note.outerHTML; 861 } else { 862 return note.innerHTML; 863 } 864 } 865 } 866 for (var i=0; i<xrefs.length; i++) { 867 const xref = xrefs[i]; 868 tippyHover(xref, undefined, function(instance) { 869 instance.disable(); 870 let url = xref.getAttribute('href'); 871 let hash = undefined; 872 if (url.startsWith('#')) { 873 hash = url; 874 } else { 875 try { hash = new URL(url).hash; } catch {} 876 } 877 if (hash) { 878 const id = hash.replace(/^#\/?/, ""); 879 const note = window.document.getElementById(id); 880 if (note !== null) { 881 try { 882 const html = processXRef(id, note.cloneNode(true)); 883 instance.setContent(html); 884 } finally { 885 instance.enable(); 886 instance.show(); 887 } 888 } else { 889 // See if we can fetch this 890 fetch(url.split('#')[0]) 891 .then(res => res.text()) 892 .then(html => { 893 const parser = new DOMParser(); 894 const htmlDoc = parser.parseFromString(html, "text/html"); 895 const note = htmlDoc.getElementById(id); 896 if (note !== null) { 897 const html = processXRef(id, note); 898 instance.setContent(html); 899 } 900 }).finally(() => { 901 instance.enable(); 902 instance.show(); 903 }); 904 } 905 } else { 906 // See if we can fetch a full url (with no hash to target)
907 // This is a special case and we should probably do some content thinning / targeting 908 fetch(url) 909 .then(res => res.text()) 910 .then(html => { 911 const parser = new DOMParser(); 912 const htmlDoc = parser.parseFromString(html, "text/html"); 913 const note = htmlDoc.querySelector('main.content'); 914 if (note !== null) { 915 // This should only happen for chapter cross references 916 // (since there is no id in the URL) 917 // remove the first header 918 if (note.children.length > 0 && note.children[0].tagName === "HEADER") { 919 note.children[0].remove(); 920 } 921 const html = processXRef(null, note); 922 instance.setContent(html); 923 } 924 }).finally(() => { 925 instance.enable(); 926 instance.show(); 927 }); 928 } 929 }, function(instance) { 930 }); 931 } 932 let selectedAnnoteEl; 933 const selectorForAnnotation = ( cell, annotation) => { 934 let cellAttr = 'data-code-cell="' + cell + '"'; 935 let lineAttr = 'data-code-annotation="' + annotation + '"'; 936 const selector = 'span[' + cellAttr + '][' + lineAttr + ']'; 937 return selector; 938 } 939 const selectCodeLines = (annoteEl) => { 940 const doc = window.document; 941 const targetCell = annoteEl.getAttribute("data-target-cell"); 942 const targetAnnotation = annoteEl.getAttribute("data-target-annotation"); 943 const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation)); 944 const lines = annoteSpan.getAttribute("data-code-lines").split(","); 945 const lineIds = lines.map((line) => { 946 return targetCell + "-" + line; 947 }) 948 let top = null; 949 let height = null; 950 let parent = null; 951 if (lineIds.length > 0) { 952 //compute the position of the single el (top and bottom and make a div) 953 const el = window.document.getElementById(lineIds[0]); 954 top = el.offsetTop; 955 height = el.offsetHeight; 956 parent = el.parentElement.parentElement; 957 if (lineIds.length > 1) { 958 const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]); 959 const bottom = lastEl.offsetTop + lastEl.offsetHeight; 960 height = bottom - top; 961 } 962 if (top !== null && height !== null && parent !== null) { 963 // cook up a div (if necessary) and position it 964 let div = window.document.getElementById("code-annotation-line-highlight"); 965 if (div === null) { 966 div = window.document.createElement("div"); 967 div.setAttribute("id", "code-annotation-line-highlight"); 968 div.style.position = 'absolute'; 969 parent.appendChild(div); 970 } 971 div.style.top = top - 2 + "px"; 972 div.style.height = height + 4 + "px"; 973 div.style.left = 0; 974 let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter"); 975 if (gutterDiv === null) { 976 gutterDiv = window.document.createElement("div"); 977 gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter"); 978 gutterDiv.style.position = 'absolute'; 979 const codeCell = window.document.getElementById(targetCell); 980 const gutter = codeCell.querySelector('.code-annotation-gutter'); 981 gutter.appendChild(gutterDiv); 982 } 983 gutterDiv.style.top = top - 2 + "px"; 984 gutterDiv.style.height = height + 4 + "px"; 985 } 986 selectedAnnoteEl = annoteEl; 987 } 988 }; 989 const unselectCodeLines = () => { 990 const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"]; 991 elementsIds.forEach((elId) => { 992 const div = window.document.getElementById(elId); 993 if (div) { 994 div.remove(); 995 } 996 }); 997 selectedAnnoteEl = undefined; 998 }; 999 // Handle positioning of the toggle 1000 window.addEventListener( 1001 "resize", 1002 throttle(() => { 1003 elRect = undefined; 1004 if (selectedAnnoteEl) { 1005 selectCodeLines(selectedAnnoteEl); 1006 } 1007 }, 10) 1008 ); 1009 function throttle(fn, ms) { 1010 let throttle = false;
1011 let timer; 1012 return (...args) => { 1013 if(!throttle) { // first call gets through 1014 fn.apply(this, args); 1015 throttle = true; 1016 } else { // all the others get throttled 1017 if(timer) clearTimeout(timer); // cancel #2 1018 timer = setTimeout(() => { 1019 fn.apply(this, args); 1020 timer = throttle = false; 1021 }, ms); 1022 } 1023 }; 1024 } 1025 // Attach click handler to the DT 1026 const annoteDls = window.document.querySelectorAll('dt[data-target-cell]'); 1027 for (const annoteDlNode of annoteDls) { 1028 annoteDlNode.addEventListener('click', (event) => { 1029 const clickedEl = event.target; 1030 if (clickedEl !== selectedAnnoteEl) { 1031 unselectCodeLines(); 1032 const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active'); 1033 if (activeEl) { 1034 activeEl.classList.remove('code-annotation-active'); 1035 } 1036 selectCodeLines(clickedEl); 1037 clickedEl.classList.add('code-annotation-active'); 1038 } else { 1039 // Unselect the line 1040 unselectCodeLines(); 1041 clickedEl.classList.remove('code-annotation-active'); 1042 } 1043 }); 1044 } 1045 const findCites = (el) => { 1046 const parentEl = el.parentElement; 1047 if (parentEl) { 1048 const cites = parentEl.dataset.cites; 1049 if (cites) { 1050 return { 1051 el, 1052 cites: cites.split(' ') 1053 }; 1054 } else { 1055 return findCites(el.parentElement) 1056 } 1057 } else { 1058 return undefined; 1059 } 1060 }; 1061 var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); 1062 for (var i=0; i<bibliorefs.length; i++) { 1063 const ref = bibliorefs[i]; 1064 const citeInfo = findCites(ref); 1065 if (citeInfo) { 1066 tippyHover(citeInfo.el, function() { 1067 var popup = window.document.createElement('div'); 1068 citeInfo.cites.forEach(function(cite) { 1069 var citeDiv = window.document.createElement('div'); 1070 citeDiv.classList.add('hanging-indent'); 1071 citeDiv.classList.add('csl-entry'); 1072 var biblioDiv = window.document.getElementById('ref-' + cite); 1073 if (biblioDiv) { 1074 citeDiv.innerHTML = biblioDiv.innerHTML; 1075 } 1076 popup.appendChild(citeDiv); 1077 }); 1078 return popup.innerHTML; 1079 }); 1080 } 1081 } 1082}); 1083</script>
1083 1084</div> <!-- /content --> 1085<footer class="footer"> 1086 <div class="nav-footer"> 1087 <div class="nav-footer-left"> 1088 1089 </div> 1090 <div class="nav-footer-center"> 1091 1092<div class="cookie-consent-footer"><a href="#" id="open_preferences_center">Cookie preferences -- it helps us to know which pages are read the most</a></div></div> 1093 <div class="nav-footer-right"> 1094 1095 </div> 1096 </div> 1097</footer> 1098 1099 1100 1101
1102<script src="site_libs/quarto-html/zenscroll-min.js"></script>
1102 1103</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.