From 89f7ef1715990cb6ee9b21114e9753c4c323fa2f Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Tue, 19 Sep 2023 22:31:52 +0000 Subject: [PATCH] build based on 2c1b189 --- previews/PR2274/.documenter-siteinfo.json | 1 + previews/PR2274/MathOptInterface.pdf | Bin 0 -> 1248238 bytes previews/PR2274/assets/documenter.js | 883 ++++++++++++++++ previews/PR2274/assets/latency.png | Bin 0 -> 25175 bytes .../PR2274/assets/themes/documenter-dark.css | 7 + .../PR2274/assets/themes/documenter-light.css | 9 + previews/PR2274/assets/themeswap.js | 84 ++ previews/PR2274/assets/warner.js | 52 + previews/PR2274/background/duality/index.html | 80 ++ .../infeasibility_certificates/index.html | 28 + .../PR2274/background/motivation/index.html | 2 + .../background/naming_conventions/index.html | 2 + previews/PR2274/changelog/index.html | 30 + .../PR2274/developer/checklists/index.html | 112 ++ previews/PR2274/index.html | 9 + previews/PR2274/manual/constraints/index.html | 22 + previews/PR2274/manual/models/index.html | 2 + .../PR2274/manual/modification/index.html | 125 +++ previews/PR2274/manual/solutions/index.html | 35 + .../PR2274/manual/standard_form/index.html | 6 + previews/PR2274/manual/variables/index.html | 13 + .../PR2274/reference/callbacks/index.html | 32 + .../PR2274/reference/constraints/index.html | 12 + previews/PR2274/reference/errors/index.html | 48 + previews/PR2274/reference/models/index.html | 132 +++ .../PR2274/reference/modification/index.html | 27 + .../PR2274/reference/nonlinear/index.html | 78 ++ .../PR2274/reference/standard_form/index.html | 989 ++++++++++++++++++ .../PR2274/reference/variables/index.html | 24 + previews/PR2274/release_notes/index.html | 30 + previews/PR2274/search_index.js | 3 + previews/PR2274/siteinfo.js | 1 + .../submodules/Benchmarks/overview/index.html | 20 + .../Benchmarks/reference/index.html | 17 + .../Bridges/list_of_bridges/index.html | 110 ++ .../submodules/Bridges/overview/index.html | 53 + .../submodules/Bridges/reference/index.html | 195 ++++ .../FileFormats/overview/index.html | 137 +++ .../FileFormats/reference/index.html | 18 + .../submodules/Nonlinear/overview/index.html | 183 ++++ .../submodules/Nonlinear/reference/index.html | 147 +++ .../submodules/Test/overview/index.html | 166 +++ .../submodules/Test/reference/index.html | 50 + .../submodules/Utilities/overview/index.html | 250 +++++ .../submodules/Utilities/reference/index.html | 289 +++++ .../tutorials/bridging_constraint/index.html | 102 ++ previews/PR2274/tutorials/example/index.html | 45 + .../PR2274/tutorials/implementing/index.html | 114 ++ previews/PR2274/tutorials/latency/index.html | 129 +++ .../manipulating_expressions/index.html | 22 + .../PR2274/tutorials/mathprogbase/index.html | 54 + 51 files changed, 4979 insertions(+) create mode 100644 previews/PR2274/.documenter-siteinfo.json create mode 100644 previews/PR2274/MathOptInterface.pdf create mode 100644 previews/PR2274/assets/documenter.js create mode 100644 previews/PR2274/assets/latency.png create mode 100644 previews/PR2274/assets/themes/documenter-dark.css create mode 100644 previews/PR2274/assets/themes/documenter-light.css create mode 100644 previews/PR2274/assets/themeswap.js create mode 100644 previews/PR2274/assets/warner.js create mode 100644 previews/PR2274/background/duality/index.html create mode 100644 previews/PR2274/background/infeasibility_certificates/index.html create mode 100644 previews/PR2274/background/motivation/index.html create mode 100644 previews/PR2274/background/naming_conventions/index.html create mode 100644 previews/PR2274/changelog/index.html create mode 100644 previews/PR2274/developer/checklists/index.html create mode 100644 previews/PR2274/index.html create mode 100644 previews/PR2274/manual/constraints/index.html create mode 100644 previews/PR2274/manual/models/index.html create mode 100644 previews/PR2274/manual/modification/index.html create mode 100644 previews/PR2274/manual/solutions/index.html create mode 100644 previews/PR2274/manual/standard_form/index.html create mode 100644 previews/PR2274/manual/variables/index.html create mode 100644 previews/PR2274/reference/callbacks/index.html create mode 100644 previews/PR2274/reference/constraints/index.html create mode 100644 previews/PR2274/reference/errors/index.html create mode 100644 previews/PR2274/reference/models/index.html create mode 100644 previews/PR2274/reference/modification/index.html create mode 100644 previews/PR2274/reference/nonlinear/index.html create mode 100644 previews/PR2274/reference/standard_form/index.html create mode 100644 previews/PR2274/reference/variables/index.html create mode 100644 previews/PR2274/release_notes/index.html create mode 100644 previews/PR2274/search_index.js create mode 100644 previews/PR2274/siteinfo.js create mode 100644 previews/PR2274/submodules/Benchmarks/overview/index.html create mode 100644 previews/PR2274/submodules/Benchmarks/reference/index.html create mode 100644 previews/PR2274/submodules/Bridges/list_of_bridges/index.html create mode 100644 previews/PR2274/submodules/Bridges/overview/index.html create mode 100644 previews/PR2274/submodules/Bridges/reference/index.html create mode 100644 previews/PR2274/submodules/FileFormats/overview/index.html create mode 100644 previews/PR2274/submodules/FileFormats/reference/index.html create mode 100644 previews/PR2274/submodules/Nonlinear/overview/index.html create mode 100644 previews/PR2274/submodules/Nonlinear/reference/index.html create mode 100644 previews/PR2274/submodules/Test/overview/index.html create mode 100644 previews/PR2274/submodules/Test/reference/index.html create mode 100644 previews/PR2274/submodules/Utilities/overview/index.html create mode 100644 previews/PR2274/submodules/Utilities/reference/index.html create mode 100644 previews/PR2274/tutorials/bridging_constraint/index.html create mode 100644 previews/PR2274/tutorials/example/index.html create mode 100644 previews/PR2274/tutorials/implementing/index.html create mode 100644 previews/PR2274/tutorials/latency/index.html create mode 100644 previews/PR2274/tutorials/manipulating_expressions/index.html create mode 100644 previews/PR2274/tutorials/mathprogbase/index.html diff --git a/previews/PR2274/.documenter-siteinfo.json b/previews/PR2274/.documenter-siteinfo.json new file mode 100644 index 0000000000..36bed24041 --- /dev/null +++ b/previews/PR2274/.documenter-siteinfo.json @@ -0,0 +1 @@ +{"documenter":{"julia_version":"1.9.3","generation_timestamp":"2023-09-19T22:23:47","documenter_version":"1.0.1"}} \ No newline at end of file diff --git a/previews/PR2274/MathOptInterface.pdf b/previews/PR2274/MathOptInterface.pdf new file mode 100644 index 0000000000000000000000000000000000000000..458e43623ed869666feeb2efc595b72645d95366 GIT binary patch literal 1248238 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≫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

E=(T~ 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 z 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

)`-5bhDrPz zfFUY^Zr0+@!k>+H5aqeElIcM4>s;jgdu!WE>A3k-!^Ae86q)7|2K z;_lX`;a`BQBEjvlGy4-xpt9j~24`VPB&RJyW|;HSatFHpbopLO1)=X_cTL`yJxkus zMOsR^;-|mz`z?#@CKB(IU5J7l%ocP66xM&wWLEPL8dRl?;|sfOr>KGR3n{oAYZNwo zAK5S9BDJEQXJ^$a%QV!?VLEsH9n=!J3KF26ULBqmd!Va24y|viQem}>6-KLo-3Oxw zr`baBF%IE6-Vs>-(8v0Rjh@6!DsYQS*$ZP73I^%7B8MGBx@`U#jK7$uby`4PEH`Ae zsaSV+m?QIbSiIh6vSZqX>Km*O>CDsS?UpN+XRxk2;~miy)lgHXa}sDzE3nz16LXQI zq1Tbo)zhy{7bxrlpJTq2;HvGY&g!Trdo;?`dVv&IJ+;9YtbK76Ubb>%m998cE!b4D zQwqBK>lYq|uX;Z-}39h_ZJ7p!1P6|grz7ocO z4CWVKfn2Jt{3dn8!rIQlU_Bp;qAhNyQ{&}J0S={V6BVKqGE6%GX=k#votK(Wi{sOa z5qb6diT#UJ+sCA46Rc7w^kKbxm@!D|y-Ho7JRQC&VNe=Ql;F*Xn%DO3>$&)PEkV zE70a=D2RNrJLCYh2e2@aqBzWi&XAMh?E+xhY^QIdU;2VswGPMTa~=YKs<5*TIa(y_ zM{Y$s2y0~iiLn1Vusn-0_`B>eCn-C8ko-t*iB&ypjaq2$Fa>;m+;I*~g>&y(r#hN& zY7lQtGGsjVB->$xY=2NcYugJG$rqI5%KO*}3mHt#UNKtAIT=d$yronoZ0fIVW5Sgz z3THk`*Y3*pBIDQg_-dJzEKZ1?SAhG))dm-VB14wMveJ`EFBHE?e-P&fMrVT!i$r?qEFGI0W=H8P8_p2L0@rw#5um)5IsZw! zyeB`i@pabg9hJ`Snv{AdkAs|;Ju?}rQ`!W!T9l*~pCYU5)aw;R0lH_2mz99WFj&4aETv1$Z^u52D;9y^{o+SA52rdWjW%1fyJB&&tT9M(9U+;w z=)~YMBFK1PDq5-Lcz;lHIuzT-EEy?&I&_*?oD$%O(^zX#v=3K(w##(ws0Ji};+$U% zo4=>*ZMU{_;1O>ceC}MK`aA`{1C@G#*k_P>Ny|TR|839h_trU5S}(~2Ky#<*nm(&0 z16wG_OV)r9`)NPyB$9pl6Ym6@RDu$lG&uqb!bJ?tqDT=c+-S0HldJT%*FnX@wT(Zj zS9e-kJLfW~l*h`}`0s9sQ-bKh^g$Yj<*vx3aPJWUmeTwpCipZElbJPH8^XS_5XstJ z8<&0Nm5ou_$%dSn9MdP2jLY9a`$XxLk?DsFWiag0?m8sAUAoU?Z7=`T58?aL@$UDy zNQisuV9US<^K37r;7o^Yi2ZAZ>bI~}^o^FuSchp3XdYVJ&b7mt4C7Hg+{ys@#rZu- z9|82_%ons@#vW;pbTH8gS18UItL6DBrpah-XYJe%kHGeA5t6%BYaYeFKh;oG9(T4^ z4kfL1N-$p49ztpjN>>OSuJy%@zS-^7wj?+BY*wB&U34!siQccQj$kp41&PsTgl>c) z(Ii$oEz)|a+C%g1m(=zl@*`0y+oseOq>fn+_w?!K+iH^xZy+szRh|-a+f`J7+BNiN zMGRZ-!?@{paBk;8^nyE`v#^vs zxnH>|FQw5w*R^Ov7LsfxVm@?RNvϏHA~!pmTf-wj8b%x@~~c;NRgAFE$&)V$wp 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ྣ-ZYp= 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∈Pgak9m4P~fo4Afk_*T88bS;f=1&ge*5Av30e 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

m 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 literal 0 HcmV?d00001 diff --git a/previews/PR2274/assets/documenter.js b/previews/PR2274/assets/documenter.js new file mode 100644 index 0000000000..f93caf595e --- /dev/null +++ b/previews/PR2274/assets/documenter.js @@ -0,0 +1,883 @@ +// Generated by Documenter.jl +requirejs.config({ + paths: { + 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia.min', + 'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/headroom.min', + 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min', + 'minisearch': 'https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min', + 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min', + 'mathjax': 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-AMS_HTML', + 'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/jQuery.headroom.min', + 'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min', + 'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia-repl.min', + }, + shim: { + "highlight-julia": { + "deps": [ + "highlight" + ] + }, + "mathjax": { + "exports": "MathJax" + }, + "headroom-jquery": { + "deps": [ + "jquery", + "headroom" + ] + }, + "highlight-julia-repl": { + "deps": [ + "highlight" + ] + } +} +}); +//////////////////////////////////////////////////////////////////////////////// +require(['mathjax'], function(MathJax) { +MathJax.Hub.Config({ + "jax": [ + "input/TeX", + "output/HTML-CSS", + "output/NativeMML" + ], + "TeX": { + "equationNumbers": { + "autoNumber": "AMS" + } + }, + "tex2jax": { + "inlineMath": [ + [ + "$", + "$" + ], + [ + "\\(", + "\\)" + ] + ], + "processEscapes": true + }, + "config": [ + "MMLorHTML.js" + ], + "extensions": [ + "MathMenu.js", + "MathZoom.js", + "TeX/AMSmath.js", + "TeX/AMSsymbols.js", + "TeX/autobold.js", + "TeX/autoload-all.js" + ] +} +); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($) { +$(document).ready(function() { + hljs.highlightAll(); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +var isExpanded = true; + +$(document).on("click", ".docstring header", function () { + let articleToggleTitle = "Expand docstring"; + + if ($(this).siblings("section").is(":visible")) { + $(this) + .find(".docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + } else { + $(this) + .find(".docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + articleToggleTitle = "Collapse docstring"; + } + + $(this) + .find(".docstring-article-toggle-button") + .prop("title", articleToggleTitle); + $(this).siblings("section").slideToggle(); +}); + +$(document).on("click", ".docs-article-toggle-button", function () { + let articleToggleTitle = "Expand docstring"; + let navArticleToggleTitle = "Expand all docstrings"; + + if (isExpanded) { + $(this).removeClass("fa-chevron-up").addClass("fa-chevron-down"); + $(".docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + + isExpanded = false; + + $(".docstring section").slideUp(); + } else { + $(this).removeClass("fa-chevron-down").addClass("fa-chevron-up"); + $(".docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + isExpanded = true; + articleToggleTitle = "Collapse docstring"; + navArticleToggleTitle = "Collapse all docstrings"; + + $(".docstring section").slideDown(); + } + + $(this).prop("title", navArticleToggleTitle); + $(".docstring-article-toggle-button").prop("title", articleToggleTitle); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require([], function() { +function addCopyButtonCallbacks() { + for (const el of document.getElementsByTagName("pre")) { + const button = document.createElement("button"); + button.classList.add("copy-button", "fa-solid", "fa-copy"); + button.setAttribute("aria-label", "Copy this code block"); + button.setAttribute("title", "Copy"); + + el.appendChild(button); + + const success = function () { + button.classList.add("success", "fa-check"); + button.classList.remove("fa-copy"); + }; + + const failure = function () { + button.classList.add("error", "fa-xmark"); + button.classList.remove("fa-copy"); + }; + + button.addEventListener("click", function () { + copyToClipboard(el.innerText).then(success, failure); + + setTimeout(function () { + button.classList.add("fa-copy"); + button.classList.remove("success", "fa-check", "fa-xmark"); + }, 5000); + }); + } +} + +function copyToClipboard(text) { + // clipboard API is only available in secure contexts + if (window.navigator && window.navigator.clipboard) { + return window.navigator.clipboard.writeText(text); + } else { + return new Promise(function (resolve, reject) { + try { + const el = document.createElement("textarea"); + el.textContent = text; + el.style.position = "fixed"; + el.style.opacity = 0; + document.body.appendChild(el); + el.select(); + document.execCommand("copy"); + + resolve(); + } catch (err) { + reject(err); + } finally { + document.body.removeChild(el); + } + }); + } +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", addCopyButtonCallbacks); +} else { + addCopyButtonCallbacks(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) { + +// Manages the top navigation bar (hides it when the user starts scrolling down on the +// mobile). +window.Headroom = Headroom; // work around buggy module loading? +$(document).ready(function () { + $("#documenter .docs-navbar").headroom({ + tolerance: { up: 10, down: 10 }, + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'minisearch'], function($, minisearch) { + +// In general, most search related things will have "search" as a prefix. +// To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc + +let results = []; +let timer = undefined; + +let data = documenterSearchIndex["docs"].map((x, key) => { + x["id"] = key; // minisearch requires a unique for each object + return x; +}); + +// list below is the lunr 2.1.3 list minus the intersect with names(Base) +// (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) +// ideally we'd just filter the original list but it's not available as a variable +const stopWords = new Set([ + "a", + "able", + "about", + "across", + "after", + "almost", + "also", + "am", + "among", + "an", + "and", + "are", + "as", + "at", + "be", + "because", + "been", + "but", + "by", + "can", + "cannot", + "could", + "dear", + "did", + "does", + "either", + "ever", + "every", + "from", + "got", + "had", + "has", + "have", + "he", + "her", + "hers", + "him", + "his", + "how", + "however", + "i", + "if", + "into", + "it", + "its", + "just", + "least", + "like", + "likely", + "may", + "me", + "might", + "most", + "must", + "my", + "neither", + "no", + "nor", + "not", + "of", + "off", + "often", + "on", + "or", + "other", + "our", + "own", + "rather", + "said", + "say", + "says", + "she", + "should", + "since", + "so", + "some", + "than", + "that", + "the", + "their", + "them", + "then", + "there", + "these", + "they", + "this", + "tis", + "to", + "too", + "twas", + "us", + "wants", + "was", + "we", + "were", + "what", + "when", + "who", + "whom", + "why", + "will", + "would", + "yet", + "you", + "your", +]); + +let index = new minisearch({ + fields: ["title", "text"], // fields to index for full-text search + storeFields: ["location", "title", "text", "category", "page"], // fields to return with search results + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + } + + return word ?? null; + }, + // add . as a separator, because otherwise "title": "Documenter.Anchors.add!", would not find anything if searching for "add!", only for the entire qualification + tokenize: (string) => string.split(/[\s\-\.]+/), + // options which will be applied during the search + searchOptions: { + boost: { title: 100 }, + fuzzy: 2, + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + } + + return word ?? null; + }, + tokenize: (string) => string.split(/[\s\-\.]+/), + }, +}); + +index.addAll(data); + +let filters = [...new Set(data.map((x) => x.category))]; +var modal_filters = make_modal_body_filters(filters); +var filter_results = []; + +$(document).on("keyup", ".documenter-search-input", function (event) { + // Adding a debounce to prevent disruptions from super-speed typing! + debounce(() => update_search(filter_results), 300); +}); + +$(document).on("click", ".search-filter", function () { + if ($(this).hasClass("search-filter-selected")) { + $(this).removeClass("search-filter-selected"); + } else { + $(this).addClass("search-filter-selected"); + } + + // Adding a debounce to prevent disruptions from crazy clicking! + debounce(() => get_filters(), 300); +}); + +/** + * A debounce function, takes a function and an optional timeout in milliseconds + * + * @function callback + * @param {number} timeout + */ +function debounce(callback, timeout = 300) { + clearTimeout(timer); + timer = setTimeout(callback, timeout); +} + +/** + * Make/Update the search component + * + * @param {string[]} selected_filters + */ +function update_search(selected_filters = []) { + let initial_search_body = ` +
Type something to get started!
+ `; + + let querystring = $(".documenter-search-input").val(); + + if (querystring.trim()) { + results = index.search(querystring, { + filter: (result) => { + // Filtering results + if (selected_filters.length === 0) { + return result.score >= 1; + } else { + return ( + result.score >= 1 && selected_filters.includes(result.category) + ); + } + }, + }); + + let search_result_container = ``; + let search_divider = `
`; + + if (results.length) { + let links = []; + let count = 0; + let search_results = ""; + + results.forEach(function (result) { + if (result.location) { + // Checking for duplication of results for the same page + if (!links.includes(result.location)) { + search_results += make_search_result(result, querystring); + count++; + } + + links.push(result.location); + } + }); + + let result_count = `
${count} result(s)
`; + + search_result_container = ` +
+ ${modal_filters} + ${search_divider} + ${result_count} +
+ ${search_results} +
+
+ `; + } else { + search_result_container = ` +
+ ${modal_filters} + ${search_divider} +
0 result(s)
+
+
No result found!
+ `; + } + + if ($(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").removeClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(search_result_container); + } else { + filter_results = []; + modal_filters = make_modal_body_filters(filters, filter_results); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(initial_search_body); + } +} + +/** + * Make the modal filter html + * + * @param {string[]} filters + * @param {string[]} selected_filters + * @returns string + */ +function make_modal_body_filters(filters, selected_filters = []) { + let str = ``; + + filters.forEach((val) => { + if (selected_filters.includes(val)) { + str += `
${val}`; + } else { + str += `${val}`; + } + }); + + let filter_html = ` +
+ Filters: + ${str} +
+ `; + + return filter_html; +} + +/** + * Make the result component given a minisearch result data object and the value of the search input as queryString. + * To view the result object structure, refer: https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchresult + * + * @param {object} result + * @param {string} querystring + * @returns string + */ +function make_search_result(result, querystring) { + let search_divider = `
`; + let display_link = + result.location.slice(Math.max(0), Math.min(50, result.location.length)) + + (result.location.length > 30 ? "..." : ""); // To cut-off the link because it messes with the overflow of the whole div + + if (result.page !== "") { + display_link += ` (${result.page})`; + } + + let textindex = new RegExp(`\\b${querystring}\\b`, "i").exec(result.text); + let text = + textindex !== null + ? result.text.slice( + Math.max(textindex.index - 100, 0), + Math.min( + textindex.index + querystring.length + 100, + result.text.length + ) + ) + : ""; // cut-off text before and after from the match + + let display_result = text.length + ? "..." + + text.replace( + new RegExp(`\\b${querystring}\\b`, "i"), // For first occurrence + '$&' + ) + + "..." + : ""; // highlights the match + + let in_code = false; + if (!["page", "section"].includes(result.category.toLowerCase())) { + in_code = true; + } + + // We encode the full url to escape some special characters which can lead to broken links + let result_div = ` + +
+
${result.title}
+
${result.category}
+
+

+ ${display_result} +

+
+ ${display_link} +
+
+ ${search_divider} + `; + + return result_div; +} + +/** + * Get selected filters, remake the filter html and lastly update the search modal + */ +function get_filters() { + let ele = $(".search-filters .search-filter-selected").get(); + filter_results = ele.map((x) => $(x).text().toLowerCase()); + modal_filters = make_modal_body_filters(filters, filter_results); + update_search(filter_results); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Modal settings dialog +$(document).ready(function () { + var settings = $("#documenter-settings"); + $("#documenter-settings-button").click(function () { + settings.toggleClass("is-active"); + }); + // Close the dialog if X is clicked + $("#documenter-settings button.delete").click(function () { + settings.removeClass("is-active"); + }); + // Close dialog if ESC is pressed + $(document).keyup(function (e) { + if (e.keyCode == 27) settings.removeClass("is-active"); + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +let search_modal_header = ` + +`; + +let initial_search_body = ` +
Type something to get started!
+`; + +let search_modal_footer = ` +
+ + Ctrl + + / to search + + esc to close +
+`; + +$(document.body).append( + ` + + ` +); + +document.querySelector(".docs-search-query").addEventListener("click", () => { + openModal(); +}); + +document.querySelector(".close-search-modal").addEventListener("click", () => { + closeModal(); +}); + +$(document).on("click", ".search-result-link", function () { + closeModal(); +}); + +document.addEventListener("keydown", (event) => { + if ((event.ctrlKey || event.metaKey) && event.key === "/") { + openModal(); + } else if (event.key === "Escape") { + closeModal(); + } + + return false; +}); + +// Functions to open and close a modal +function openModal() { + let searchModal = document.querySelector("#search-modal"); + + searchModal.classList.add("is-active"); + document.querySelector(".documenter-search-input").focus(); +} + +function closeModal() { + let searchModal = document.querySelector("#search-modal"); + let initial_search_body = ` +
Type something to get started!
+ `; + + searchModal.classList.remove("is-active"); + document.querySelector(".documenter-search-input").blur(); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".documenter-search-input").val(""); + $(".search-modal-card-body").html(initial_search_body); +} + +document + .querySelector("#search-modal .modal-background") + .addEventListener("click", () => { + closeModal(); + }); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Manages the showing and hiding of the sidebar. +$(document).ready(function () { + var sidebar = $("#documenter > .docs-sidebar"); + var sidebar_button = $("#documenter-sidebar-button"); + sidebar_button.click(function (ev) { + ev.preventDefault(); + sidebar.toggleClass("visible"); + if (sidebar.hasClass("visible")) { + // Makes sure that the current menu item is visible in the sidebar. + $("#documenter .docs-menu a.is-active").focus(); + } + }); + $("#documenter > .docs-main").bind("click", function (ev) { + if ($(ev.target).is(sidebar_button)) { + return; + } + if (sidebar.hasClass("visible")) { + sidebar.removeClass("visible"); + } + }); +}); + +// Resizes the package name / sitename in the sidebar if it is too wide. +// Inspired by: https://github.com/davatron5000/FitText.js +$(document).ready(function () { + e = $("#documenter .docs-autofit"); + function resize() { + var L = parseInt(e.css("max-width"), 10); + var L0 = e.width(); + if (L0 > L) { + var h0 = parseInt(e.css("font-size"), 10); + e.css("font-size", (L * h0) / L0); + // TODO: make sure it survives resizes? + } + } + // call once and then register events + resize(); + $(window).resize(resize); + $(window).on("orientationchange", resize); +}); + +// Scroll the navigation bar to the currently selected menu item +$(document).ready(function () { + var sidebar = $("#documenter .docs-menu").get(0); + var active = $("#documenter .docs-menu .is-active").get(0); + if (typeof active !== "undefined") { + sidebar.scrollTop = active.offsetTop - sidebar.offsetTop - 15; + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Theme picker setup +$(document).ready(function () { + // onchange callback + $("#documenter-themepicker").change(function themepick_callback(ev) { + var themename = $("#documenter-themepicker option:selected").attr("value"); + if (themename === "auto") { + // set_theme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); + window.localStorage.removeItem("documenter-theme"); + } else { + // set_theme(themename); + window.localStorage.setItem("documenter-theme", themename); + } + // We re-use the global function from themeswap.js to actually do the swapping. + set_theme_from_local_storage(); + }); + + // Make sure that the themepicker displays the correct theme when the theme is retrieved + // from localStorage + if (typeof window.localStorage !== "undefined") { + var theme = window.localStorage.getItem("documenter-theme"); + if (theme !== null) { + $("#documenter-themepicker option").each(function (i, e) { + e.selected = e.value === theme; + }); + } + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// update the version selector with info from the siteinfo.js and ../versions.js files +$(document).ready(function () { + // If the version selector is disabled with DOCUMENTER_VERSION_SELECTOR_DISABLED in the + // siteinfo.js file, we just return immediately and not display the version selector. + if ( + typeof DOCUMENTER_VERSION_SELECTOR_DISABLED === "boolean" && + DOCUMENTER_VERSION_SELECTOR_DISABLED + ) { + return; + } + + var version_selector = $("#documenter .docs-version-selector"); + var version_selector_select = $("#documenter .docs-version-selector select"); + + version_selector_select.change(function (x) { + target_href = version_selector_select + .children("option:selected") + .get(0).value; + window.location.href = target_href; + }); + + // add the current version to the selector based on siteinfo.js, but only if the selector is empty + if ( + typeof DOCUMENTER_CURRENT_VERSION !== "undefined" && + $("#version-selector > option").length == 0 + ) { + var option = $( + "" + ); + version_selector_select.append(option); + } + + if (typeof DOC_VERSIONS !== "undefined") { + var existing_versions = version_selector_select.children("option"); + var existing_versions_texts = existing_versions.map(function (i, x) { + return x.text; + }); + DOC_VERSIONS.forEach(function (each) { + var version_url = documenterBaseURL + "/../" + each + "/"; + var existing_id = $.inArray(each, existing_versions_texts); + // if not already in the version selector, add it as a new option, + // otherwise update the old option with the URL and enable it + if (existing_id == -1) { + var option = $( + "" + ); + version_selector_select.append(option); + } else { + var option = existing_versions[existing_id]; + option.value = version_url; + option.disabled = false; + } + }); + } + + // only show the version selector if the selector has been populated + if (version_selector_select.children("option").length > 0) { + version_selector.toggleClass("visible"); + } +}); + +}) diff --git a/previews/PR2274/assets/latency.png b/previews/PR2274/assets/latency.png new file mode 100644 index 0000000000000000000000000000000000000000..9b51f3b25fc63c559400a3fe628a33348b6e30ff GIT binary patch literal 25175 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,html.theme--documenter-dark .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus,html.theme--documenter-dark .pagination-ellipsis:focus,html.theme--documenter-dark .file-cta:focus,html.theme--documenter-dark .file-name:focus,html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .button:focus,html.theme--documenter-dark .is-focused.pagination-previous,html.theme--documenter-dark .is-focused.pagination-next,html.theme--documenter-dark .is-focused.pagination-link,html.theme--documenter-dark .is-focused.pagination-ellipsis,html.theme--documenter-dark .is-focused.file-cta,html.theme--documenter-dark .is-focused.file-name,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-focused.button,html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active,html.theme--documenter-dark .pagination-ellipsis:active,html.theme--documenter-dark .file-cta:active,html.theme--documenter-dark .file-name:active,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .button:active,html.theme--documenter-dark .is-active.pagination-previous,html.theme--documenter-dark .is-active.pagination-next,html.theme--documenter-dark .is-active.pagination-link,html.theme--documenter-dark .is-active.pagination-ellipsis,html.theme--documenter-dark .is-active.file-cta,html.theme--documenter-dark .is-active.file-name,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .is-active.button{outline:none}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-ellipsis[disabled],html.theme--documenter-dark .file-cta[disabled],html.theme--documenter-dark .file-name[disabled],html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--documenter-dark .pagination-next,html.theme--documenter-dark fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--documenter-dark .pagination-link,html.theme--documenter-dark fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--documenter-dark .file-cta,html.theme--documenter-dark fieldset[disabled] .file-cta,fieldset[disabled] html.theme--documenter-dark .file-name,html.theme--documenter-dark fieldset[disabled] .file-name,fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark fieldset[disabled] .select select,html.theme--documenter-dark .select fieldset[disabled] select,html.theme--documenter-dark fieldset[disabled] .textarea,html.theme--documenter-dark fieldset[disabled] .input,html.theme--documenter-dark fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--documenter-dark .button,html.theme--documenter-dark fieldset[disabled] .button{cursor:not-allowed}html.theme--documenter-dark .tabs,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .breadcrumb,html.theme--documenter-dark .file,html.theme--documenter-dark .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after,html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--documenter-dark .admonition:not(:last-child),html.theme--documenter-dark .tabs:not(:last-child),html.theme--documenter-dark .pagination:not(:last-child),html.theme--documenter-dark .message:not(:last-child),html.theme--documenter-dark .level:not(:last-child),html.theme--documenter-dark .breadcrumb:not(:last-child),html.theme--documenter-dark .block:not(:last-child),html.theme--documenter-dark .title:not(:last-child),html.theme--documenter-dark .subtitle:not(:last-child),html.theme--documenter-dark .table-container:not(:last-child),html.theme--documenter-dark .table:not(:last-child),html.theme--documenter-dark .progress:not(:last-child),html.theme--documenter-dark .notification:not(:last-child),html.theme--documenter-dark .content:not(:last-child),html.theme--documenter-dark .box:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .modal-close,html.theme--documenter-dark .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before,html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before{height:2px;width:50%}html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{height:50%;width:2px}html.theme--documenter-dark .modal-close:hover,html.theme--documenter-dark .delete:hover,html.theme--documenter-dark .modal-close:focus,html.theme--documenter-dark .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--documenter-dark .modal-close:active,html.theme--documenter-dark .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--documenter-dark .is-small.modal-close,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--documenter-dark .is-small.delete,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--documenter-dark .is-medium.modal-close,html.theme--documenter-dark .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--documenter-dark .is-large.modal-close,html.theme--documenter-dark .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--documenter-dark .control.is-loading::after,html.theme--documenter-dark .select.is-loading::after,html.theme--documenter-dark .loader,html.theme--documenter-dark .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdee0;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--documenter-dark .hero-video,html.theme--documenter-dark .modal-background,html.theme--documenter-dark .modal,html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--documenter-dark .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#ecf0f1 !important}a.has-text-light:hover,a.has-text-light:focus{color:#cfd9db !important}.has-background-light{background-color:#ecf0f1 !important}.has-text-dark{color:#282f2f !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#111414 !important}.has-background-dark{background-color:#282f2f !important}.has-text-primary{color:#375a7f !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#28415b !important}.has-background-primary{background-color:#375a7f !important}.has-text-primary-light{color:#f1f5f9 !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#cddbe9 !important}.has-background-primary-light{background-color:#f1f5f9 !important}.has-text-primary-dark{color:#4d7eb2 !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#7198c1 !important}.has-background-primary-dark{background-color:#4d7eb2 !important}.has-text-link{color:#1abc9c !important}a.has-text-link:hover,a.has-text-link:focus{color:#148f77 !important}.has-background-link{background-color:#1abc9c !important}.has-text-link-light{color:#edfdf9 !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c0f6ec !important}.has-background-link-light{background-color:#edfdf9 !important}.has-text-link-dark{color:#15987e !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#1bc5a4 !important}.has-background-link-dark{background-color:#15987e !important}.has-text-info{color:#024c7d !important}a.has-text-info:hover,a.has-text-info:focus{color:#012d4b !important}.has-background-info{background-color:#024c7d !important}.has-text-info-light{color:#ebf7ff !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#b9e2fe !important}.has-background-info-light{background-color:#ebf7ff !important}.has-text-info-dark{color:#0e9dfb !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#40b1fc !important}.has-background-info-dark{background-color:#0e9dfb !important}.has-text-success{color:#008438 !important}a.has-text-success:hover,a.has-text-success:focus{color:#005122 !important}.has-background-success{background-color:#008438 !important}.has-text-success-light{color:#ebfff3 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#b8ffd6 !important}.has-background-success-light{background-color:#ebfff3 !important}.has-text-success-dark{color:#00eb64 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#1fff7e !important}.has-background-success-dark{background-color:#00eb64 !important}.has-text-warning{color:#ad8100 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#7a5b00 !important}.has-background-warning{background-color:#ad8100 !important}.has-text-warning-light{color:#fffaeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#ffedb8 !important}.has-background-warning-light{background-color:#fffaeb !important}.has-text-warning-dark{color:#d19c00 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#ffbf05 !important}.has-background-warning-dark{background-color:#d19c00 !important}.has-text-danger{color:#9e1b0d !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#6f1309 !important}.has-background-danger{background-color:#9e1b0d !important}.has-text-danger-light{color:#fdeeec !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#fac3bd !important}.has-background-danger-light{background-color:#fdeeec !important}.has-text-danger-dark{color:#ec311d !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#f05c4c !important}.has-background-danger-dark{background-color:#ec311d !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#282f2f !important}.has-background-grey-darker{background-color:#282f2f !important}.has-text-grey-dark{color:#343c3d !important}.has-background-grey-dark{background-color:#343c3d !important}.has-text-grey{color:#5e6d6f !important}.has-background-grey{background-color:#5e6d6f !important}.has-text-grey-light{color:#8c9b9d !important}.has-background-grey-light{background-color:#8c9b9d !important}.has-text-grey-lighter{color:#dbdee0 !important}.has-background-grey-lighter{background-color:#dbdee0 !important}.has-text-white-ter{color:#ecf0f1 !important}.has-background-white-ter{background-color:#ecf0f1 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--documenter-dark{/*! + Theme: a11y-dark + Author: @ericwbailey + Maintainer: @ericwbailey + + Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css +*/}html.theme--documenter-dark html{background-color:#1f2424;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark article,html.theme--documenter-dark aside,html.theme--documenter-dark figure,html.theme--documenter-dark footer,html.theme--documenter-dark header,html.theme--documenter-dark hgroup,html.theme--documenter-dark section{display:block}html.theme--documenter-dark body,html.theme--documenter-dark button,html.theme--documenter-dark input,html.theme--documenter-dark optgroup,html.theme--documenter-dark select,html.theme--documenter-dark textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--documenter-dark code,html.theme--documenter-dark pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark body{color:#fff;font-size:1em;font-weight:400;line-height:1.5}html.theme--documenter-dark a{color:#1abc9c;cursor:pointer;text-decoration:none}html.theme--documenter-dark a strong{color:currentColor}html.theme--documenter-dark a:hover{color:#1dd2af}html.theme--documenter-dark code{background-color:rgba(255,255,255,0.05);color:#ececec;font-size:.875em;font-weight:normal;padding:.1em}html.theme--documenter-dark hr{background-color:#282f2f;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--documenter-dark img{height:auto;max-width:100%}html.theme--documenter-dark input[type="checkbox"],html.theme--documenter-dark input[type="radio"]{vertical-align:baseline}html.theme--documenter-dark small{font-size:.875em}html.theme--documenter-dark span{font-style:inherit;font-weight:inherit}html.theme--documenter-dark strong{color:#f2f2f2;font-weight:700}html.theme--documenter-dark fieldset{border:none}html.theme--documenter-dark pre{-webkit-overflow-scrolling:touch;background-color:#282f2f;color:#fff;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--documenter-dark pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--documenter-dark table td,html.theme--documenter-dark table th{vertical-align:top}html.theme--documenter-dark table td:not([align]),html.theme--documenter-dark table th:not([align]){text-align:inherit}html.theme--documenter-dark table th{color:#f2f2f2}html.theme--documenter-dark .box{background-color:#343c3d;border-radius:8px;box-shadow:none;color:#fff;display:block;padding:1.25rem}html.theme--documenter-dark a.box:hover,html.theme--documenter-dark a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #1abc9c}html.theme--documenter-dark a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #1abc9c}html.theme--documenter-dark .button{background-color:#282f2f;border-color:#4c5759;border-width:1px;color:#375a7f;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--documenter-dark .button strong{color:inherit}html.theme--documenter-dark .button .icon,html.theme--documenter-dark .button .icon.is-small,html.theme--documenter-dark .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--documenter-dark #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--documenter-dark .button .icon.is-medium,html.theme--documenter-dark .button .icon.is-large{height:1.5em;width:1.5em}html.theme--documenter-dark .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--documenter-dark .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button:hover,html.theme--documenter-dark .button.is-hovered{border-color:#8c9b9d;color:#f2f2f2}html.theme--documenter-dark .button:focus,html.theme--documenter-dark .button.is-focused{border-color:#8c9b9d;color:#17a689}html.theme--documenter-dark .button:focus:not(:active),html.theme--documenter-dark .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button:active,html.theme--documenter-dark .button.is-active{border-color:#343c3d;color:#f2f2f2}html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;color:#fff;text-decoration:underline}html.theme--documenter-dark .button.is-text:hover,html.theme--documenter-dark .button.is-text.is-hovered,html.theme--documenter-dark .button.is-text:focus,html.theme--documenter-dark .button.is-text.is-focused{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .button.is-text:active,html.theme--documenter-dark .button.is-text.is-active{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .button.is-text[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#1abc9c;text-decoration:none}html.theme--documenter-dark .button.is-ghost:hover,html.theme--documenter-dark .button.is-ghost.is-hovered{color:#1abc9c;text-decoration:underline}html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:hover,html.theme--documenter-dark .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus,html.theme--documenter-dark .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus:not(:active),html.theme--documenter-dark .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--documenter-dark .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-white.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:hover,html.theme--documenter-dark .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus,html.theme--documenter-dark .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus:not(:active),html.theme--documenter-dark .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:hover,html.theme--documenter-dark .button.is-light.is-hovered{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus,html.theme--documenter-dark .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus:not(:active),html.theme--documenter-dark .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light.is-active{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:#ecf0f1;box-shadow:none}html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-outlined.is-focused{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-dark,html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover,html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus:not(:active),html.theme--documenter-dark .content kbd.button:focus:not(:active),html.theme--documenter-dark .button.is-dark.is-focused:not(:active),html.theme--documenter-dark .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark[disabled],html.theme--documenter-dark .content kbd.button[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark,fieldset[disabled] html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:#282f2f;box-shadow:none}html.theme--documenter-dark .button.is-dark.is-inverted,html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted:hover,html.theme--documenter-dark .content kbd.button.is-inverted:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-dark.is-inverted[disabled],html.theme--documenter-dark .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-loading::after,html.theme--documenter-dark .content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined,html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-outlined.is-focused{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus:not(:active),html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--documenter-dark .button.is-primary.is-focused:not(:active),html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary[disabled],html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;box-shadow:none}html.theme--documenter-dark .button.is-primary.is-inverted,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--documenter-dark .button.is-primary.is-inverted[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:hover,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-light.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e8eef5;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:active,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-light.is-active,html.theme--documenter-dark .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#dfe8f1;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:hover,html.theme--documenter-dark .button.is-link.is-hovered{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus,html.theme--documenter-dark .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus:not(:active),html.theme--documenter-dark .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link.is-active{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:#1abc9c;box-shadow:none}html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-outlined.is-focused{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:hover,html.theme--documenter-dark .button.is-link.is-light.is-hovered{background-color:#e2fbf6;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:active,html.theme--documenter-dark .button.is-link.is-light.is-active{background-color:#d7f9f3;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:hover,html.theme--documenter-dark .button.is-info.is-hovered{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus,html.theme--documenter-dark .button.is-info.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus:not(:active),html.theme--documenter-dark .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info.is-active{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:#024c7d;box-shadow:none}html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;color:#024c7d}html.theme--documenter-dark .button.is-info.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-outlined.is-focused{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-info.is-light{background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .button.is-info.is-light:hover,html.theme--documenter-dark .button.is-info.is-light.is-hovered{background-color:#def2fe;border-color:transparent;color:#0e9dfb}html.theme--documenter-dark .button.is-info.is-light:active,html.theme--documenter-dark .button.is-info.is-light.is-active{background-color:#d2edfe;border-color:transparent;color:#0e9dfb}html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:hover,html.theme--documenter-dark .button.is-success.is-hovered{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus,html.theme--documenter-dark .button.is-success.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus:not(:active),html.theme--documenter-dark .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success.is-active{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:#008438;box-shadow:none}html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;color:#008438}html.theme--documenter-dark .button.is-success.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-outlined.is-focused{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-success.is-light{background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .button.is-success.is-light:hover,html.theme--documenter-dark .button.is-success.is-light.is-hovered{background-color:#deffec;border-color:transparent;color:#00eb64}html.theme--documenter-dark .button.is-success.is-light:active,html.theme--documenter-dark .button.is-success.is-light.is-active{background-color:#d1ffe5;border-color:transparent;color:#00eb64}html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:hover,html.theme--documenter-dark .button.is-warning.is-hovered{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus,html.theme--documenter-dark .button.is-warning.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus:not(:active),html.theme--documenter-dark .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning.is-active{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:#ad8100;box-shadow:none}html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-outlined.is-focused{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-focused{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-warning.is-light{background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .button.is-warning.is-light:hover,html.theme--documenter-dark .button.is-warning.is-light.is-hovered{background-color:#fff7de;border-color:transparent;color:#d19c00}html.theme--documenter-dark .button.is-warning.is-light:active,html.theme--documenter-dark .button.is-warning.is-light.is-active{background-color:#fff3d1;border-color:transparent;color:#d19c00}html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:hover,html.theme--documenter-dark .button.is-danger.is-hovered{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus,html.theme--documenter-dark .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus:not(:active),html.theme--documenter-dark .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger.is-active{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;box-shadow:none}html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-outlined.is-focused{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-danger.is-light{background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .button.is-danger.is-light:hover,html.theme--documenter-dark .button.is-danger.is-light.is-hovered{background-color:#fce3e0;border-color:transparent;color:#ec311d}html.theme--documenter-dark .button.is-danger.is-light:active,html.theme--documenter-dark .button.is-danger.is-light.is-active{background-color:#fcd8d5;border-color:transparent;color:#ec311d}html.theme--documenter-dark .button.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--documenter-dark .button.is-small:not(.is-rounded),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--documenter-dark .button.is-normal{font-size:1rem}html.theme--documenter-dark .button.is-medium{font-size:1.25rem}html.theme--documenter-dark .button.is-large{font-size:1.5rem}html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .button{background-color:#8c9b9d;border-color:#5e6d6f;box-shadow:none;opacity:.5}html.theme--documenter-dark .button.is-fullwidth{display:flex;width:100%}html.theme--documenter-dark .button.is-loading{color:transparent !important;pointer-events:none}html.theme--documenter-dark .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--documenter-dark .button.is-static{background-color:#282f2f;border-color:#5e6d6f;color:#dbdee0;box-shadow:none;pointer-events:none}html.theme--documenter-dark .button.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--documenter-dark .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .buttons .button{margin-bottom:0.5rem}html.theme--documenter-dark .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--documenter-dark .buttons:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .buttons:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--documenter-dark .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--documenter-dark .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--documenter-dark .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--documenter-dark .buttons.has-addons .button:last-child{margin-right:0}html.theme--documenter-dark .buttons.has-addons .button:hover,html.theme--documenter-dark .buttons.has-addons .button.is-hovered{z-index:2}html.theme--documenter-dark .buttons.has-addons .button:focus,html.theme--documenter-dark .buttons.has-addons .button.is-focused,html.theme--documenter-dark .buttons.has-addons .button:active,html.theme--documenter-dark .buttons.has-addons .button.is-active,html.theme--documenter-dark .buttons.has-addons .button.is-selected{z-index:3}html.theme--documenter-dark .buttons.has-addons .button:focus:hover,html.theme--documenter-dark .buttons.has-addons .button.is-focused:hover,html.theme--documenter-dark .buttons.has-addons .button:active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--documenter-dark .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .buttons.is-centered{justify-content:center}html.theme--documenter-dark .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--documenter-dark .buttons.is-right{justify-content:flex-end}html.theme--documenter-dark .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:1rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1.25rem}}html.theme--documenter-dark .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--documenter-dark .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--documenter-dark .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--documenter-dark .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--documenter-dark .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--documenter-dark .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--documenter-dark .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--documenter-dark .content li+li{margin-top:0.25em}html.theme--documenter-dark .content p:not(:last-child),html.theme--documenter-dark .content dl:not(:last-child),html.theme--documenter-dark .content ol:not(:last-child),html.theme--documenter-dark .content ul:not(:last-child),html.theme--documenter-dark .content blockquote:not(:last-child),html.theme--documenter-dark .content pre:not(:last-child),html.theme--documenter-dark .content table:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .content h1,html.theme--documenter-dark .content h2,html.theme--documenter-dark .content h3,html.theme--documenter-dark .content h4,html.theme--documenter-dark .content h5,html.theme--documenter-dark .content h6{color:#f2f2f2;font-weight:600;line-height:1.125}html.theme--documenter-dark .content h1{font-size:2em;margin-bottom:0.5em}html.theme--documenter-dark .content h1:not(:first-child){margin-top:1em}html.theme--documenter-dark .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--documenter-dark .content h2:not(:first-child){margin-top:1.1428em}html.theme--documenter-dark .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--documenter-dark .content h3:not(:first-child){margin-top:1.3333em}html.theme--documenter-dark .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--documenter-dark .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--documenter-dark .content h6{font-size:1em;margin-bottom:1em}html.theme--documenter-dark .content blockquote{background-color:#282f2f;border-left:5px solid #5e6d6f;padding:1.25em 1.5em}html.theme--documenter-dark .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ol:not([type]){list-style-type:decimal}html.theme--documenter-dark .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--documenter-dark .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--documenter-dark .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--documenter-dark .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--documenter-dark .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--documenter-dark .content ul ul ul{list-style-type:square}html.theme--documenter-dark .content dd{margin-left:2em}html.theme--documenter-dark .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--documenter-dark .content figure:not(:first-child){margin-top:2em}html.theme--documenter-dark .content figure:not(:last-child){margin-bottom:2em}html.theme--documenter-dark .content figure img{display:inline-block}html.theme--documenter-dark .content figure figcaption{font-style:italic}html.theme--documenter-dark .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--documenter-dark .content sup,html.theme--documenter-dark .content sub{font-size:75%}html.theme--documenter-dark .content table{width:100%}html.theme--documenter-dark .content table td,html.theme--documenter-dark .content table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .content table th{color:#f2f2f2}html.theme--documenter-dark .content table th:not([align]){text-align:inherit}html.theme--documenter-dark .content table thead td,html.theme--documenter-dark .content table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .content table tfoot td,html.theme--documenter-dark .content table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .content table tbody tr:last-child td,html.theme--documenter-dark .content table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .content .tabs li+li{margin-top:0}html.theme--documenter-dark .content.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--documenter-dark .content.is-normal{font-size:1rem}html.theme--documenter-dark .content.is-medium{font-size:1.25rem}html.theme--documenter-dark .content.is-large{font-size:1.5rem}html.theme--documenter-dark .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--documenter-dark .icon.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--documenter-dark .icon.is-medium{height:2rem;width:2rem}html.theme--documenter-dark .icon.is-large{height:3rem;width:3rem}html.theme--documenter-dark .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--documenter-dark .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--documenter-dark .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--documenter-dark div.icon-text{display:flex}html.theme--documenter-dark .image,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--documenter-dark .image img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--documenter-dark .image img.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--documenter-dark .image.is-fullwidth,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--documenter-dark .image.is-square,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--documenter-dark .image.is-1by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--documenter-dark .image.is-5by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--documenter-dark .image.is-4by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--documenter-dark .image.is-3by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--documenter-dark .image.is-5by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--documenter-dark .image.is-16by9,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--documenter-dark .image.is-2by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--documenter-dark .image.is-3by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--documenter-dark .image.is-4by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--documenter-dark .image.is-3by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--documenter-dark .image.is-2by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--documenter-dark .image.is-3by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--documenter-dark .image.is-9by16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--documenter-dark .image.is-1by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--documenter-dark .image.is-1by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--documenter-dark .image.is-16x16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--documenter-dark .image.is-24x24,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--documenter-dark .image.is-32x32,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--documenter-dark .image.is-48x48,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--documenter-dark .image.is-64x64,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--documenter-dark .image.is-96x96,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--documenter-dark .image.is-128x128,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--documenter-dark .notification{background-color:#282f2f;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--documenter-dark .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .notification strong{color:currentColor}html.theme--documenter-dark .notification code,html.theme--documenter-dark .notification pre{background:#fff}html.theme--documenter-dark .notification pre code{background:transparent}html.theme--documenter-dark .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--documenter-dark .notification .title,html.theme--documenter-dark .notification .subtitle,html.theme--documenter-dark .notification .content{color:currentColor}html.theme--documenter-dark .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .notification.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .notification.is-dark,html.theme--documenter-dark .content kbd.notification{background-color:#282f2f;color:#fff}html.theme--documenter-dark .notification.is-primary,html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .notification.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .notification.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .notification.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .notification.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .notification.is-info.is-light{background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .notification.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .notification.is-success.is-light{background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .notification.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .notification.is-warning.is-light{background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .notification.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .notification.is-danger.is-light{background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--documenter-dark .progress::-webkit-progress-bar{background-color:#343c3d}html.theme--documenter-dark .progress::-webkit-progress-value{background-color:#dbdee0}html.theme--documenter-dark .progress::-moz-progress-bar{background-color:#dbdee0}html.theme--documenter-dark .progress::-ms-fill{background-color:#dbdee0;border:none}html.theme--documenter-dark .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--documenter-dark .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--documenter-dark .progress.is-white::-ms-fill{background-color:#fff}html.theme--documenter-dark .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-light::-webkit-progress-value{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-moz-progress-bar{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-ms-fill{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light:indeterminate{background-image:linear-gradient(to right, #ecf0f1 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-dark::-webkit-progress-value,html.theme--documenter-dark .content kbd.progress::-webkit-progress-value{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-moz-progress-bar,html.theme--documenter-dark .content kbd.progress::-moz-progress-bar{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-ms-fill,html.theme--documenter-dark .content kbd.progress::-ms-fill{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark:indeterminate,html.theme--documenter-dark .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #282f2f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-primary::-webkit-progress-value,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-moz-progress-bar,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-ms-fill,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary:indeterminate,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #375a7f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-link::-webkit-progress-value{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-moz-progress-bar{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-ms-fill{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link:indeterminate{background-image:linear-gradient(to right, #1abc9c 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-info::-webkit-progress-value{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-moz-progress-bar{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-ms-fill{background-color:#024c7d}html.theme--documenter-dark .progress.is-info:indeterminate{background-image:linear-gradient(to right, #024c7d 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-success::-webkit-progress-value{background-color:#008438}html.theme--documenter-dark .progress.is-success::-moz-progress-bar{background-color:#008438}html.theme--documenter-dark .progress.is-success::-ms-fill{background-color:#008438}html.theme--documenter-dark .progress.is-success:indeterminate{background-image:linear-gradient(to right, #008438 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-warning::-webkit-progress-value{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-moz-progress-bar{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-ms-fill{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ad8100 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-danger::-webkit-progress-value{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-moz-progress-bar{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-ms-fill{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #9e1b0d 30%, #343c3d 30%)}html.theme--documenter-dark .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#343c3d;background-image:linear-gradient(to right, #fff 30%, #343c3d 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--documenter-dark .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-ms-fill{animation-name:none}html.theme--documenter-dark .progress.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--documenter-dark .progress.is-medium{height:1.25rem}html.theme--documenter-dark .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--documenter-dark .table{background-color:#343c3d;color:#fff}html.theme--documenter-dark .table td,html.theme--documenter-dark .table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .table td.is-white,html.theme--documenter-dark .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .table td.is-black,html.theme--documenter-dark .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .table td.is-light,html.theme--documenter-dark .table th.is-light{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .table td.is-dark,html.theme--documenter-dark .table th.is-dark{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .table td.is-primary,html.theme--documenter-dark .table th.is-primary{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-link,html.theme--documenter-dark .table th.is-link{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .table td.is-info,html.theme--documenter-dark .table th.is-info{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .table td.is-success,html.theme--documenter-dark .table th.is-success{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .table td.is-warning,html.theme--documenter-dark .table th.is-warning{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .table td.is-danger,html.theme--documenter-dark .table th.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .table td.is-narrow,html.theme--documenter-dark .table th.is-narrow{white-space:nowrap;width:1%}html.theme--documenter-dark .table td.is-selected,html.theme--documenter-dark .table th.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-selected a,html.theme--documenter-dark .table td.is-selected strong,html.theme--documenter-dark .table th.is-selected a,html.theme--documenter-dark .table th.is-selected strong{color:currentColor}html.theme--documenter-dark .table td.is-vcentered,html.theme--documenter-dark .table th.is-vcentered{vertical-align:middle}html.theme--documenter-dark .table th{color:#f2f2f2}html.theme--documenter-dark .table th:not([align]){text-align:left}html.theme--documenter-dark .table tr.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table tr.is-selected a,html.theme--documenter-dark .table tr.is-selected strong{color:currentColor}html.theme--documenter-dark .table tr.is-selected td,html.theme--documenter-dark .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--documenter-dark .table thead{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table thead td,html.theme--documenter-dark .table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .table tfoot{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tfoot td,html.theme--documenter-dark .table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .table tbody{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tbody tr:last-child td,html.theme--documenter-dark .table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .table.is-bordered td,html.theme--documenter-dark .table.is-bordered th{border-width:1px}html.theme--documenter-dark .table.is-bordered tr:last-child td,html.theme--documenter-dark .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--documenter-dark .table.is-fullwidth{width:100%}html.theme--documenter-dark .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#2d3435}html.theme--documenter-dark .table.is-narrow td,html.theme--documenter-dark .table.is-narrow th{padding:0.25em 0.5em}html.theme--documenter-dark .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#282f2f}html.theme--documenter-dark .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--documenter-dark .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .tags .tag,html.theme--documenter-dark .tags .content kbd,html.theme--documenter-dark .content .tags kbd,html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--documenter-dark .tags .tag:not(:last-child),html.theme--documenter-dark .tags .content kbd:not(:last-child),html.theme--documenter-dark .content .tags kbd:not(:last-child),html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--documenter-dark .tags:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .tags:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--documenter-dark .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--documenter-dark .tags.is-centered{justify-content:center}html.theme--documenter-dark .tags.is-centered .tag,html.theme--documenter-dark .tags.is-centered .content kbd,html.theme--documenter-dark .content .tags.is-centered kbd,html.theme--documenter-dark .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--documenter-dark .tags.is-right{justify-content:flex-end}html.theme--documenter-dark .tags.is-right .tag:not(:first-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:first-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--documenter-dark .tags.is-right .tag:not(:last-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:last-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--documenter-dark .tags.has-addons .tag,html.theme--documenter-dark .tags.has-addons .content kbd,html.theme--documenter-dark .content .tags.has-addons kbd,html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--documenter-dark .tags.has-addons .tag:not(:first-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:first-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--documenter-dark .tags.has-addons .tag:not(:last-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:last-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--documenter-dark .tag:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#282f2f;border-radius:.4em;color:#fff;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--documenter-dark .tag:not(body) .delete,html.theme--documenter-dark .content kbd:not(body) .delete,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--documenter-dark .tag.is-white:not(body),html.theme--documenter-dark .content kbd.is-white:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .tag.is-black:not(body),html.theme--documenter-dark .content kbd.is-black:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .tag.is-light:not(body),html.theme--documenter-dark .content kbd.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .tag.is-dark:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--documenter-dark .content .docstring>section>kbd:not(body){background-color:#282f2f;color:#fff}html.theme--documenter-dark .tag.is-primary:not(body),html.theme--documenter-dark .content kbd.is-primary:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){background-color:#375a7f;color:#fff}html.theme--documenter-dark .tag.is-primary.is-light:not(body),html.theme--documenter-dark .content kbd.is-primary.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .tag.is-link:not(body),html.theme--documenter-dark .content kbd.is-link:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#1abc9c;color:#fff}html.theme--documenter-dark .tag.is-link.is-light:not(body),html.theme--documenter-dark .content kbd.is-link.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .tag.is-info:not(body),html.theme--documenter-dark .content kbd.is-info:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#024c7d;color:#fff}html.theme--documenter-dark .tag.is-info.is-light:not(body),html.theme--documenter-dark .content kbd.is-info.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .tag.is-success:not(body),html.theme--documenter-dark .content kbd.is-success:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#008438;color:#fff}html.theme--documenter-dark .tag.is-success.is-light:not(body),html.theme--documenter-dark .content kbd.is-success.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .tag.is-warning:not(body),html.theme--documenter-dark .content kbd.is-warning:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ad8100;color:#fff}html.theme--documenter-dark .tag.is-warning.is-light:not(body),html.theme--documenter-dark .content kbd.is-warning.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .tag.is-danger:not(body),html.theme--documenter-dark .content kbd.is-danger:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .tag.is-danger.is-light:not(body),html.theme--documenter-dark .content kbd.is-danger.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .tag.is-normal:not(body),html.theme--documenter-dark .content kbd.is-normal:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--documenter-dark .tag.is-medium:not(body),html.theme--documenter-dark .content kbd.is-medium:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--documenter-dark .tag.is-large:not(body),html.theme--documenter-dark .content kbd.is-large:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--documenter-dark .tag:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--documenter-dark .tag:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--documenter-dark .tag:not(body) .icon:first-child:last-child,html.theme--documenter-dark .content kbd:not(body) .icon:first-child:last-child,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--documenter-dark .tag.is-delete:not(body),html.theme--documenter-dark .content kbd.is-delete:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--documenter-dark .tag.is-delete:not(body):hover,html.theme--documenter-dark .content kbd.is-delete:not(body):hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--documenter-dark .tag.is-delete:not(body):focus,html.theme--documenter-dark .content kbd.is-delete:not(body):focus,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#1d2122}html.theme--documenter-dark .tag.is-delete:not(body):active,html.theme--documenter-dark .content kbd.is-delete:not(body):active,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#111414}html.theme--documenter-dark .tag.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--documenter-dark .content kbd.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--documenter-dark a.tag:hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--documenter-dark .title,html.theme--documenter-dark .subtitle{word-break:break-word}html.theme--documenter-dark .title em,html.theme--documenter-dark .title span,html.theme--documenter-dark .subtitle em,html.theme--documenter-dark .subtitle span{font-weight:inherit}html.theme--documenter-dark .title sub,html.theme--documenter-dark .subtitle sub{font-size:.75em}html.theme--documenter-dark .title sup,html.theme--documenter-dark .subtitle sup{font-size:.75em}html.theme--documenter-dark .title .tag,html.theme--documenter-dark .title .content kbd,html.theme--documenter-dark .content .title kbd,html.theme--documenter-dark .title .docstring>section>a.docs-sourcelink,html.theme--documenter-dark .subtitle .tag,html.theme--documenter-dark .subtitle .content kbd,html.theme--documenter-dark .content .subtitle kbd,html.theme--documenter-dark .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--documenter-dark .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--documenter-dark .title strong{color:inherit;font-weight:inherit}html.theme--documenter-dark .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--documenter-dark .title.is-1{font-size:3rem}html.theme--documenter-dark .title.is-2{font-size:2.5rem}html.theme--documenter-dark .title.is-3{font-size:2rem}html.theme--documenter-dark .title.is-4{font-size:1.5rem}html.theme--documenter-dark .title.is-5{font-size:1.25rem}html.theme--documenter-dark .title.is-6{font-size:1rem}html.theme--documenter-dark .title.is-7{font-size:.75rem}html.theme--documenter-dark .subtitle{color:#8c9b9d;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--documenter-dark .subtitle strong{color:#8c9b9d;font-weight:600}html.theme--documenter-dark .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--documenter-dark .subtitle.is-1{font-size:3rem}html.theme--documenter-dark .subtitle.is-2{font-size:2.5rem}html.theme--documenter-dark .subtitle.is-3{font-size:2rem}html.theme--documenter-dark .subtitle.is-4{font-size:1.5rem}html.theme--documenter-dark .subtitle.is-5{font-size:1.25rem}html.theme--documenter-dark .subtitle.is-6{font-size:1rem}html.theme--documenter-dark .subtitle.is-7{font-size:.75rem}html.theme--documenter-dark .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--documenter-dark .number{align-items:center;background-color:#282f2f;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#1f2424;border-color:#5e6d6f;border-radius:.4em;color:#dbdee0}html.theme--documenter-dark .select select::-moz-placeholder,html.theme--documenter-dark .textarea::-moz-placeholder,html.theme--documenter-dark .input::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select::-webkit-input-placeholder,html.theme--documenter-dark .textarea::-webkit-input-placeholder,html.theme--documenter-dark .input::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:-moz-placeholder,html.theme--documenter-dark .textarea:-moz-placeholder,html.theme--documenter-dark .input:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select:-ms-input-placeholder,html.theme--documenter-dark .textarea:-ms-input-placeholder,html.theme--documenter-dark .input:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:hover,html.theme--documenter-dark .textarea:hover,html.theme--documenter-dark .input:hover,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:hover,html.theme--documenter-dark .select select.is-hovered,html.theme--documenter-dark .is-hovered.textarea,html.theme--documenter-dark .is-hovered.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#8c9b9d}html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#1abc9c;box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#8c9b9d;border-color:#282f2f;box-shadow:none;color:#fff}html.theme--documenter-dark .select select[disabled]::-moz-placeholder,html.theme--documenter-dark .textarea[disabled]::-moz-placeholder,html.theme--documenter-dark .input[disabled]::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .textarea[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .input[disabled]::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-moz-placeholder,html.theme--documenter-dark .textarea[disabled]:-moz-placeholder,html.theme--documenter-dark .input[disabled]:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-ms-input-placeholder,html.theme--documenter-dark .textarea[disabled]:-ms-input-placeholder,html.theme--documenter-dark .input[disabled]:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--documenter-dark .textarea[readonly],html.theme--documenter-dark .input[readonly],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--documenter-dark .is-white.textarea,html.theme--documenter-dark .is-white.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--documenter-dark .is-white.textarea:focus,html.theme--documenter-dark .is-white.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--documenter-dark .is-white.is-focused.textarea,html.theme--documenter-dark .is-white.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-white.textarea:active,html.theme--documenter-dark .is-white.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--documenter-dark .is-white.is-active.textarea,html.theme--documenter-dark .is-white.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .is-black.textarea,html.theme--documenter-dark .is-black.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--documenter-dark .is-black.textarea:focus,html.theme--documenter-dark .is-black.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--documenter-dark .is-black.is-focused.textarea,html.theme--documenter-dark .is-black.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-black.textarea:active,html.theme--documenter-dark .is-black.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--documenter-dark .is-black.is-active.textarea,html.theme--documenter-dark .is-black.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .is-light.textarea,html.theme--documenter-dark .is-light.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#ecf0f1}html.theme--documenter-dark .is-light.textarea:focus,html.theme--documenter-dark .is-light.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--documenter-dark .is-light.is-focused.textarea,html.theme--documenter-dark .is-light.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-light.textarea:active,html.theme--documenter-dark .is-light.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--documenter-dark .is-light.is-active.textarea,html.theme--documenter-dark .is-light.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .is-dark.textarea,html.theme--documenter-dark .content kbd.textarea,html.theme--documenter-dark .is-dark.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--documenter-dark .content kbd.input{border-color:#282f2f}html.theme--documenter-dark .is-dark.textarea:focus,html.theme--documenter-dark .content kbd.textarea:focus,html.theme--documenter-dark .is-dark.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--documenter-dark .content kbd.input:focus,html.theme--documenter-dark .is-dark.is-focused.textarea,html.theme--documenter-dark .content kbd.is-focused.textarea,html.theme--documenter-dark .is-dark.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .content kbd.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--documenter-dark .is-dark.textarea:active,html.theme--documenter-dark .content kbd.textarea:active,html.theme--documenter-dark .is-dark.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--documenter-dark .content kbd.input:active,html.theme--documenter-dark .is-dark.is-active.textarea,html.theme--documenter-dark .content kbd.is-active.textarea,html.theme--documenter-dark .is-dark.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .content kbd.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .is-primary.textarea,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink{border-color:#375a7f}html.theme--documenter-dark .is-primary.textarea:focus,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.is-focused.textarea,html.theme--documenter-dark .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--documenter-dark .is-primary.textarea:active,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:active,html.theme--documenter-dark .is-primary.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:active,html.theme--documenter-dark .is-primary.is-active.textarea,html.theme--documenter-dark .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .is-link.textarea,html.theme--documenter-dark .is-link.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#1abc9c}html.theme--documenter-dark .is-link.textarea:focus,html.theme--documenter-dark .is-link.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--documenter-dark .is-link.is-focused.textarea,html.theme--documenter-dark .is-link.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-link.textarea:active,html.theme--documenter-dark .is-link.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--documenter-dark .is-link.is-active.textarea,html.theme--documenter-dark .is-link.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .is-info.textarea,html.theme--documenter-dark .is-info.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#024c7d}html.theme--documenter-dark .is-info.textarea:focus,html.theme--documenter-dark .is-info.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--documenter-dark .is-info.is-focused.textarea,html.theme--documenter-dark .is-info.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-info.textarea:active,html.theme--documenter-dark .is-info.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--documenter-dark .is-info.is-active.textarea,html.theme--documenter-dark .is-info.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .is-success.textarea,html.theme--documenter-dark .is-success.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#008438}html.theme--documenter-dark .is-success.textarea:focus,html.theme--documenter-dark .is-success.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--documenter-dark .is-success.is-focused.textarea,html.theme--documenter-dark .is-success.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-success.textarea:active,html.theme--documenter-dark .is-success.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--documenter-dark .is-success.is-active.textarea,html.theme--documenter-dark .is-success.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .is-warning.textarea,html.theme--documenter-dark .is-warning.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ad8100}html.theme--documenter-dark .is-warning.textarea:focus,html.theme--documenter-dark .is-warning.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--documenter-dark .is-warning.is-focused.textarea,html.theme--documenter-dark .is-warning.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-warning.textarea:active,html.theme--documenter-dark .is-warning.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--documenter-dark .is-warning.is-active.textarea,html.theme--documenter-dark .is-warning.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .is-danger.textarea,html.theme--documenter-dark .is-danger.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#9e1b0d}html.theme--documenter-dark .is-danger.textarea:focus,html.theme--documenter-dark .is-danger.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--documenter-dark .is-danger.is-focused.textarea,html.theme--documenter-dark .is-danger.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-danger.textarea:active,html.theme--documenter-dark .is-danger.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--documenter-dark .is-danger.is-active.textarea,html.theme--documenter-dark .is-danger.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .is-small.textarea,html.theme--documenter-dark .is-small.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .is-medium.textarea,html.theme--documenter-dark .is-medium.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--documenter-dark .is-large.textarea,html.theme--documenter-dark .is-large.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--documenter-dark .is-fullwidth.textarea,html.theme--documenter-dark .is-fullwidth.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--documenter-dark .is-inline.textarea,html.theme--documenter-dark .is-inline.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--documenter-dark .input.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--documenter-dark .input.is-static,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--documenter-dark .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--documenter-dark .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--documenter-dark .textarea[rows]{height:initial}html.theme--documenter-dark .textarea.has-fixed-size{resize:none}html.theme--documenter-dark .radio,html.theme--documenter-dark .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--documenter-dark .radio input,html.theme--documenter-dark .checkbox input{cursor:pointer}html.theme--documenter-dark .radio:hover,html.theme--documenter-dark .checkbox:hover{color:#8c9b9d}html.theme--documenter-dark .radio[disabled],html.theme--documenter-dark .checkbox[disabled],fieldset[disabled] html.theme--documenter-dark .radio,fieldset[disabled] html.theme--documenter-dark .checkbox,html.theme--documenter-dark .radio input[disabled],html.theme--documenter-dark .checkbox input[disabled]{color:#fff;cursor:not-allowed}html.theme--documenter-dark .radio+.radio{margin-left:.5em}html.theme--documenter-dark .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--documenter-dark .select:not(.is-multiple){height:2.5em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border-color:#1abc9c;right:1.125em;z-index:4}html.theme--documenter-dark .select.is-rounded select,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--documenter-dark .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--documenter-dark .select select::-ms-expand{display:none}html.theme--documenter-dark .select select[disabled]:hover,fieldset[disabled] html.theme--documenter-dark .select select:hover{border-color:#282f2f}html.theme--documenter-dark .select select:not([multiple]){padding-right:2.5em}html.theme--documenter-dark .select select[multiple]{height:auto;padding:0}html.theme--documenter-dark .select select[multiple] option{padding:0.5em 1em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#8c9b9d}html.theme--documenter-dark .select.is-white:not(:hover)::after{border-color:#fff}html.theme--documenter-dark .select.is-white select{border-color:#fff}html.theme--documenter-dark .select.is-white select:hover,html.theme--documenter-dark .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--documenter-dark .select.is-white select:focus,html.theme--documenter-dark .select.is-white select.is-focused,html.theme--documenter-dark .select.is-white select:active,html.theme--documenter-dark .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select:hover,html.theme--documenter-dark .select.is-black select.is-hovered{border-color:#000}html.theme--documenter-dark .select.is-black select:focus,html.theme--documenter-dark .select.is-black select.is-focused,html.theme--documenter-dark .select.is-black select:active,html.theme--documenter-dark .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .select.is-light:not(:hover)::after{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select:hover,html.theme--documenter-dark .select.is-light select.is-hovered{border-color:#dde4e6}html.theme--documenter-dark .select.is-light select:focus,html.theme--documenter-dark .select.is-light select.is-focused,html.theme--documenter-dark .select.is-light select:active,html.theme--documenter-dark .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .select.is-dark:not(:hover)::after,html.theme--documenter-dark .content kbd.select:not(:hover)::after{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select,html.theme--documenter-dark .content kbd.select select{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select:hover,html.theme--documenter-dark .content kbd.select select:hover,html.theme--documenter-dark .select.is-dark select.is-hovered,html.theme--documenter-dark .content kbd.select select.is-hovered{border-color:#1d2122}html.theme--documenter-dark .select.is-dark select:focus,html.theme--documenter-dark .content kbd.select select:focus,html.theme--documenter-dark .select.is-dark select.is-focused,html.theme--documenter-dark .content kbd.select select.is-focused,html.theme--documenter-dark .select.is-dark select:active,html.theme--documenter-dark .content kbd.select select:active,html.theme--documenter-dark .select.is-dark select.is-active,html.theme--documenter-dark .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .select.is-primary:not(:hover)::after,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select:hover,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:hover,html.theme--documenter-dark .select.is-primary select.is-hovered,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#2f4d6d}html.theme--documenter-dark .select.is-primary select:focus,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:focus,html.theme--documenter-dark .select.is-primary select.is-focused,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--documenter-dark .select.is-primary select:active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:active,html.theme--documenter-dark .select.is-primary select.is-active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .select.is-link:not(:hover)::after{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select:hover,html.theme--documenter-dark .select.is-link select.is-hovered{border-color:#17a689}html.theme--documenter-dark .select.is-link select:focus,html.theme--documenter-dark .select.is-link select.is-focused,html.theme--documenter-dark .select.is-link select:active,html.theme--documenter-dark .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select.is-info:not(:hover)::after{border-color:#024c7d}html.theme--documenter-dark .select.is-info select{border-color:#024c7d}html.theme--documenter-dark .select.is-info select:hover,html.theme--documenter-dark .select.is-info select.is-hovered{border-color:#023d64}html.theme--documenter-dark .select.is-info select:focus,html.theme--documenter-dark .select.is-info select.is-focused,html.theme--documenter-dark .select.is-info select:active,html.theme--documenter-dark .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .select.is-success:not(:hover)::after{border-color:#008438}html.theme--documenter-dark .select.is-success select{border-color:#008438}html.theme--documenter-dark .select.is-success select:hover,html.theme--documenter-dark .select.is-success select.is-hovered{border-color:#006b2d}html.theme--documenter-dark .select.is-success select:focus,html.theme--documenter-dark .select.is-success select.is-focused,html.theme--documenter-dark .select.is-success select:active,html.theme--documenter-dark .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .select.is-warning:not(:hover)::after{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select:hover,html.theme--documenter-dark .select.is-warning select.is-hovered{border-color:#946e00}html.theme--documenter-dark .select.is-warning select:focus,html.theme--documenter-dark .select.is-warning select.is-focused,html.theme--documenter-dark .select.is-warning select:active,html.theme--documenter-dark .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .select.is-danger:not(:hover)::after{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select:hover,html.theme--documenter-dark .select.is-danger select.is-hovered{border-color:#86170b}html.theme--documenter-dark .select.is-danger select:focus,html.theme--documenter-dark .select.is-danger select.is-focused,html.theme--documenter-dark .select.is-danger select:active,html.theme--documenter-dark .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .select.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .select.is-medium{font-size:1.25rem}html.theme--documenter-dark .select.is-large{font-size:1.5rem}html.theme--documenter-dark .select.is-disabled::after{border-color:#fff !important;opacity:0.5}html.theme--documenter-dark .select.is-fullwidth{width:100%}html.theme--documenter-dark .select.is-fullwidth select{width:100%}html.theme--documenter-dark .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--documenter-dark .select.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .select.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--documenter-dark .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:hover .file-cta,html.theme--documenter-dark .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:focus .file-cta,html.theme--documenter-dark .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--documenter-dark .file.is-white:active .file-cta,html.theme--documenter-dark .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:hover .file-cta,html.theme--documenter-dark .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:focus .file-cta,html.theme--documenter-dark .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--documenter-dark .file.is-black:active .file-cta,html.theme--documenter-dark .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-light .file-cta{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:hover .file-cta,html.theme--documenter-dark .file.is-light.is-hovered .file-cta{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:focus .file-cta,html.theme--documenter-dark .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(236,240,241,0.25);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:active .file-cta,html.theme--documenter-dark .file.is-light.is-active .file-cta{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-dark .file-cta,html.theme--documenter-dark .content kbd.file .file-cta{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:hover .file-cta,html.theme--documenter-dark .content kbd.file:hover .file-cta,html.theme--documenter-dark .file.is-dark.is-hovered .file-cta,html.theme--documenter-dark .content kbd.file.is-hovered .file-cta{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:focus .file-cta,html.theme--documenter-dark .content kbd.file:focus .file-cta,html.theme--documenter-dark .file.is-dark.is-focused .file-cta,html.theme--documenter-dark .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(40,47,47,0.25);color:#fff}html.theme--documenter-dark .file.is-dark:active .file-cta,html.theme--documenter-dark .content kbd.file:active .file-cta,html.theme--documenter-dark .file.is-dark.is-active .file-cta,html.theme--documenter-dark .content kbd.file.is-active .file-cta{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:hover .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--documenter-dark .file.is-primary.is-hovered .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:focus .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--documenter-dark .file.is-primary.is-focused .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(55,90,127,0.25);color:#fff}html.theme--documenter-dark .file.is-primary:active .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--documenter-dark .file.is-primary.is-active .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link .file-cta{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:hover .file-cta,html.theme--documenter-dark .file.is-link.is-hovered .file-cta{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:focus .file-cta,html.theme--documenter-dark .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(26,188,156,0.25);color:#fff}html.theme--documenter-dark .file.is-link:active .file-cta,html.theme--documenter-dark .file.is-link.is-active .file-cta{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info .file-cta{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:hover .file-cta,html.theme--documenter-dark .file.is-info.is-hovered .file-cta{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:focus .file-cta,html.theme--documenter-dark .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(2,76,125,0.25);color:#fff}html.theme--documenter-dark .file.is-info:active .file-cta,html.theme--documenter-dark .file.is-info.is-active .file-cta{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success .file-cta{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:hover .file-cta,html.theme--documenter-dark .file.is-success.is-hovered .file-cta{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:focus .file-cta,html.theme--documenter-dark .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(0,132,56,0.25);color:#fff}html.theme--documenter-dark .file.is-success:active .file-cta,html.theme--documenter-dark .file.is-success.is-active .file-cta{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning .file-cta{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:hover .file-cta,html.theme--documenter-dark .file.is-warning.is-hovered .file-cta{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:focus .file-cta,html.theme--documenter-dark .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(173,129,0,0.25);color:#fff}html.theme--documenter-dark .file.is-warning:active .file-cta,html.theme--documenter-dark .file.is-warning.is-active .file-cta{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger .file-cta{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:hover .file-cta,html.theme--documenter-dark .file.is-danger.is-hovered .file-cta{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:focus .file-cta,html.theme--documenter-dark .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(158,27,13,0.25);color:#fff}html.theme--documenter-dark .file.is-danger:active .file-cta,html.theme--documenter-dark .file.is-danger.is-active .file-cta{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--documenter-dark .file.is-normal{font-size:1rem}html.theme--documenter-dark .file.is-medium{font-size:1.25rem}html.theme--documenter-dark .file.is-medium .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-large{font-size:1.5rem}html.theme--documenter-dark .file.is-large .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--documenter-dark .file.has-name.is-empty .file-name{display:none}html.theme--documenter-dark .file.is-boxed .file-label{flex-direction:column}html.theme--documenter-dark .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--documenter-dark .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--documenter-dark .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--documenter-dark .file.is-boxed .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-boxed.is-small .file-icon .fa,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--documenter-dark .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--documenter-dark .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--documenter-dark .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--documenter-dark .file.is-centered{justify-content:center}html.theme--documenter-dark .file.is-fullwidth .file-label{width:100%}html.theme--documenter-dark .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--documenter-dark .file.is-right{justify-content:flex-end}html.theme--documenter-dark .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--documenter-dark .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--documenter-dark .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--documenter-dark .file-label:hover .file-cta{background-color:#232829;color:#f2f2f2}html.theme--documenter-dark .file-label:hover .file-name{border-color:#596668}html.theme--documenter-dark .file-label:active .file-cta{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .file-label:active .file-name{border-color:#535f61}html.theme--documenter-dark .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--documenter-dark .file-cta{background-color:#282f2f;color:#fff}html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--documenter-dark .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--documenter-dark .file-icon .fa{font-size:14px}html.theme--documenter-dark .label{color:#f2f2f2;display:block;font-size:1rem;font-weight:700}html.theme--documenter-dark .label:not(:last-child){margin-bottom:0.5em}html.theme--documenter-dark .label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--documenter-dark .label.is-medium{font-size:1.25rem}html.theme--documenter-dark .label.is-large{font-size:1.5rem}html.theme--documenter-dark .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--documenter-dark .help.is-white{color:#fff}html.theme--documenter-dark .help.is-black{color:#0a0a0a}html.theme--documenter-dark .help.is-light{color:#ecf0f1}html.theme--documenter-dark .help.is-dark,html.theme--documenter-dark .content kbd.help{color:#282f2f}html.theme--documenter-dark .help.is-primary,html.theme--documenter-dark .docstring>section>a.help.docs-sourcelink{color:#375a7f}html.theme--documenter-dark .help.is-link{color:#1abc9c}html.theme--documenter-dark .help.is-info{color:#024c7d}html.theme--documenter-dark .help.is-success{color:#008438}html.theme--documenter-dark .help.is-warning{color:#ad8100}html.theme--documenter-dark .help.is-danger{color:#9e1b0d}html.theme--documenter-dark .field:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.has-addons{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--documenter-dark .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.has-addons.has-addons-centered{justify-content:center}html.theme--documenter-dark .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--documenter-dark .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .field.is-grouped{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.is-grouped>.control{flex-shrink:0}html.theme--documenter-dark .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--documenter-dark .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field.is-horizontal{display:flex}}html.theme--documenter-dark .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--documenter-dark .field-label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-normal{padding-top:0.375em}html.theme--documenter-dark .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--documenter-dark .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--documenter-dark .field-body .field{margin-bottom:0}html.theme--documenter-dark .field-body>.field{flex-shrink:1}html.theme--documenter-dark .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--documenter-dark .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--documenter-dark .control.has-icons-left .input:focus~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-left .select:focus~.icon,html.theme--documenter-dark .control.has-icons-right .input:focus~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-right .select:focus~.icon{color:#282f2f}html.theme--documenter-dark .control.has-icons-left .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-small~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--documenter-dark .control.has-icons-left .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--documenter-dark .control.has-icons-left .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon{color:#5e6d6f;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--documenter-dark .control.has-icons-left .input,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--documenter-dark .control.has-icons-left .select select{padding-left:2.5em}html.theme--documenter-dark .control.has-icons-left .icon.is-left{left:0}html.theme--documenter-dark .control.has-icons-right .input,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--documenter-dark .control.has-icons-right .select select{padding-right:2.5em}html.theme--documenter-dark .control.has-icons-right .icon.is-right{right:0}html.theme--documenter-dark .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--documenter-dark .control.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .control.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--documenter-dark .breadcrumb a{align-items:center;color:#1abc9c;display:flex;justify-content:center;padding:0 .75em}html.theme--documenter-dark .breadcrumb a:hover{color:#1dd2af}html.theme--documenter-dark .breadcrumb li{align-items:center;display:flex}html.theme--documenter-dark .breadcrumb li:first-child a{padding-left:0}html.theme--documenter-dark .breadcrumb li.is-active a{color:#f2f2f2;cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb li+li::before{color:#8c9b9d;content:"\0002f"}html.theme--documenter-dark .breadcrumb ul,html.theme--documenter-dark .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .breadcrumb .icon:first-child{margin-right:.5em}html.theme--documenter-dark .breadcrumb .icon:last-child{margin-left:.5em}html.theme--documenter-dark .breadcrumb.is-centered ol,html.theme--documenter-dark .breadcrumb.is-centered ul{justify-content:center}html.theme--documenter-dark .breadcrumb.is-right ol,html.theme--documenter-dark .breadcrumb.is-right ul{justify-content:flex-end}html.theme--documenter-dark .breadcrumb.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--documenter-dark .breadcrumb.is-medium{font-size:1.25rem}html.theme--documenter-dark .breadcrumb.is-large{font-size:1.5rem}html.theme--documenter-dark .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--documenter-dark .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--documenter-dark .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--documenter-dark .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--documenter-dark .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#fff;max-width:100%;position:relative}html.theme--documenter-dark .card-footer:first-child,html.theme--documenter-dark .card-content:first-child,html.theme--documenter-dark .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-footer:last-child,html.theme--documenter-dark .card-content:last-child,html.theme--documenter-dark .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--documenter-dark .card-header-title{align-items:center;color:#f2f2f2;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--documenter-dark .card-header-title.is-centered{justify-content:center}html.theme--documenter-dark .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--documenter-dark .card-image{display:block;position:relative}html.theme--documenter-dark .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--documenter-dark .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--documenter-dark .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--documenter-dark .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--documenter-dark .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--documenter-dark .dropdown.is-active .dropdown-menu,html.theme--documenter-dark .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--documenter-dark .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--documenter-dark .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--documenter-dark .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .dropdown-content{background-color:#282f2f;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--documenter-dark .dropdown-item{color:#fff;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--documenter-dark a.dropdown-item,html.theme--documenter-dark button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--documenter-dark a.dropdown-item:hover,html.theme--documenter-dark button.dropdown-item:hover{background-color:#282f2f;color:#0a0a0a}html.theme--documenter-dark a.dropdown-item.is-active,html.theme--documenter-dark button.dropdown-item.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--documenter-dark .level{align-items:center;justify-content:space-between}html.theme--documenter-dark .level code{border-radius:.4em}html.theme--documenter-dark .level img{display:inline-block;vertical-align:top}html.theme--documenter-dark .level.is-mobile{display:flex}html.theme--documenter-dark .level.is-mobile .level-left,html.theme--documenter-dark .level.is-mobile .level-right{display:flex}html.theme--documenter-dark .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--documenter-dark .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level{display:flex}html.theme--documenter-dark .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--documenter-dark .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--documenter-dark .level-item .title,html.theme--documenter-dark .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--documenter-dark .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--documenter-dark .level-left,html.theme--documenter-dark .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .level-left .level-item.is-flexible,html.theme--documenter-dark .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left .level-item:not(:last-child),html.theme--documenter-dark .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--documenter-dark .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left{display:flex}}html.theme--documenter-dark .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-right{display:flex}}html.theme--documenter-dark .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--documenter-dark .media .content:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .media .media{border-top:1px solid rgba(94,109,111,0.5);display:flex;padding-top:.75rem}html.theme--documenter-dark .media .media .content:not(:last-child),html.theme--documenter-dark .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--documenter-dark .media .media .media{padding-top:.5rem}html.theme--documenter-dark .media .media .media+.media{margin-top:.5rem}html.theme--documenter-dark .media+.media{border-top:1px solid rgba(94,109,111,0.5);margin-top:1rem;padding-top:1rem}html.theme--documenter-dark .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--documenter-dark .media-left,html.theme--documenter-dark .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .media-left{margin-right:1rem}html.theme--documenter-dark .media-right{margin-left:1rem}html.theme--documenter-dark .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .media-content{overflow-x:auto}}html.theme--documenter-dark .menu{font-size:1rem}html.theme--documenter-dark .menu.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--documenter-dark .menu.is-medium{font-size:1.25rem}html.theme--documenter-dark .menu.is-large{font-size:1.5rem}html.theme--documenter-dark .menu-list{line-height:1.25}html.theme--documenter-dark .menu-list a{border-radius:3px;color:#fff;display:block;padding:0.5em 0.75em}html.theme--documenter-dark .menu-list a:hover{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .menu-list a.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .menu-list li ul{border-left:1px solid #5e6d6f;margin:.75em;padding-left:.75em}html.theme--documenter-dark .menu-label{color:#fff;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--documenter-dark .menu-label:not(:first-child){margin-top:1em}html.theme--documenter-dark .menu-label:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .message{background-color:#282f2f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .message strong{color:currentColor}html.theme--documenter-dark .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .message.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--documenter-dark .message.is-medium{font-size:1.25rem}html.theme--documenter-dark .message.is-large{font-size:1.5rem}html.theme--documenter-dark .message.is-white{background-color:#fff}html.theme--documenter-dark .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .message.is-white .message-body{border-color:#fff}html.theme--documenter-dark .message.is-black{background-color:#fafafa}html.theme--documenter-dark .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .message.is-black .message-body{border-color:#0a0a0a}html.theme--documenter-dark .message.is-light{background-color:#f9fafb}html.theme--documenter-dark .message.is-light .message-header{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .message.is-light .message-body{border-color:#ecf0f1}html.theme--documenter-dark .message.is-dark,html.theme--documenter-dark .content kbd.message{background-color:#f9fafa}html.theme--documenter-dark .message.is-dark .message-header,html.theme--documenter-dark .content kbd.message .message-header{background-color:#282f2f;color:#fff}html.theme--documenter-dark .message.is-dark .message-body,html.theme--documenter-dark .content kbd.message .message-body{border-color:#282f2f}html.theme--documenter-dark .message.is-primary,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink{background-color:#f1f5f9}html.theme--documenter-dark .message.is-primary .message-header,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-header{background-color:#375a7f;color:#fff}html.theme--documenter-dark .message.is-primary .message-body,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-body{border-color:#375a7f;color:#4d7eb2}html.theme--documenter-dark .message.is-link{background-color:#edfdf9}html.theme--documenter-dark .message.is-link .message-header{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .message.is-link .message-body{border-color:#1abc9c;color:#15987e}html.theme--documenter-dark .message.is-info{background-color:#ebf7ff}html.theme--documenter-dark .message.is-info .message-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .message.is-info .message-body{border-color:#024c7d;color:#0e9dfb}html.theme--documenter-dark .message.is-success{background-color:#ebfff3}html.theme--documenter-dark .message.is-success .message-header{background-color:#008438;color:#fff}html.theme--documenter-dark .message.is-success .message-body{border-color:#008438;color:#00eb64}html.theme--documenter-dark .message.is-warning{background-color:#fffaeb}html.theme--documenter-dark .message.is-warning .message-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .message.is-warning .message-body{border-color:#ad8100;color:#d19c00}html.theme--documenter-dark .message.is-danger{background-color:#fdeeec}html.theme--documenter-dark .message.is-danger .message-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .message.is-danger .message-body{border-color:#9e1b0d;color:#ec311d}html.theme--documenter-dark .message-header{align-items:center;background-color:#fff;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--documenter-dark .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--documenter-dark .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--documenter-dark .message-body{border-color:#5e6d6f;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#fff;padding:1.25em 1.5em}html.theme--documenter-dark .message-body code,html.theme--documenter-dark .message-body pre{background-color:#fff}html.theme--documenter-dark .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--documenter-dark .modal.is-active{display:flex}html.theme--documenter-dark .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--documenter-dark .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--documenter-dark .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--documenter-dark .modal-card-head,html.theme--documenter-dark .modal-card-foot{align-items:center;background-color:#282f2f;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--documenter-dark .modal-card-head{border-bottom:1px solid #5e6d6f;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--documenter-dark .modal-card-title{color:#f2f2f2;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--documenter-dark .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #5e6d6f}html.theme--documenter-dark .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--documenter-dark .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--documenter-dark .navbar{background-color:#375a7f;min-height:4rem;position:relative;z-index:30}html.theme--documenter-dark .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-white .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--documenter-dark .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-black .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--documenter-dark .navbar.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-light .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}}html.theme--documenter-dark .navbar.is-dark,html.theme--documenter-dark .content kbd.navbar{background-color:#282f2f;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-burger,html.theme--documenter-dark .content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-dark .navbar-start>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-end>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#282f2f;color:#fff}}html.theme--documenter-dark .navbar.is-primary,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-burger,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-primary .navbar-start>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-end>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#375a7f;color:#fff}}html.theme--documenter-dark .navbar.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-link .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c;color:#fff}}html.theme--documenter-dark .navbar.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-info .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#024c7d;color:#fff}}html.theme--documenter-dark .navbar.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-success .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#008438;color:#fff}}html.theme--documenter-dark .navbar.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-warning .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ad8100;color:#fff}}html.theme--documenter-dark .navbar.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-danger .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#9e1b0d;color:#fff}}html.theme--documenter-dark .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--documenter-dark .navbar.has-shadow{box-shadow:0 2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-bottom,html.theme--documenter-dark .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-top{top:0}html.theme--documenter-dark html.has-navbar-fixed-top,html.theme--documenter-dark body.has-navbar-fixed-top{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom,html.theme--documenter-dark body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--documenter-dark .navbar-brand,html.theme--documenter-dark .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--documenter-dark .navbar-brand a.navbar-item:focus,html.theme--documenter-dark .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--documenter-dark .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--documenter-dark .navbar-burger{color:#fff;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--documenter-dark .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--documenter-dark .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--documenter-dark .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--documenter-dark .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--documenter-dark .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--documenter-dark .navbar-menu{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{color:#fff;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--documenter-dark .navbar-item .icon:only-child,html.theme--documenter-dark .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--documenter-dark a.navbar-item,html.theme--documenter-dark .navbar-link{cursor:pointer}html.theme--documenter-dark a.navbar-item:focus,html.theme--documenter-dark a.navbar-item:focus-within,html.theme--documenter-dark a.navbar-item:hover,html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link:focus,html.theme--documenter-dark .navbar-link:focus-within,html.theme--documenter-dark .navbar-link:hover,html.theme--documenter-dark .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-item{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .navbar-item img{max-height:1.75rem}html.theme--documenter-dark .navbar-item.has-dropdown{padding:0}html.theme--documenter-dark .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--documenter-dark .navbar-item.is-tab:focus,html.theme--documenter-dark .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c}html.theme--documenter-dark .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c;border-bottom-style:solid;border-bottom-width:3px;color:#1abc9c;padding-bottom:calc(0.5rem - 3px)}html.theme--documenter-dark .navbar-content{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--documenter-dark .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--documenter-dark .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar>.container{display:block}html.theme--documenter-dark .navbar-brand .navbar-item,html.theme--documenter-dark .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--documenter-dark .navbar-link::after{display:none}html.theme--documenter-dark .navbar-menu{background-color:#375a7f;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--documenter-dark .navbar-menu.is-active{display:block}html.theme--documenter-dark .navbar.is-fixed-bottom-touch,html.theme--documenter-dark .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-touch{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-touch{top:0}html.theme--documenter-dark .navbar.is-fixed-top .navbar-menu,html.theme--documenter-dark .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--documenter-dark html.has-navbar-fixed-top-touch,html.theme--documenter-dark body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-touch,html.theme--documenter-dark body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar,html.theme--documenter-dark .navbar-menu,html.theme--documenter-dark .navbar-start,html.theme--documenter-dark .navbar-end{align-items:stretch;display:flex}html.theme--documenter-dark .navbar{min-height:4rem}html.theme--documenter-dark .navbar.is-spaced{padding:1rem 2rem}html.theme--documenter-dark .navbar.is-spaced .navbar-start,html.theme--documenter-dark .navbar.is-spaced .navbar-end{align-items:center}html.theme--documenter-dark .navbar.is-spaced a.navbar-item,html.theme--documenter-dark .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent a.navbar-item:hover,html.theme--documenter-dark .navbar.is-transparent a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-transparent .navbar-link:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-link:hover,html.theme--documenter-dark .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-burger{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{align-items:center;display:flex}html.theme--documenter-dark .navbar-item.has-dropdown{align-items:stretch}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--documenter-dark .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--documenter-dark .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--documenter-dark .navbar-dropdown{background-color:#375a7f;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--documenter-dark .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--documenter-dark .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}.navbar.is-spaced html.theme--documenter-dark .navbar-dropdown,html.theme--documenter-dark .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--documenter-dark .navbar-dropdown.is-right{left:auto;right:0}html.theme--documenter-dark .navbar-divider{display:block}html.theme--documenter-dark .navbar>.container .navbar-brand,html.theme--documenter-dark .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--documenter-dark .navbar>.container .navbar-menu,html.theme--documenter-dark .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop,html.theme--documenter-dark .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-desktop{top:0}html.theme--documenter-dark html.has-navbar-fixed-top-desktop,html.theme--documenter-dark body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-desktop,html.theme--documenter-dark body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-top,html.theme--documenter-dark body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-bottom,html.theme--documenter-dark body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link.is-active{color:#1abc9c}html.theme--documenter-dark a.navbar-item.is-active:not(:focus):not(:hover),html.theme--documenter-dark .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--documenter-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--documenter-dark .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--documenter-dark .pagination{font-size:1rem;margin:-.25rem}html.theme--documenter-dark .pagination.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--documenter-dark .pagination.is-medium{font-size:1.25rem}html.theme--documenter-dark .pagination.is-large{font-size:1.5rem}html.theme--documenter-dark .pagination.is-rounded .pagination-previous,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--documenter-dark .pagination.is-rounded .pagination-next,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--documenter-dark .pagination.is-rounded .pagination-link,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--documenter-dark .pagination,html.theme--documenter-dark .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link{border-color:#5e6d6f;color:#1abc9c;min-width:2.5em}html.theme--documenter-dark .pagination-previous:hover,html.theme--documenter-dark .pagination-next:hover,html.theme--documenter-dark .pagination-link:hover{border-color:#8c9b9d;color:#1dd2af}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus{border-color:#8c9b9d}html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-previous.is-disabled,html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-next.is-disabled,html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-link.is-disabled{background-color:#5e6d6f;border-color:#5e6d6f;box-shadow:none;color:#fff;opacity:0.5}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--documenter-dark .pagination-link.is-current{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .pagination-ellipsis{color:#8c9b9d;pointer-events:none}html.theme--documenter-dark .pagination-list{flex-wrap:wrap}html.theme--documenter-dark .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--documenter-dark .pagination{flex-wrap:wrap}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination-previous{order:2}html.theme--documenter-dark .pagination-next{order:3}html.theme--documenter-dark .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination.is-centered .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--documenter-dark .pagination.is-centered .pagination-next{order:3}html.theme--documenter-dark .pagination.is-right .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-right .pagination-next{order:2}html.theme--documenter-dark .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--documenter-dark .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--documenter-dark .panel:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--documenter-dark .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--documenter-dark .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--documenter-dark .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--documenter-dark .panel.is-light .panel-heading{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .panel.is-light .panel-tabs a.is-active{border-bottom-color:#ecf0f1}html.theme--documenter-dark .panel.is-light .panel-block.is-active .panel-icon{color:#ecf0f1}html.theme--documenter-dark .panel.is-dark .panel-heading,html.theme--documenter-dark .content kbd.panel .panel-heading{background-color:#282f2f;color:#fff}html.theme--documenter-dark .panel.is-dark .panel-tabs a.is-active,html.theme--documenter-dark .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#282f2f}html.theme--documenter-dark .panel.is-dark .panel-block.is-active .panel-icon,html.theme--documenter-dark .content kbd.panel .panel-block.is-active .panel-icon{color:#282f2f}html.theme--documenter-dark .panel.is-primary .panel-heading,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#375a7f;color:#fff}html.theme--documenter-dark .panel.is-primary .panel-tabs a.is-active,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#375a7f}html.theme--documenter-dark .panel.is-primary .panel-block.is-active .panel-icon,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#375a7f}html.theme--documenter-dark .panel.is-link .panel-heading{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .panel.is-link .panel-tabs a.is-active{border-bottom-color:#1abc9c}html.theme--documenter-dark .panel.is-link .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel.is-info .panel-heading{background-color:#024c7d;color:#fff}html.theme--documenter-dark .panel.is-info .panel-tabs a.is-active{border-bottom-color:#024c7d}html.theme--documenter-dark .panel.is-info .panel-block.is-active .panel-icon{color:#024c7d}html.theme--documenter-dark .panel.is-success .panel-heading{background-color:#008438;color:#fff}html.theme--documenter-dark .panel.is-success .panel-tabs a.is-active{border-bottom-color:#008438}html.theme--documenter-dark .panel.is-success .panel-block.is-active .panel-icon{color:#008438}html.theme--documenter-dark .panel.is-warning .panel-heading{background-color:#ad8100;color:#fff}html.theme--documenter-dark .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ad8100}html.theme--documenter-dark .panel.is-warning .panel-block.is-active .panel-icon{color:#ad8100}html.theme--documenter-dark .panel.is-danger .panel-heading{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#9e1b0d}html.theme--documenter-dark .panel.is-danger .panel-block.is-active .panel-icon{color:#9e1b0d}html.theme--documenter-dark .panel-tabs:not(:last-child),html.theme--documenter-dark .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--documenter-dark .panel-heading{background-color:#343c3d;border-radius:8px 8px 0 0;color:#f2f2f2;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--documenter-dark .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--documenter-dark .panel-tabs a{border-bottom:1px solid #5e6d6f;margin-bottom:-1px;padding:0.5em}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#343c3d;color:#17a689}html.theme--documenter-dark .panel-list a{color:#fff}html.theme--documenter-dark .panel-list a:hover{color:#1abc9c}html.theme--documenter-dark .panel-block{align-items:center;color:#f2f2f2;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--documenter-dark .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--documenter-dark .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--documenter-dark .panel-block.is-wrapped{flex-wrap:wrap}html.theme--documenter-dark .panel-block.is-active{border-left-color:#1abc9c;color:#17a689}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--documenter-dark a.panel-block,html.theme--documenter-dark label.panel-block{cursor:pointer}html.theme--documenter-dark a.panel-block:hover,html.theme--documenter-dark label.panel-block:hover{background-color:#282f2f}html.theme--documenter-dark .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#fff;margin-right:.75em}html.theme--documenter-dark .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--documenter-dark .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--documenter-dark .tabs a{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;color:#fff;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--documenter-dark .tabs a:hover{border-bottom-color:#f2f2f2;color:#f2f2f2}html.theme--documenter-dark .tabs li{display:block}html.theme--documenter-dark .tabs li.is-active a{border-bottom-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .tabs ul{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--documenter-dark .tabs ul.is-left{padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--documenter-dark .tabs .icon:first-child{margin-right:.5em}html.theme--documenter-dark .tabs .icon:last-child{margin-left:.5em}html.theme--documenter-dark .tabs.is-centered ul{justify-content:center}html.theme--documenter-dark .tabs.is-right ul{justify-content:flex-end}html.theme--documenter-dark .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--documenter-dark .tabs.is-boxed a:hover{background-color:#282f2f;border-bottom-color:#5e6d6f}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#5e6d6f;border-bottom-color:rgba(0,0,0,0) !important}html.theme--documenter-dark .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .tabs.is-toggle a{border-color:#5e6d6f;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--documenter-dark .tabs.is-toggle a:hover{background-color:#282f2f;border-color:#8c9b9d;z-index:2}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li.is-active a{background-color:#1abc9c;border-color:#1abc9c;color:#fff;z-index:1}html.theme--documenter-dark .tabs.is-toggle ul{border-bottom:none}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--documenter-dark .tabs.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--documenter-dark .tabs.is-medium{font-size:1.25rem}html.theme--documenter-dark .tabs.is-large{font-size:1.5rem}html.theme--documenter-dark .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--documenter-dark .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--documenter-dark .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--documenter-dark .column.is-narrow-mobile{flex:none;width:unset}html.theme--documenter-dark .column.is-full-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-mobile{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--documenter-dark .column.is-0-mobile{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-mobile{margin-left:0%}html.theme--documenter-dark .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-mobile{margin-left:25%}html.theme--documenter-dark .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-mobile{margin-left:50%}html.theme--documenter-dark .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-mobile{margin-left:75%}html.theme--documenter-dark .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .column.is-narrow,html.theme--documenter-dark .column.is-narrow-tablet{flex:none;width:unset}html.theme--documenter-dark .column.is-full,html.theme--documenter-dark .column.is-full-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters,html.theme--documenter-dark .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds,html.theme--documenter-dark .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half,html.theme--documenter-dark .column.is-half-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third,html.theme--documenter-dark .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter,html.theme--documenter-dark .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth,html.theme--documenter-dark .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths,html.theme--documenter-dark .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths,html.theme--documenter-dark .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths,html.theme--documenter-dark .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters,html.theme--documenter-dark .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds,html.theme--documenter-dark .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half,html.theme--documenter-dark .column.is-offset-half-tablet{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third,html.theme--documenter-dark .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter,html.theme--documenter-dark .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth,html.theme--documenter-dark .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths,html.theme--documenter-dark .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths,html.theme--documenter-dark .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths,html.theme--documenter-dark .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--documenter-dark .column.is-0,html.theme--documenter-dark .column.is-0-tablet{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0,html.theme--documenter-dark .column.is-offset-0-tablet{margin-left:0%}html.theme--documenter-dark .column.is-1,html.theme--documenter-dark .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1,html.theme--documenter-dark .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2,html.theme--documenter-dark .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2,html.theme--documenter-dark .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3,html.theme--documenter-dark .column.is-3-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3,html.theme--documenter-dark .column.is-offset-3-tablet{margin-left:25%}html.theme--documenter-dark .column.is-4,html.theme--documenter-dark .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4,html.theme--documenter-dark .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5,html.theme--documenter-dark .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5,html.theme--documenter-dark .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6,html.theme--documenter-dark .column.is-6-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6,html.theme--documenter-dark .column.is-offset-6-tablet{margin-left:50%}html.theme--documenter-dark .column.is-7,html.theme--documenter-dark .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7,html.theme--documenter-dark .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8,html.theme--documenter-dark .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8,html.theme--documenter-dark .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9,html.theme--documenter-dark .column.is-9-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9,html.theme--documenter-dark .column.is-offset-9-tablet{margin-left:75%}html.theme--documenter-dark .column.is-10,html.theme--documenter-dark .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10,html.theme--documenter-dark .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11,html.theme--documenter-dark .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11,html.theme--documenter-dark .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12,html.theme--documenter-dark .column.is-12-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12,html.theme--documenter-dark .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--documenter-dark .column.is-narrow-touch{flex:none;width:unset}html.theme--documenter-dark .column.is-full-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-touch{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-touch{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-touch{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-touch{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-touch{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--documenter-dark .column.is-0-touch{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-touch{margin-left:0%}html.theme--documenter-dark .column.is-1-touch{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-touch{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-touch{margin-left:25%}html.theme--documenter-dark .column.is-4-touch{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-touch{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-touch{margin-left:50%}html.theme--documenter-dark .column.is-7-touch{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-touch{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-touch{margin-left:75%}html.theme--documenter-dark .column.is-10-touch{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-touch{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--documenter-dark .column.is-narrow-desktop{flex:none;width:unset}html.theme--documenter-dark .column.is-full-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-desktop{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--documenter-dark .column.is-0-desktop{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-desktop{margin-left:0%}html.theme--documenter-dark .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-desktop{margin-left:25%}html.theme--documenter-dark .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-desktop{margin-left:50%}html.theme--documenter-dark .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-desktop{margin-left:75%}html.theme--documenter-dark .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--documenter-dark .column.is-narrow-widescreen{flex:none;width:unset}html.theme--documenter-dark .column.is-full-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--documenter-dark .column.is-0-widescreen{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-widescreen{margin-left:0%}html.theme--documenter-dark .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--documenter-dark .column.is-narrow-fullhd{flex:none;width:unset}html.theme--documenter-dark .column.is-full-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--documenter-dark .column.is-0-fullhd{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-fullhd{margin-left:0%}html.theme--documenter-dark .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-fullhd{margin-left:100%}}html.theme--documenter-dark .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .columns:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--documenter-dark .columns.is-centered{justify-content:center}html.theme--documenter-dark .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--documenter-dark .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--documenter-dark .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .columns.is-gapless:last-child{margin-bottom:0}html.theme--documenter-dark .columns.is-mobile{display:flex}html.theme--documenter-dark .columns.is-multiline{flex-wrap:wrap}html.theme--documenter-dark .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-desktop{display:flex}}html.theme--documenter-dark .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--documenter-dark .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--documenter-dark .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--documenter-dark .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--documenter-dark .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--documenter-dark .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--documenter-dark .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--documenter-dark .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--documenter-dark .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--documenter-dark .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--documenter-dark .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--documenter-dark .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--documenter-dark .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .tile.is-child{margin:0 !important}html.theme--documenter-dark .tile.is-parent{padding:.75rem}html.theme--documenter-dark .tile.is-vertical{flex-direction:column}html.theme--documenter-dark .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--documenter-dark .tile:not(.is-child){display:flex}html.theme--documenter-dark .tile.is-1{flex:none;width:8.33333337%}html.theme--documenter-dark .tile.is-2{flex:none;width:16.66666674%}html.theme--documenter-dark .tile.is-3{flex:none;width:25%}html.theme--documenter-dark .tile.is-4{flex:none;width:33.33333337%}html.theme--documenter-dark .tile.is-5{flex:none;width:41.66666674%}html.theme--documenter-dark .tile.is-6{flex:none;width:50%}html.theme--documenter-dark .tile.is-7{flex:none;width:58.33333337%}html.theme--documenter-dark .tile.is-8{flex:none;width:66.66666674%}html.theme--documenter-dark .tile.is-9{flex:none;width:75%}html.theme--documenter-dark .tile.is-10{flex:none;width:83.33333337%}html.theme--documenter-dark .tile.is-11{flex:none;width:91.66666674%}html.theme--documenter-dark .tile.is-12{flex:none;width:100%}}html.theme--documenter-dark .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--documenter-dark .hero .navbar{background:none}html.theme--documenter-dark .hero .tabs ul{border-bottom:none}html.theme--documenter-dark .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-white strong{color:inherit}html.theme--documenter-dark .hero.is-white .title{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--documenter-dark .hero.is-white .subtitle a:not(.button),html.theme--documenter-dark .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-white .navbar-menu{background-color:#fff}}html.theme--documenter-dark .hero.is-white .navbar-item,html.theme--documenter-dark .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--documenter-dark .hero.is-white a.navbar-item:hover,html.theme--documenter-dark .hero.is-white a.navbar-item.is-active,html.theme--documenter-dark .hero.is-white .navbar-link:hover,html.theme--documenter-dark .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--documenter-dark .hero.is-white .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--documenter-dark .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-black strong{color:inherit}html.theme--documenter-dark .hero.is-black .title{color:#fff}html.theme--documenter-dark .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-black .subtitle a:not(.button),html.theme--documenter-dark .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--documenter-dark .hero.is-black .navbar-item,html.theme--documenter-dark .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-black a.navbar-item:hover,html.theme--documenter-dark .hero.is-black a.navbar-item.is-active,html.theme--documenter-dark .hero.is-black .navbar-link:hover,html.theme--documenter-dark .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-black .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--documenter-dark .hero.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-light strong{color:inherit}html.theme--documenter-dark .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--documenter-dark .hero.is-light .subtitle a:not(.button),html.theme--documenter-dark .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-light .navbar-menu{background-color:#ecf0f1}}html.theme--documenter-dark .hero.is-light .navbar-item,html.theme--documenter-dark .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a.navbar-item:hover,html.theme--documenter-dark .hero.is-light a.navbar-item.is-active,html.theme--documenter-dark .hero.is-light .navbar-link:hover,html.theme--documenter-dark .hero.is-light .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--documenter-dark .hero.is-light .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-light .tabs li.is-active a{color:#ecf0f1 !important;opacity:1}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .hero.is-light.is-bold{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}}html.theme--documenter-dark .hero.is-dark,html.theme--documenter-dark .content kbd.hero{background-color:#282f2f;color:#fff}html.theme--documenter-dark .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-dark strong,html.theme--documenter-dark .content kbd.hero strong{color:inherit}html.theme--documenter-dark .hero.is-dark .title,html.theme--documenter-dark .content kbd.hero .title{color:#fff}html.theme--documenter-dark .hero.is-dark .subtitle,html.theme--documenter-dark .content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-dark .subtitle a:not(.button),html.theme--documenter-dark .content kbd.hero .subtitle a:not(.button),html.theme--documenter-dark .hero.is-dark .subtitle strong,html.theme--documenter-dark .content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-dark .navbar-menu,html.theme--documenter-dark .content kbd.hero .navbar-menu{background-color:#282f2f}}html.theme--documenter-dark .hero.is-dark .navbar-item,html.theme--documenter-dark .content kbd.hero .navbar-item,html.theme--documenter-dark .hero.is-dark .navbar-link,html.theme--documenter-dark .content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-dark a.navbar-item:hover,html.theme--documenter-dark .content kbd.hero a.navbar-item:hover,html.theme--documenter-dark .hero.is-dark a.navbar-item.is-active,html.theme--documenter-dark .content kbd.hero a.navbar-item.is-active,html.theme--documenter-dark .hero.is-dark .navbar-link:hover,html.theme--documenter-dark .content kbd.hero .navbar-link:hover,html.theme--documenter-dark .hero.is-dark .navbar-link.is-active,html.theme--documenter-dark .content kbd.hero .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .hero.is-dark .tabs a,html.theme--documenter-dark .content kbd.hero .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-dark .tabs a:hover,html.theme--documenter-dark .content kbd.hero .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-dark .tabs li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs li.is-active a{color:#282f2f !important;opacity:1}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#282f2f}html.theme--documenter-dark .hero.is-dark.is-bold,html.theme--documenter-dark .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-dark.is-bold .navbar-menu,html.theme--documenter-dark .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}}html.theme--documenter-dark .hero.is-primary,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-primary strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--documenter-dark .hero.is-primary .title,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--documenter-dark .hero.is-primary .subtitle,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-primary .subtitle a:not(.button),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--documenter-dark .hero.is-primary .subtitle strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-primary .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#375a7f}}html.theme--documenter-dark .hero.is-primary .navbar-item,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--documenter-dark .hero.is-primary .navbar-link,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-primary a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--documenter-dark .hero.is-primary a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--documenter-dark .hero.is-primary .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--documenter-dark .hero.is-primary .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .hero.is-primary .tabs a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-primary .tabs a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-primary .tabs li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#375a7f !important;opacity:1}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#375a7f}html.theme--documenter-dark .hero.is-primary.is-bold,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-primary.is-bold .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}}html.theme--documenter-dark .hero.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-link strong{color:inherit}html.theme--documenter-dark .hero.is-link .title{color:#fff}html.theme--documenter-dark .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-link .subtitle a:not(.button),html.theme--documenter-dark .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-link .navbar-menu{background-color:#1abc9c}}html.theme--documenter-dark .hero.is-link .navbar-item,html.theme--documenter-dark .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-link a.navbar-item:hover,html.theme--documenter-dark .hero.is-link a.navbar-item.is-active,html.theme--documenter-dark .hero.is-link .navbar-link:hover,html.theme--documenter-dark .hero.is-link .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-link .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-link .tabs li.is-active a{color:#1abc9c !important;opacity:1}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#1abc9c}html.theme--documenter-dark .hero.is-link.is-bold{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}}html.theme--documenter-dark .hero.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-info strong{color:inherit}html.theme--documenter-dark .hero.is-info .title{color:#fff}html.theme--documenter-dark .hero.is-info .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-info .subtitle a:not(.button),html.theme--documenter-dark .hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-info .navbar-menu{background-color:#024c7d}}html.theme--documenter-dark .hero.is-info .navbar-item,html.theme--documenter-dark .hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-info a.navbar-item:hover,html.theme--documenter-dark .hero.is-info a.navbar-item.is-active,html.theme--documenter-dark .hero.is-info .navbar-link:hover,html.theme--documenter-dark .hero.is-info .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .hero.is-info .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-info .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-info .tabs li.is-active a{color:#024c7d !important;opacity:1}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#024c7d}html.theme--documenter-dark .hero.is-info.is-bold{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}}html.theme--documenter-dark .hero.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-success strong{color:inherit}html.theme--documenter-dark .hero.is-success .title{color:#fff}html.theme--documenter-dark .hero.is-success .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-success .subtitle a:not(.button),html.theme--documenter-dark .hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-success .navbar-menu{background-color:#008438}}html.theme--documenter-dark .hero.is-success .navbar-item,html.theme--documenter-dark .hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-success a.navbar-item:hover,html.theme--documenter-dark .hero.is-success a.navbar-item.is-active,html.theme--documenter-dark .hero.is-success .navbar-link:hover,html.theme--documenter-dark .hero.is-success .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .hero.is-success .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-success .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-success .tabs li.is-active a{color:#008438 !important;opacity:1}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#008438}html.theme--documenter-dark .hero.is-success.is-bold{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}}html.theme--documenter-dark .hero.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-warning strong{color:inherit}html.theme--documenter-dark .hero.is-warning .title{color:#fff}html.theme--documenter-dark .hero.is-warning .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-warning .subtitle a:not(.button),html.theme--documenter-dark .hero.is-warning .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-warning .navbar-menu{background-color:#ad8100}}html.theme--documenter-dark .hero.is-warning .navbar-item,html.theme--documenter-dark .hero.is-warning .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-warning a.navbar-item:hover,html.theme--documenter-dark .hero.is-warning a.navbar-item.is-active,html.theme--documenter-dark .hero.is-warning .navbar-link:hover,html.theme--documenter-dark .hero.is-warning .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .hero.is-warning .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-warning .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-warning .tabs li.is-active a{color:#ad8100 !important;opacity:1}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#ad8100}html.theme--documenter-dark .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}}html.theme--documenter-dark .hero.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-danger strong{color:inherit}html.theme--documenter-dark .hero.is-danger .title{color:#fff}html.theme--documenter-dark .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-danger .subtitle a:not(.button),html.theme--documenter-dark .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-danger .navbar-menu{background-color:#9e1b0d}}html.theme--documenter-dark .hero.is-danger .navbar-item,html.theme--documenter-dark .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-danger a.navbar-item:hover,html.theme--documenter-dark .hero.is-danger a.navbar-item.is-active,html.theme--documenter-dark .hero.is-danger .navbar-link:hover,html.theme--documenter-dark .hero.is-danger .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-danger .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-danger .tabs li.is-active a{color:#9e1b0d !important;opacity:1}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#9e1b0d}html.theme--documenter-dark .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}}html.theme--documenter-dark .hero.is-small .hero-body,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--documenter-dark .hero.is-halfheight .hero-body,html.theme--documenter-dark .hero.is-fullheight .hero-body,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--documenter-dark .hero.is-halfheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .hero.is-halfheight{min-height:50vh}html.theme--documenter-dark .hero.is-fullheight{min-height:100vh}html.theme--documenter-dark .hero-video{overflow:hidden}html.theme--documenter-dark .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--documenter-dark .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-video{display:none}}html.theme--documenter-dark .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-buttons .button{display:flex}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-buttons{display:flex;justify-content:center}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--documenter-dark .hero-head,html.theme--documenter-dark .hero-foot{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-body{padding:3rem 3rem}}html.theme--documenter-dark .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--documenter-dark .section{padding:3rem 3rem}html.theme--documenter-dark .section.is-medium{padding:9rem 4.5rem}html.theme--documenter-dark .section.is-large{padding:18rem 6rem}}html.theme--documenter-dark .footer{background-color:#282f2f;padding:3rem 1.5rem 6rem}html.theme--documenter-dark hr{height:1px}html.theme--documenter-dark h6{text-transform:uppercase;letter-spacing:0.5px}html.theme--documenter-dark .hero{background-color:#343c3d}html.theme--documenter-dark a{transition:all 200ms ease}html.theme--documenter-dark .button{transition:all 200ms ease;border-width:1px;color:#fff}html.theme--documenter-dark .button.is-active,html.theme--documenter-dark .button.is-focused,html.theme--documenter-dark .button:active,html.theme--documenter-dark .button:focus{box-shadow:0 0 0 2px rgba(140,155,157,0.5)}html.theme--documenter-dark .button.is-white.is-hovered,html.theme--documenter-dark .button.is-white:hover{background-color:#fff}html.theme--documenter-dark .button.is-white.is-active,html.theme--documenter-dark .button.is-white.is-focused,html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white:focus{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,0.5)}html.theme--documenter-dark .button.is-black.is-hovered,html.theme--documenter-dark .button.is-black:hover{background-color:#1d1d1d}html.theme--documenter-dark .button.is-black.is-active,html.theme--documenter-dark .button.is-black.is-focused,html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black:focus{border-color:#0a0a0a;box-shadow:0 0 0 2px rgba(10,10,10,0.5)}html.theme--documenter-dark .button.is-light.is-hovered,html.theme--documenter-dark .button.is-light:hover{background-color:#fff}html.theme--documenter-dark .button.is-light.is-active,html.theme--documenter-dark .button.is-light.is-focused,html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light:focus{border-color:#ecf0f1;box-shadow:0 0 0 2px rgba(236,240,241,0.5)}html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered,html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover{background-color:#3a4344}html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused,html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus{border-color:#282f2f;box-shadow:0 0 0 2px rgba(40,47,47,0.5)}html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover{background-color:#436d9a}html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink,html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus{border-color:#375a7f;box-shadow:0 0 0 2px rgba(55,90,127,0.5)}html.theme--documenter-dark .button.is-link.is-hovered,html.theme--documenter-dark .button.is-link:hover{background-color:#1fdeb8}html.theme--documenter-dark .button.is-link.is-active,html.theme--documenter-dark .button.is-link.is-focused,html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link:focus{border-color:#1abc9c;box-shadow:0 0 0 2px rgba(26,188,156,0.5)}html.theme--documenter-dark .button.is-info.is-hovered,html.theme--documenter-dark .button.is-info:hover{background-color:#0363a3}html.theme--documenter-dark .button.is-info.is-active,html.theme--documenter-dark .button.is-info.is-focused,html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info:focus{border-color:#024c7d;box-shadow:0 0 0 2px rgba(2,76,125,0.5)}html.theme--documenter-dark .button.is-success.is-hovered,html.theme--documenter-dark .button.is-success:hover{background-color:#00aa48}html.theme--documenter-dark .button.is-success.is-active,html.theme--documenter-dark .button.is-success.is-focused,html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success:focus{border-color:#008438;box-shadow:0 0 0 2px rgba(0,132,56,0.5)}html.theme--documenter-dark .button.is-warning.is-hovered,html.theme--documenter-dark .button.is-warning:hover{background-color:#d39e00}html.theme--documenter-dark .button.is-warning.is-active,html.theme--documenter-dark .button.is-warning.is-focused,html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning:focus{border-color:#ad8100;box-shadow:0 0 0 2px rgba(173,129,0,0.5)}html.theme--documenter-dark .button.is-danger.is-hovered,html.theme--documenter-dark .button.is-danger:hover{background-color:#c12110}html.theme--documenter-dark .button.is-danger.is-active,html.theme--documenter-dark .button.is-danger.is-focused,html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger:focus{border-color:#9e1b0d;box-shadow:0 0 0 2px rgba(158,27,13,0.5)}html.theme--documenter-dark .label{color:#dbdee0}html.theme--documenter-dark .button,html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .select,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea{height:2.5em}html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em}html.theme--documenter-dark .select:after,html.theme--documenter-dark .select select{border-width:1px}html.theme--documenter-dark .control.has-addons .button,html.theme--documenter-dark .control.has-addons .input,html.theme--documenter-dark .control.has-addons #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-addons form.docs-search>input,html.theme--documenter-dark .control.has-addons .select{margin-right:-1px}html.theme--documenter-dark .notification{background-color:#343c3d}html.theme--documenter-dark .card{box-shadow:none;border:1px solid #343c3d;background-color:#282f2f;border-radius:.4em}html.theme--documenter-dark .card .card-image img{border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-header{box-shadow:none;background-color:rgba(18,18,18,0.2);border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-footer{background-color:rgba(18,18,18,0.2)}html.theme--documenter-dark .card .card-footer,html.theme--documenter-dark .card .card-footer-item{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .notification.is-white a:not(.button){color:#0a0a0a;text-decoration:underline}html.theme--documenter-dark .notification.is-black a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-light a:not(.button){color:rgba(0,0,0,0.7);text-decoration:underline}html.theme--documenter-dark .notification.is-dark a:not(.button),html.theme--documenter-dark .content kbd.notification a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-primary a:not(.button),html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-link a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-info a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-success a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-warning a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-danger a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .tag,html.theme--documenter-dark .content kbd,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{border-radius:.4em}html.theme--documenter-dark .menu-list a{transition:all 300ms ease}html.theme--documenter-dark .modal-card-body{background-color:#282f2f}html.theme--documenter-dark .modal-card-foot,html.theme--documenter-dark .modal-card-head{border-color:#343c3d}html.theme--documenter-dark .message-header{font-weight:700;background-color:#343c3d;color:#fff}html.theme--documenter-dark .message-body{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .navbar{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent{background:none}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar .navbar-menu{background-color:#375a7f;border-radius:0 0 .4em .4em}}html.theme--documenter-dark .hero .navbar,html.theme--documenter-dark body>.navbar{border-radius:0}html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous{border-width:1px}html.theme--documenter-dark .panel-block,html.theme--documenter-dark .panel-heading,html.theme--documenter-dark .panel-tabs{border-width:1px}html.theme--documenter-dark .panel-block:first-child,html.theme--documenter-dark .panel-heading:first-child,html.theme--documenter-dark .panel-tabs:first-child{border-top-width:1px}html.theme--documenter-dark .panel-heading{font-weight:700}html.theme--documenter-dark .panel-tabs a{border-width:1px;margin-bottom:-1px}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#17a689}html.theme--documenter-dark .panel-block:hover{color:#1dd2af}html.theme--documenter-dark .panel-block:hover .panel-icon{color:#1dd2af}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#17a689}html.theme--documenter-dark .tabs a{border-bottom-width:1px;margin-bottom:-1px}html.theme--documenter-dark .tabs ul{border-bottom-width:1px}html.theme--documenter-dark .tabs.is-boxed a{border-width:1px}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#1f2424}html.theme--documenter-dark .tabs.is-toggle li a{border-width:1px;margin-bottom:0}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .hero.is-white .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-black .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-light .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-dark .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .content kbd.hero .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-primary .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-link .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-info .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-success .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-warning .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-danger .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark h1 .docs-heading-anchor,html.theme--documenter-dark h1 .docs-heading-anchor:hover,html.theme--documenter-dark h1 .docs-heading-anchor:visited,html.theme--documenter-dark h2 .docs-heading-anchor,html.theme--documenter-dark h2 .docs-heading-anchor:hover,html.theme--documenter-dark h2 .docs-heading-anchor:visited,html.theme--documenter-dark h3 .docs-heading-anchor,html.theme--documenter-dark h3 .docs-heading-anchor:hover,html.theme--documenter-dark h3 .docs-heading-anchor:visited,html.theme--documenter-dark h4 .docs-heading-anchor,html.theme--documenter-dark h4 .docs-heading-anchor:hover,html.theme--documenter-dark h4 .docs-heading-anchor:visited,html.theme--documenter-dark h5 .docs-heading-anchor,html.theme--documenter-dark h5 .docs-heading-anchor:hover,html.theme--documenter-dark h5 .docs-heading-anchor:visited,html.theme--documenter-dark h6 .docs-heading-anchor,html.theme--documenter-dark h6 .docs-heading-anchor:hover,html.theme--documenter-dark h6 .docs-heading-anchor:visited{color:#f2f2f2}html.theme--documenter-dark h1 .docs-heading-anchor-permalink,html.theme--documenter-dark h2 .docs-heading-anchor-permalink,html.theme--documenter-dark h3 .docs-heading-anchor-permalink,html.theme--documenter-dark h4 .docs-heading-anchor-permalink,html.theme--documenter-dark h5 .docs-heading-anchor-permalink,html.theme--documenter-dark h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--documenter-dark h1 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h2 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h3 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h4 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h5 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--documenter-dark h1:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h2:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h3:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h4:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h5:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--documenter-dark .docs-light-only{display:none !important}html.theme--documenter-dark pre{position:relative;overflow:hidden}html.theme--documenter-dark pre code,html.theme--documenter-dark pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--documenter-dark pre code:first-of-type,html.theme--documenter-dark pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--documenter-dark pre code:last-of-type,html.theme--documenter-dark pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--documenter-dark pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#fff;cursor:pointer;text-align:center}html.theme--documenter-dark pre .copy-button:focus,html.theme--documenter-dark pre .copy-button:hover{opacity:1;background:rgba(255,255,255,0.1);color:#1abc9c}html.theme--documenter-dark pre .copy-button.success{color:#259a12;opacity:1}html.theme--documenter-dark pre .copy-button.error{color:#cb3c33;opacity:1}html.theme--documenter-dark pre:hover .copy-button{opacity:1}html.theme--documenter-dark .admonition{background-color:#282f2f;border-style:solid;border-width:1px;border-color:#5e6d6f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .admonition strong{color:currentColor}html.theme--documenter-dark .admonition.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--documenter-dark .admonition.is-medium{font-size:1.25rem}html.theme--documenter-dark .admonition.is-large{font-size:1.5rem}html.theme--documenter-dark .admonition.is-default{background-color:#282f2f;border-color:#5e6d6f}html.theme--documenter-dark .admonition.is-default>.admonition-header{background-color:#5e6d6f;color:#fff}html.theme--documenter-dark .admonition.is-default>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-info{background-color:#282f2f;border-color:#024c7d}html.theme--documenter-dark .admonition.is-info>.admonition-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .admonition.is-info>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-success{background-color:#282f2f;border-color:#008438}html.theme--documenter-dark .admonition.is-success>.admonition-header{background-color:#008438;color:#fff}html.theme--documenter-dark .admonition.is-success>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-warning{background-color:#282f2f;border-color:#ad8100}html.theme--documenter-dark .admonition.is-warning>.admonition-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .admonition.is-warning>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-danger{background-color:#282f2f;border-color:#9e1b0d}html.theme--documenter-dark .admonition.is-danger>.admonition-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .admonition.is-danger>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-compat{background-color:#282f2f;border-color:#137886}html.theme--documenter-dark .admonition.is-compat>.admonition-header{background-color:#137886;color:#fff}html.theme--documenter-dark .admonition.is-compat>.admonition-body{color:#fff}html.theme--documenter-dark .admonition-header{color:#fff;background-color:#5e6d6f;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--documenter-dark .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--documenter-dark details.admonition.is-details>.admonition-header{list-style:none}html.theme--documenter-dark details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--documenter-dark details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--documenter-dark .admonition-body{color:#fff;padding:0.5rem .75rem}html.theme--documenter-dark .admonition-body pre{background-color:#282f2f}html.theme--documenter-dark .admonition-body code{background-color:rgba(255,255,255,0.05)}html.theme--documenter-dark .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #5e6d6f;box-shadow:none;max-width:100%}html.theme--documenter-dark .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#282f2f;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>header code{background-color:transparent}html.theme--documenter-dark .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--documenter-dark .docstring>header .docstring-binding{margin-right:0.3em}html.theme--documenter-dark .docstring>header .docstring-category{margin-left:0.3em}html.theme--documenter-dark .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>section:last-child{border-bottom:none}html.theme--documenter-dark .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--documenter-dark .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--documenter-dark .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--documenter-dark .documenter-example-output{background-color:#1f2424}html.theme--documenter-dark .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#282f2f;color:#fff;border-bottom:3px solid #9e1b0d;padding:10px 35px;text-align:center;font-size:15px}html.theme--documenter-dark .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--documenter-dark .outdated-warning-overlay a{color:#1abc9c}html.theme--documenter-dark .outdated-warning-overlay a:hover{color:#1dd2af}html.theme--documenter-dark .content pre{border:1px solid #5e6d6f}html.theme--documenter-dark .content code{font-weight:inherit}html.theme--documenter-dark .content a code{color:#1abc9c}html.theme--documenter-dark .content h1 code,html.theme--documenter-dark .content h2 code,html.theme--documenter-dark .content h3 code,html.theme--documenter-dark .content h4 code,html.theme--documenter-dark .content h5 code,html.theme--documenter-dark .content h6 code{color:#f2f2f2}html.theme--documenter-dark .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--documenter-dark .content blockquote>ul:first-child,html.theme--documenter-dark .content blockquote>ol:first-child,html.theme--documenter-dark .content .admonition-body>ul:first-child,html.theme--documenter-dark .content .admonition-body>ol:first-child{margin-top:0}html.theme--documenter-dark pre,html.theme--documenter-dark code{font-variant-ligatures:no-contextual}html.theme--documenter-dark .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb a.is-disabled,html.theme--documenter-dark .breadcrumb a.is-disabled:hover{color:#f2f2f2}html.theme--documenter-dark .hljs{background:initial !important}html.theme--documenter-dark .katex .katex-mathml{top:0;right:0}html.theme--documenter-dark .katex-display,html.theme--documenter-dark mjx-container,html.theme--documenter-dark .MathJax_Display{margin:0.5em 0 !important}html.theme--documenter-dark html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--documenter-dark li.no-marker{list-style:none}html.theme--documenter-dark #documenter .docs-main>article{overflow-wrap:break-word}html.theme--documenter-dark #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main{width:100%}html.theme--documenter-dark #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-main>header,html.theme--documenter-dark #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar{background-color:#1f2424;border-bottom:1px solid #5e6d6f;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--documenter-dark #documenter .docs-main section.footnotes{border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-main section.footnotes li .tag:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--documenter-dark .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--documenter-dark #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #5e6d6f;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--documenter-dark #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--documenter-dark #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--documenter-dark #documenter .docs-sidebar{display:flex;flex-direction:column;color:#fff;background-color:#282f2f;border-right:1px solid #5e6d6f;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--documenter-dark #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar{left:0;top:0}}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a,html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a:hover{color:#fff}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #5e6d6f;display:none;padding:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #5e6d6f;padding-bottom:1.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#fff;background:#282f2f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#fff;background-color:#32393a}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #5e6d6f;border-bottom:1px solid #5e6d6f;background-color:#1f2424}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#1f2424;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#32393a;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--documenter-dark #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}html.theme--documenter-dark kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--documenter-dark .search-min-width-50{min-width:50%}html.theme--documenter-dark .search-min-height-100{min-height:100%}html.theme--documenter-dark .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--documenter-dark .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--documenter-dark .search-result-link:hover,html.theme--documenter-dark .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--documenter-dark .search-result-link .property-search-result-badge,html.theme--documenter-dark .search-result-link .search-filter{transition:all 300ms}html.theme--documenter-dark .property-search-result-badge,html.theme--documenter-dark .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--documenter-dark .search-result-link:hover .property-search-result-badge,html.theme--documenter-dark .search-result-link:hover .search-filter,html.theme--documenter-dark .search-result-link:focus .property-search-result-badge,html.theme--documenter-dark .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--documenter-dark .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--documenter-dark .search-filter:hover,html.theme--documenter-dark .search-filter:focus{color:#333}html.theme--documenter-dark .search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}html.theme--documenter-dark .search-filter-selected:hover,html.theme--documenter-dark .search-filter-selected:focus{color:#f5f5f5}html.theme--documenter-dark .search-result-highlight{background-color:#ffdd57;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .search-result-title{width:85%;color:#f5f5f5}html.theme--documenter-dark .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--documenter-dark .w-100{width:100%}html.theme--documenter-dark .gap-2{gap:0.5rem}html.theme--documenter-dark .gap-4{gap:1rem}html.theme--documenter-dark .gap-8{gap:2rem}html.theme--documenter-dark{background-color:#1f2424;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark .ansi span.sgr1{font-weight:bolder}html.theme--documenter-dark .ansi span.sgr2{font-weight:lighter}html.theme--documenter-dark .ansi span.sgr3{font-style:italic}html.theme--documenter-dark .ansi span.sgr4{text-decoration:underline}html.theme--documenter-dark .ansi span.sgr7{color:#1f2424;background-color:#fff}html.theme--documenter-dark .ansi span.sgr8{color:transparent}html.theme--documenter-dark .ansi span.sgr8 span{color:transparent}html.theme--documenter-dark .ansi span.sgr9{text-decoration:line-through}html.theme--documenter-dark .ansi span.sgr30{color:#242424}html.theme--documenter-dark .ansi span.sgr31{color:#f6705f}html.theme--documenter-dark .ansi span.sgr32{color:#4fb43a}html.theme--documenter-dark .ansi span.sgr33{color:#f4c72f}html.theme--documenter-dark .ansi span.sgr34{color:#7587f0}html.theme--documenter-dark .ansi span.sgr35{color:#bc89d3}html.theme--documenter-dark .ansi span.sgr36{color:#49b6ca}html.theme--documenter-dark .ansi span.sgr37{color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr40{background-color:#242424}html.theme--documenter-dark .ansi span.sgr41{background-color:#f6705f}html.theme--documenter-dark .ansi span.sgr42{background-color:#4fb43a}html.theme--documenter-dark .ansi span.sgr43{background-color:#f4c72f}html.theme--documenter-dark .ansi span.sgr44{background-color:#7587f0}html.theme--documenter-dark .ansi span.sgr45{background-color:#bc89d3}html.theme--documenter-dark .ansi span.sgr46{background-color:#49b6ca}html.theme--documenter-dark .ansi span.sgr47{background-color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr90{color:#92a0a2}html.theme--documenter-dark .ansi span.sgr91{color:#ff8674}html.theme--documenter-dark .ansi span.sgr92{color:#79d462}html.theme--documenter-dark .ansi span.sgr93{color:#ffe76b}html.theme--documenter-dark .ansi span.sgr94{color:#8a98ff}html.theme--documenter-dark .ansi span.sgr95{color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr96{color:#6bc8db}html.theme--documenter-dark .ansi span.sgr97{color:#ecf0f1}html.theme--documenter-dark .ansi span.sgr100{background-color:#92a0a2}html.theme--documenter-dark .ansi span.sgr101{background-color:#ff8674}html.theme--documenter-dark .ansi span.sgr102{background-color:#79d462}html.theme--documenter-dark .ansi span.sgr103{background-color:#ffe76b}html.theme--documenter-dark .ansi span.sgr104{background-color:#8a98ff}html.theme--documenter-dark .ansi span.sgr105{background-color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr106{background-color:#6bc8db}html.theme--documenter-dark .ansi span.sgr107{background-color:#ecf0f1}html.theme--documenter-dark code.language-julia-repl>span.hljs-meta{color:#4fb43a;font-weight:bolder}html.theme--documenter-dark .hljs{background:#2b2b2b;color:#f8f8f2}html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-quote{color:#d4d0ab}html.theme--documenter-dark .hljs-variable,html.theme--documenter-dark .hljs-template-variable,html.theme--documenter-dark .hljs-tag,html.theme--documenter-dark .hljs-name,html.theme--documenter-dark .hljs-selector-id,html.theme--documenter-dark .hljs-selector-class,html.theme--documenter-dark .hljs-regexp,html.theme--documenter-dark .hljs-deletion{color:#ffa07a}html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-link{color:#f5ab35}html.theme--documenter-dark .hljs-attribute{color:#ffd700}html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-addition{color:#abe338}html.theme--documenter-dark .hljs-title,html.theme--documenter-dark .hljs-section{color:#00e0e0}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{color:#dcc6e0}html.theme--documenter-dark .hljs-emphasis{font-style:italic}html.theme--documenter-dark .hljs-strong{font-weight:bold}@media screen and (-ms-high-contrast: active){html.theme--documenter-dark .hljs-addition,html.theme--documenter-dark .hljs-attribute,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-link,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-quote{color:highlight}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{font-weight:bold}}html.theme--documenter-dark .hljs-subst{color:#f8f8f2} diff --git a/previews/PR2274/assets/themes/documenter-light.css b/previews/PR2274/assets/themes/documenter-light.css new file mode 100644 index 0000000000..60a317a4c5 --- /dev/null +++ b/previews/PR2274/assets/themes/documenter-light.css @@ -0,0 +1,9 @@ +.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.file-cta,.file-name,.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input,.button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:4px;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus,.pagination-ellipsis:focus,.file-cta:focus,.file-name:focus,.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.button:focus,.is-focused.pagination-previous,.is-focused.pagination-next,.is-focused.pagination-link,.is-focused.pagination-ellipsis,.is-focused.file-cta,.is-focused.file-name,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-focused.button,.pagination-previous:active,.pagination-next:active,.pagination-link:active,.pagination-ellipsis:active,.file-cta:active,.file-name:active,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.button:active,.is-active.pagination-previous,.is-active.pagination-next,.is-active.pagination-link,.is-active.pagination-ellipsis,.is-active.file-cta,.is-active.file-name,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.is-active.button{outline:none}.pagination-previous[disabled],.pagination-next[disabled],.pagination-link[disabled],.pagination-ellipsis[disabled],.file-cta[disabled],.file-name[disabled],.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],.button[disabled],fieldset[disabled] .pagination-previous,fieldset[disabled] .pagination-next,fieldset[disabled] .pagination-link,fieldset[disabled] .pagination-ellipsis,fieldset[disabled] .file-cta,fieldset[disabled] .file-name,fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] .button{cursor:not-allowed}.tabs,.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.breadcrumb,.file,.button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}.admonition:not(:last-child),.tabs:not(:last-child),.pagination:not(:last-child),.message:not(:last-child),.level:not(:last-child),.breadcrumb:not(:last-child),.block:not(:last-child),.title:not(:last-child),.subtitle:not(:last-child),.table-container:not(:last-child),.table:not(:last-child),.progress:not(:last-child),.notification:not(:last-child),.content:not(:last-child),.box:not(:last-child){margin-bottom:1.5rem}.modal-close,.delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}.modal-close::before,.delete::before,.modal-close::after,.delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.modal-close::before,.delete::before{height:2px;width:50%}.modal-close::after,.delete::after{height:50%;width:2px}.modal-close:hover,.delete:hover,.modal-close:focus,.delete:focus{background-color:rgba(10,10,10,0.3)}.modal-close:active,.delete:active{background-color:rgba(10,10,10,0.4)}.is-small.modal-close,#documenter .docs-sidebar form.docs-search>input.modal-close,.is-small.delete,#documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.is-medium.modal-close,.is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.is-large.modal-close,.is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.control.is-loading::after,.select.is-loading::after,.loader,.button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdbdb;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.hero-video,.modal-background,.modal,.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}.navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#363636 !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#1c1c1c !important}.has-background-dark{background-color:#363636 !important}.has-text-primary{color:#4eb5de !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#27a1d2 !important}.has-background-primary{background-color:#4eb5de !important}.has-text-primary-light{color:#eef8fc !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#c3e6f4 !important}.has-background-primary-light{background-color:#eef8fc !important}.has-text-primary-dark{color:#1a6d8e !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#228eb9 !important}.has-background-primary-dark{background-color:#1a6d8e !important}.has-text-link{color:#2e63b8 !important}a.has-text-link:hover,a.has-text-link:focus{color:#244d8f !important}.has-background-link{background-color:#2e63b8 !important}.has-text-link-light{color:#eff3fb !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c6d6f1 !important}.has-background-link-light{background-color:#eff3fb !important}.has-text-link-dark{color:#3169c4 !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#5485d4 !important}.has-background-link-dark{background-color:#3169c4 !important}.has-text-info{color:#209cee !important}a.has-text-info:hover,a.has-text-info:focus{color:#1081cb !important}.has-background-info{background-color:#209cee !important}.has-text-info-light{color:#ecf7fe !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#bde2fa !important}.has-background-info-light{background-color:#ecf7fe !important}.has-text-info-dark{color:#0e72b4 !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#1190e3 !important}.has-background-info-dark{background-color:#0e72b4 !important}.has-text-success{color:#22c35b !important}a.has-text-success:hover,a.has-text-success:focus{color:#1a9847 !important}.has-background-success{background-color:#22c35b !important}.has-text-success-light{color:#eefcf3 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#c2f4d4 !important}.has-background-success-light{background-color:#eefcf3 !important}.has-text-success-dark{color:#198f43 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#21bb57 !important}.has-background-success-dark{background-color:#198f43 !important}.has-text-warning{color:#ffdd57 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#ffd324 !important}.has-background-warning{background-color:#ffdd57 !important}.has-text-warning-light{color:#fffbeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#fff1b8 !important}.has-background-warning-light{background-color:#fffbeb !important}.has-text-warning-dark{color:#947600 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#c79f00 !important}.has-background-warning-dark{background-color:#947600 !important}.has-text-danger{color:#da0b00 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#a70800 !important}.has-background-danger{background-color:#da0b00 !important}.has-text-danger-light{color:#ffeceb !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#ffbbb8 !important}.has-background-danger-light{background-color:#ffeceb !important}.has-text-danger-dark{color:#f50c00 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#ff3429 !important}.has-background-danger-dark{background-color:#f50c00 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#363636 !important}.has-background-grey-darker{background-color:#363636 !important}.has-text-grey-dark{color:#4a4a4a !important}.has-background-grey-dark{background-color:#4a4a4a !important}.has-text-grey{color:#6b6b6b !important}.has-background-grey{background-color:#6b6b6b !important}.has-text-grey-light{color:#b5b5b5 !important}.has-background-grey-light{background-color:#b5b5b5 !important}.has-text-grey-lighter{color:#dbdbdb !important}.has-background-grey-lighter{background-color:#dbdbdb !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,.docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,optgroup,select,textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}body{color:#222;font-size:1em;font-weight:400;line-height:1.5}a{color:#2e63b8;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:rgba(0,0,0,0.05);color:#000;font-size:.875em;font-weight:normal;padding:.1em}hr{background-color:#f5f5f5;border:none;display:block;height:2px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type="checkbox"],input[type="radio"]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#222;font-weight:700}fieldset{border:none}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#222;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{vertical-align:top}table td:not([align]),table th:not([align]){text-align:inherit}table th{color:#222}@keyframes spinAround{from{transform:rotate(0deg)}to{transform:rotate(359deg)}}.box{background-color:#fff;border-radius:6px;box-shadow:#bbb;color:#222;display:block;padding:1.25rem}a.box:hover,a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #2e63b8}a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #2e63b8}.button{background-color:#fff;border-color:#dbdbdb;border-width:1px;color:#222;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}.button strong{color:inherit}.button .icon,.button .icon.is-small,.button #documenter .docs-sidebar form.docs-search>input.icon,#documenter .docs-sidebar .button form.docs-search>input.icon,.button .icon.is-medium,.button .icon.is-large{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}.button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}.button:hover,.button.is-hovered{border-color:#b5b5b5;color:#363636}.button:focus,.button.is-focused{border-color:#3c5dcd;color:#363636}.button:focus:not(:active),.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button:active,.button.is-active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#222;text-decoration:underline}.button.is-text:hover,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text.is-focused{background-color:#f5f5f5;color:#222}.button.is-text:active,.button.is-text.is-active{background-color:#e8e8e8;color:#222}.button.is-text[disabled],fieldset[disabled] .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}.button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#2e63b8;text-decoration:none}.button.is-ghost:hover,.button.is-ghost.is-hovered{color:#2e63b8;text-decoration:underline}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white:hover,.button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white:focus,.button.is-white.is-focused{border-color:transparent;color:#0a0a0a}.button.is-white:focus:not(:active),.button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.button.is-white:active,.button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled],fieldset[disabled] .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted:hover,.button.is-white.is-inverted.is-hovered{background-color:#000}.button.is-white.is-inverted[disabled],fieldset[disabled] .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}.button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined:hover,.button.is-white.is-outlined.is-hovered,.button.is-white.is-outlined:focus,.button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-outlined.is-loading:hover::after,.button.is-white.is-outlined.is-loading.is-hovered::after,.button.is-white.is-outlined.is-loading:focus::after,.button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined[disabled],fieldset[disabled] .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined:hover,.button.is-white.is-inverted.is-outlined.is-hovered,.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined.is-loading:hover::after,.button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-white.is-inverted.is-outlined.is-loading:focus::after,.button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black:hover,.button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}.button.is-black:focus,.button.is-black.is-focused{border-color:transparent;color:#fff}.button.is-black:focus:not(:active),.button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.button.is-black:active,.button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled],fieldset[disabled] .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted:hover,.button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-black.is-inverted[disabled],fieldset[disabled] .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined:hover,.button.is-black.is-outlined.is-hovered,.button.is-black.is-outlined:focus,.button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-outlined.is-loading:hover::after,.button.is-black.is-outlined.is-loading.is-hovered::after,.button.is-black.is-outlined.is-loading:focus::after,.button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined[disabled],fieldset[disabled] .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined:hover,.button.is-black.is-inverted.is-outlined.is-hovered,.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined.is-loading:hover::after,.button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-black.is-inverted.is-outlined.is-loading:focus::after,.button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:hover,.button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus,.button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus:not(:active),.button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.button.is-light:active,.button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light[disabled],fieldset[disabled] .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}.button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted:hover,.button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-light.is-inverted[disabled],fieldset[disabled] .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined:hover,.button.is-light.is-outlined.is-hovered,.button.is-light.is-outlined:focus,.button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-outlined.is-loading:hover::after,.button.is-light.is-outlined.is-loading.is-hovered::after,.button.is-light.is-outlined.is-loading:focus::after,.button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined[disabled],fieldset[disabled] .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-light.is-inverted.is-outlined:hover,.button.is-light.is-inverted.is-outlined.is-hovered,.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted.is-outlined.is-loading:hover::after,.button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-light.is-inverted.is-outlined.is-loading:focus::after,.button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-dark,.content kbd.button{background-color:#363636;border-color:transparent;color:#fff}.button.is-dark:hover,.content kbd.button:hover,.button.is-dark.is-hovered,.content kbd.button.is-hovered{background-color:#2f2f2f;border-color:transparent;color:#fff}.button.is-dark:focus,.content kbd.button:focus,.button.is-dark.is-focused,.content kbd.button.is-focused{border-color:transparent;color:#fff}.button.is-dark:focus:not(:active),.content kbd.button:focus:not(:active),.button.is-dark.is-focused:not(:active),.content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.button.is-dark:active,.content kbd.button:active,.button.is-dark.is-active,.content kbd.button.is-active{background-color:#292929;border-color:transparent;color:#fff}.button.is-dark[disabled],.content kbd.button[disabled],fieldset[disabled] .button.is-dark,fieldset[disabled] .content kbd.button,.content fieldset[disabled] kbd.button{background-color:#363636;border-color:#363636;box-shadow:none}.button.is-dark.is-inverted,.content kbd.button.is-inverted{background-color:#fff;color:#363636}.button.is-dark.is-inverted:hover,.content kbd.button.is-inverted:hover,.button.is-dark.is-inverted.is-hovered,.content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-dark.is-inverted[disabled],.content kbd.button.is-inverted[disabled],fieldset[disabled] .button.is-dark.is-inverted,fieldset[disabled] .content kbd.button.is-inverted,.content fieldset[disabled] kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#363636}.button.is-dark.is-loading::after,.content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined,.content kbd.button.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined:hover,.content kbd.button.is-outlined:hover,.button.is-dark.is-outlined.is-hovered,.content kbd.button.is-outlined.is-hovered,.button.is-dark.is-outlined:focus,.content kbd.button.is-outlined:focus,.button.is-dark.is-outlined.is-focused,.content kbd.button.is-outlined.is-focused{background-color:#363636;border-color:#363636;color:#fff}.button.is-dark.is-outlined.is-loading::after,.content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-outlined.is-loading:hover::after,.content kbd.button.is-outlined.is-loading:hover::after,.button.is-dark.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-outlined.is-loading:focus::after,.content kbd.button.is-outlined.is-loading:focus::after,.button.is-dark.is-outlined.is-loading.is-focused::after,.content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined[disabled],.content kbd.button.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-outlined,fieldset[disabled] .content kbd.button.is-outlined,.content fieldset[disabled] kbd.button.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined,.content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-dark.is-inverted.is-outlined:hover,.content kbd.button.is-inverted.is-outlined:hover,.button.is-dark.is-inverted.is-outlined.is-hovered,.content kbd.button.is-inverted.is-outlined.is-hovered,.button.is-dark.is-inverted.is-outlined:focus,.content kbd.button.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined.is-focused,.content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-outlined.is-loading:hover::after,.content kbd.button.is-inverted.is-outlined.is-loading:hover::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-inverted.is-outlined.is-loading:focus::after,.content kbd.button.is-inverted.is-outlined.is-loading:focus::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-inverted.is-outlined[disabled],.content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-inverted.is-outlined,fieldset[disabled] .content kbd.button.is-inverted.is-outlined,.content fieldset[disabled] kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary,.docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:transparent;color:#fff}.button.is-primary:hover,.docstring>section>a.button.docs-sourcelink:hover,.button.is-primary.is-hovered,.docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#43b1dc;border-color:transparent;color:#fff}.button.is-primary:focus,.docstring>section>a.button.docs-sourcelink:focus,.button.is-primary.is-focused,.docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}.button.is-primary:focus:not(:active),.docstring>section>a.button.docs-sourcelink:focus:not(:active),.button.is-primary.is-focused:not(:active),.docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.button.is-primary:active,.docstring>section>a.button.docs-sourcelink:active,.button.is-primary.is-active,.docstring>section>a.button.is-active.docs-sourcelink{background-color:#39acda;border-color:transparent;color:#fff}.button.is-primary[disabled],.docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary,fieldset[disabled] .docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;box-shadow:none}.button.is-primary.is-inverted,.docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted:hover,.docstring>section>a.button.is-inverted.docs-sourcelink:hover,.button.is-primary.is-inverted.is-hovered,.docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled],.docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted,fieldset[disabled] .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#4eb5de}.button.is-primary.is-loading::after,.docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined,.docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;color:#4eb5de}.button.is-primary.is-outlined:hover,.docstring>section>a.button.is-outlined.docs-sourcelink:hover,.button.is-primary.is-outlined.is-hovered,.docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-outlined:focus,.docstring>section>a.button.is-outlined.docs-sourcelink:focus,.button.is-primary.is-outlined.is-focused,.docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.button.is-primary.is-outlined.is-loading::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined[disabled],.docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-outlined,fieldset[disabled] .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;box-shadow:none;color:#4eb5de}.button.is-primary.is-inverted.is-outlined,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined:hover,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,.button.is-primary.is-inverted.is-outlined.is-hovered,.docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-inverted.is-outlined:focus,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,.button.is-primary.is-inverted.is-outlined.is-focused,.docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-inverted.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-inverted.is-outlined[disabled],.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted.is-outlined,fieldset[disabled] .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary.is-light,.docstring>section>a.button.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.button.is-primary.is-light:hover,.docstring>section>a.button.is-light.docs-sourcelink:hover,.button.is-primary.is-light.is-hovered,.docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e3f3fa;border-color:transparent;color:#1a6d8e}.button.is-primary.is-light:active,.docstring>section>a.button.is-light.docs-sourcelink:active,.button.is-primary.is-light.is-active,.docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d8eff8;border-color:transparent;color:#1a6d8e}.button.is-link{background-color:#2e63b8;border-color:transparent;color:#fff}.button.is-link:hover,.button.is-link.is-hovered{background-color:#2b5eae;border-color:transparent;color:#fff}.button.is-link:focus,.button.is-link.is-focused{border-color:transparent;color:#fff}.button.is-link:focus:not(:active),.button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button.is-link:active,.button.is-link.is-active{background-color:#2958a4;border-color:transparent;color:#fff}.button.is-link[disabled],fieldset[disabled] .button.is-link{background-color:#2e63b8;border-color:#2e63b8;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted:hover,.button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-link.is-inverted[disabled],fieldset[disabled] .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#2e63b8}.button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;color:#2e63b8}.button.is-link.is-outlined:hover,.button.is-link.is-outlined.is-hovered,.button.is-link.is-outlined:focus,.button.is-link.is-outlined.is-focused{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-outlined.is-loading:hover::after,.button.is-link.is-outlined.is-loading.is-hovered::after,.button.is-link.is-outlined.is-loading:focus::after,.button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined[disabled],fieldset[disabled] .button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;box-shadow:none;color:#2e63b8}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined:hover,.button.is-link.is-inverted.is-outlined.is-hovered,.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted.is-outlined.is-loading:hover::after,.button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-link.is-inverted.is-outlined.is-loading:focus::after,.button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-link.is-light{background-color:#eff3fb;color:#3169c4}.button.is-link.is-light:hover,.button.is-link.is-light.is-hovered{background-color:#e4ecf8;border-color:transparent;color:#3169c4}.button.is-link.is-light:active,.button.is-link.is-light.is-active{background-color:#dae5f6;border-color:transparent;color:#3169c4}.button.is-info{background-color:#209cee;border-color:transparent;color:#fff}.button.is-info:hover,.button.is-info.is-hovered{background-color:#1497ed;border-color:transparent;color:#fff}.button.is-info:focus,.button.is-info.is-focused{border-color:transparent;color:#fff}.button.is-info:focus:not(:active),.button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.button.is-info:active,.button.is-info.is-active{background-color:#1190e3;border-color:transparent;color:#fff}.button.is-info[disabled],fieldset[disabled] .button.is-info{background-color:#209cee;border-color:#209cee;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#209cee}.button.is-info.is-inverted:hover,.button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-info.is-inverted[disabled],fieldset[disabled] .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#209cee}.button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined{background-color:transparent;border-color:#209cee;color:#209cee}.button.is-info.is-outlined:hover,.button.is-info.is-outlined.is-hovered,.button.is-info.is-outlined:focus,.button.is-info.is-outlined.is-focused{background-color:#209cee;border-color:#209cee;color:#fff}.button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-outlined.is-loading:hover::after,.button.is-info.is-outlined.is-loading.is-hovered::after,.button.is-info.is-outlined.is-loading:focus::after,.button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined[disabled],fieldset[disabled] .button.is-info.is-outlined{background-color:transparent;border-color:#209cee;box-shadow:none;color:#209cee}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined:hover,.button.is-info.is-inverted.is-outlined.is-hovered,.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#209cee}.button.is-info.is-inverted.is-outlined.is-loading:hover::after,.button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-info.is-inverted.is-outlined.is-loading:focus::after,.button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-info.is-light{background-color:#ecf7fe;color:#0e72b4}.button.is-info.is-light:hover,.button.is-info.is-light.is-hovered{background-color:#e0f1fd;border-color:transparent;color:#0e72b4}.button.is-info.is-light:active,.button.is-info.is-light.is-active{background-color:#d4ecfc;border-color:transparent;color:#0e72b4}.button.is-success{background-color:#22c35b;border-color:transparent;color:#fff}.button.is-success:hover,.button.is-success.is-hovered{background-color:#20b856;border-color:transparent;color:#fff}.button.is-success:focus,.button.is-success.is-focused{border-color:transparent;color:#fff}.button.is-success:focus:not(:active),.button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.button.is-success:active,.button.is-success.is-active{background-color:#1ead51;border-color:transparent;color:#fff}.button.is-success[disabled],fieldset[disabled] .button.is-success{background-color:#22c35b;border-color:#22c35b;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#22c35b}.button.is-success.is-inverted:hover,.button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-success.is-inverted[disabled],fieldset[disabled] .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#22c35b}.button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;color:#22c35b}.button.is-success.is-outlined:hover,.button.is-success.is-outlined.is-hovered,.button.is-success.is-outlined:focus,.button.is-success.is-outlined.is-focused{background-color:#22c35b;border-color:#22c35b;color:#fff}.button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-outlined.is-loading:hover::after,.button.is-success.is-outlined.is-loading.is-hovered::after,.button.is-success.is-outlined.is-loading:focus::after,.button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined[disabled],fieldset[disabled] .button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;box-shadow:none;color:#22c35b}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined:hover,.button.is-success.is-inverted.is-outlined.is-hovered,.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#22c35b}.button.is-success.is-inverted.is-outlined.is-loading:hover::after,.button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-success.is-inverted.is-outlined.is-loading:focus::after,.button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-success.is-light{background-color:#eefcf3;color:#198f43}.button.is-success.is-light:hover,.button.is-success.is-light.is-hovered{background-color:#e3faeb;border-color:transparent;color:#198f43}.button.is-success.is-light:active,.button.is-success.is-light.is-active{background-color:#d8f8e3;border-color:transparent;color:#198f43}.button.is-warning{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:hover,.button.is-warning.is-hovered{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus,.button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus:not(:active),.button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.button.is-warning:active,.button.is-warning.is-active{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning[disabled],fieldset[disabled] .button.is-warning{background-color:#ffdd57;border-color:#ffdd57;box-shadow:none}.button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted:hover,.button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted[disabled],fieldset[disabled] .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ffdd57}.button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;color:#ffdd57}.button.is-warning.is-outlined:hover,.button.is-warning.is-outlined.is-hovered,.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined.is-focused{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-outlined.is-loading:hover::after,.button.is-warning.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-outlined.is-loading:focus::after,.button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;box-shadow:none;color:#ffdd57}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted.is-outlined:hover,.button.is-warning.is-inverted.is-outlined.is-hovered,.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted.is-outlined.is-loading:hover::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-inverted.is-outlined.is-loading:focus::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-warning.is-light{background-color:#fffbeb;color:#947600}.button.is-warning.is-light:hover,.button.is-warning.is-light.is-hovered{background-color:#fff8de;border-color:transparent;color:#947600}.button.is-warning.is-light:active,.button.is-warning.is-light.is-active{background-color:#fff6d1;border-color:transparent;color:#947600}.button.is-danger{background-color:#da0b00;border-color:transparent;color:#fff}.button.is-danger:hover,.button.is-danger.is-hovered{background-color:#cd0a00;border-color:transparent;color:#fff}.button.is-danger:focus,.button.is-danger.is-focused{border-color:transparent;color:#fff}.button.is-danger:focus:not(:active),.button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.button.is-danger:active,.button.is-danger.is-active{background-color:#c10a00;border-color:transparent;color:#fff}.button.is-danger[disabled],fieldset[disabled] .button.is-danger{background-color:#da0b00;border-color:#da0b00;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted:hover,.button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled],fieldset[disabled] .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#da0b00}.button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;color:#da0b00}.button.is-danger.is-outlined:hover,.button.is-danger.is-outlined.is-hovered,.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined.is-focused{background-color:#da0b00;border-color:#da0b00;color:#fff}.button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-outlined.is-loading:hover::after,.button.is-danger.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-outlined.is-loading:focus::after,.button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;box-shadow:none;color:#da0b00}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined:hover,.button.is-danger.is-inverted.is-outlined.is-hovered,.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted.is-outlined.is-loading:hover::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-inverted.is-outlined.is-loading:focus::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-danger.is-light{background-color:#ffeceb;color:#f50c00}.button.is-danger.is-light:hover,.button.is-danger.is-light.is-hovered{background-color:#ffe0de;border-color:transparent;color:#f50c00}.button.is-danger.is-light:active,.button.is-danger.is-light.is-active{background-color:#ffd3d1;border-color:transparent;color:#f50c00}.button.is-small,#documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}.button.is-small:not(.is-rounded),#documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:2px}.button.is-normal{font-size:1rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled],fieldset[disabled] .button{background-color:#fff;border-color:#dbdbdb;box-shadow:none;opacity:.5}.button.is-fullwidth{display:flex;width:100%}.button.is-loading{color:transparent !important;pointer-events:none}.button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#6b6b6b;box-shadow:none;pointer-events:none}.button.is-rounded,#documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}.buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.buttons .button{margin-bottom:0.5rem}.buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}.buttons:last-child{margin-bottom:-0.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:2px}.buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}.buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.buttons.has-addons .button:last-child{margin-right:0}.buttons.has-addons .button:hover,.buttons.has-addons .button.is-hovered{z-index:2}.buttons.has-addons .button:focus,.buttons.has-addons .button.is-focused,.buttons.has-addons .button:active,.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-selected{z-index:3}.buttons.has-addons .button:focus:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-selected:hover{z-index:4}.buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}.buttons.is-centered{justify-content:center}.buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}.buttons.is-right{justify-content:flex-end}.buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.65625rem}.button.is-responsive.is-medium{font-size:.75rem}.button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.75rem}.button.is-responsive.is-medium{font-size:1rem}.button.is-responsive.is-large{font-size:1.25rem}}.container{flex-grow:1;margin:0 auto;position:relative;width:auto}.container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){.container{max-width:992px}}@media screen and (max-width: 1215px){.container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){.container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){.container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){.container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}.content li+li{margin-top:0.25em}.content p:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content ul:not(:last-child),.content blockquote:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#222;font-weight:600;line-height:1.125}.content h1{font-size:2em;margin-bottom:0.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:0.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:0.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:0.8em}.content h5{font-size:1.125em;margin-bottom:0.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-left:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style-position:outside;margin-left:2em;margin-top:1em}.content ol:not([type]){list-style-type:decimal}.content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}.content ol.is-lower-roman:not([type]){list-style-type:lower-roman}.content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}.content ol.is-upper-roman:not([type]){list-style-type:upper-roman}.content ul{list-style:disc outside;margin-left:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:0.5em}.content ul ul ul{list-style-type:square}.content dd{margin-left:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}.content sup,.content sub{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.content table th{color:#222}.content table th:not([align]){text-align:inherit}.content table thead td,.content table thead th{border-width:0 0 2px;color:#222}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#222}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content .tabs li+li{margin-top:0}.content.is-small,#documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}.content.is-normal{font-size:1rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small,#documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}.icon-text .icon{flex-grow:0;flex-shrink:0}.icon-text .icon:not(:last-child){margin-right:.25em}.icon-text .icon:not(:first-child){margin-left:.25em}div.icon-text{display:flex}.image,#documenter .docs-sidebar .docs-logo>img{display:block;position:relative}.image img,#documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}.image img.is-rounded,#documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}.image.is-fullwidth,#documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}.image.is-square,#documenter .docs-sidebar .docs-logo>img.is-square,.image.is-1by1,#documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}.image.is-5by4,#documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}.image.is-4by3,#documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}.image.is-3by2,#documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}.image.is-5by3,#documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}.image.is-16by9,#documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}.image.is-2by1,#documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}.image.is-3by1,#documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}.image.is-4by5,#documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}.image.is-3by4,#documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}.image.is-2by3,#documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}.image.is-3by5,#documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}.image.is-9by16,#documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}.image.is-1by2,#documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}.image.is-1by3,#documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}.image.is-16x16,#documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}.image.is-24x24,#documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}.image.is-32x32,#documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}.image.is-48x48,#documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}.image.is-64x64,#documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}.image.is-96x96,#documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}.image.is-128x128,#documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:4px;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}.notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:transparent}.notification>.delete{right:.5rem;position:absolute;top:0.5rem}.notification .title,.notification .subtitle,.notification .content{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.notification.is-dark,.content kbd.notification{background-color:#363636;color:#fff}.notification.is-primary,.docstring>section>a.notification.docs-sourcelink{background-color:#4eb5de;color:#fff}.notification.is-primary.is-light,.docstring>section>a.notification.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.notification.is-link{background-color:#2e63b8;color:#fff}.notification.is-link.is-light{background-color:#eff3fb;color:#3169c4}.notification.is-info{background-color:#209cee;color:#fff}.notification.is-info.is-light{background-color:#ecf7fe;color:#0e72b4}.notification.is-success{background-color:#22c35b;color:#fff}.notification.is-success.is-light{background-color:#eefcf3;color:#198f43}.notification.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.notification.is-warning.is-light{background-color:#fffbeb;color:#947600}.notification.is-danger{background-color:#da0b00;color:#fff}.notification.is-danger.is-light{background-color:#ffeceb;color:#f50c00}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background-color:#ededed}.progress::-webkit-progress-value{background-color:#222}.progress::-moz-progress-bar{background-color:#222}.progress::-ms-fill{background-color:#222;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #ededed 30%)}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #ededed 30%)}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #ededed 30%)}.progress.is-dark::-webkit-progress-value,.content kbd.progress::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar,.content kbd.progress::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill,.content kbd.progress::-ms-fill{background-color:#363636}.progress.is-dark:indeterminate,.content kbd.progress:indeterminate{background-image:linear-gradient(to right, #363636 30%, #ededed 30%)}.progress.is-primary::-webkit-progress-value,.docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#4eb5de}.progress.is-primary::-moz-progress-bar,.docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#4eb5de}.progress.is-primary::-ms-fill,.docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#4eb5de}.progress.is-primary:indeterminate,.docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #4eb5de 30%, #ededed 30%)}.progress.is-link::-webkit-progress-value{background-color:#2e63b8}.progress.is-link::-moz-progress-bar{background-color:#2e63b8}.progress.is-link::-ms-fill{background-color:#2e63b8}.progress.is-link:indeterminate{background-image:linear-gradient(to right, #2e63b8 30%, #ededed 30%)}.progress.is-info::-webkit-progress-value{background-color:#209cee}.progress.is-info::-moz-progress-bar{background-color:#209cee}.progress.is-info::-ms-fill{background-color:#209cee}.progress.is-info:indeterminate{background-image:linear-gradient(to right, #209cee 30%, #ededed 30%)}.progress.is-success::-webkit-progress-value{background-color:#22c35b}.progress.is-success::-moz-progress-bar{background-color:#22c35b}.progress.is-success::-ms-fill{background-color:#22c35b}.progress.is-success:indeterminate{background-image:linear-gradient(to right, #22c35b 30%, #ededed 30%)}.progress.is-warning::-webkit-progress-value{background-color:#ffdd57}.progress.is-warning::-moz-progress-bar{background-color:#ffdd57}.progress.is-warning::-ms-fill{background-color:#ffdd57}.progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ffdd57 30%, #ededed 30%)}.progress.is-danger::-webkit-progress-value{background-color:#da0b00}.progress.is-danger::-moz-progress-bar{background-color:#da0b00}.progress.is-danger::-ms-fill{background-color:#da0b00}.progress.is-danger:indeterminate{background-image:linear-gradient(to right, #da0b00 30%, #ededed 30%)}.progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#ededed;background-image:linear-gradient(to right, #222 30%, #ededed 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}.progress:indeterminate::-webkit-progress-bar{background-color:transparent}.progress:indeterminate::-moz-progress-bar{background-color:transparent}.progress:indeterminate::-ms-fill{animation-name:none}.progress.is-small,#documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}.table{background-color:#fff;color:#222}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#fff}.table td.is-primary,.table th.is-primary{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.table td.is-link,.table th.is-link{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.table td.is-info,.table th.is-info{background-color:#209cee;border-color:#209cee;color:#fff}.table td.is-success,.table th.is-success{background-color:#22c35b;border-color:#22c35b;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.table td.is-danger,.table th.is-danger{background-color:#da0b00;border-color:#da0b00;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#4eb5de;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table td.is-vcentered,.table th.is-vcentered{vertical-align:middle}.table th{color:#222}.table th:not([align]){text-align:left}.table tr.is-selected{background-color:#4eb5de;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead{background-color:rgba(0,0,0,0)}.table thead td,.table thead th{border-width:0 0 2px;color:#222}.table tfoot{background-color:rgba(0,0,0,0)}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#222}.table tbody{background-color:rgba(0,0,0,0)}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:0.25em 0.5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}.tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.tags .tag,.tags .content kbd,.content .tags kbd,.tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}.tags .tag:not(:last-child),.tags .content kbd:not(:last-child),.content .tags kbd:not(:last-child),.tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}.tags:last-child{margin-bottom:-0.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.are-medium .tag:not(.is-normal):not(.is-large),.tags.are-medium .content kbd:not(.is-normal):not(.is-large),.content .tags.are-medium kbd:not(.is-normal):not(.is-large),.tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}.tags.are-large .tag:not(.is-normal):not(.is-medium),.tags.are-large .content kbd:not(.is-normal):not(.is-medium),.content .tags.are-large kbd:not(.is-normal):not(.is-medium),.tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}.tags.is-centered{justify-content:center}.tags.is-centered .tag,.tags.is-centered .content kbd,.content .tags.is-centered kbd,.tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}.tags.is-right{justify-content:flex-end}.tags.is-right .tag:not(:first-child),.tags.is-right .content kbd:not(:first-child),.content .tags.is-right kbd:not(:first-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}.tags.is-right .tag:not(:last-child),.tags.is-right .content kbd:not(:last-child),.content .tags.is-right kbd:not(:last-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}.tags.has-addons .tag,.tags.has-addons .content kbd,.content .tags.has-addons kbd,.tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}.tags.has-addons .tag:not(:first-child),.tags.has-addons .content kbd:not(:first-child),.content .tags.has-addons kbd:not(:first-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.tags.has-addons .tag:not(:last-child),.tags.has-addons .content kbd:not(:last-child),.content .tags.has-addons kbd:not(:last-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.tag:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#f5f5f5;border-radius:4px;color:#222;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}.tag:not(body) .delete,.content kbd:not(body) .delete,.docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}.tag.is-white:not(body),.content kbd.is-white:not(body),.docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}.tag.is-black:not(body),.content kbd.is-black:not(body),.docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}.tag.is-light:not(body),.content kbd.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.tag.is-dark:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink.is-dark:not(body),.content .docstring>section>kbd:not(body){background-color:#363636;color:#fff}.tag.is-primary:not(body),.content kbd.is-primary:not(body),.docstring>section>a.docs-sourcelink:not(body){background-color:#4eb5de;color:#fff}.tag.is-primary.is-light:not(body),.content kbd.is-primary.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#eef8fc;color:#1a6d8e}.tag.is-link:not(body),.content kbd.is-link:not(body),.docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#2e63b8;color:#fff}.tag.is-link.is-light:not(body),.content kbd.is-link.is-light:not(body),.docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#eff3fb;color:#3169c4}.tag.is-info:not(body),.content kbd.is-info:not(body),.docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#209cee;color:#fff}.tag.is-info.is-light:not(body),.content kbd.is-info.is-light:not(body),.docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#ecf7fe;color:#0e72b4}.tag.is-success:not(body),.content kbd.is-success:not(body),.docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#22c35b;color:#fff}.tag.is-success.is-light:not(body),.content kbd.is-success.is-light:not(body),.docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#eefcf3;color:#198f43}.tag.is-warning:not(body),.content kbd.is-warning:not(body),.docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ffdd57;color:rgba(0,0,0,0.7)}.tag.is-warning.is-light:not(body),.content kbd.is-warning.is-light:not(body),.docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffbeb;color:#947600}.tag.is-danger:not(body),.content kbd.is-danger:not(body),.docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#da0b00;color:#fff}.tag.is-danger.is-light:not(body),.content kbd.is-danger.is-light:not(body),.docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#ffeceb;color:#f50c00}.tag.is-normal:not(body),.content kbd.is-normal:not(body),.docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}.tag.is-medium:not(body),.content kbd.is-medium:not(body),.docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}.tag.is-large:not(body),.content kbd.is-large:not(body),.docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child),.content kbd:not(body) .icon:first-child:not(:last-child),.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}.tag:not(body) .icon:last-child:not(:first-child),.content kbd:not(body) .icon:last-child:not(:first-child),.docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}.tag:not(body) .icon:first-child:last-child,.content kbd:not(body) .icon:first-child:last-child,.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}.tag.is-delete:not(body),.content kbd.is-delete:not(body),.docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before,.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}.tag.is-delete:not(body):hover,.content kbd.is-delete:not(body):hover,.docstring>section>a.docs-sourcelink.is-delete:not(body):hover,.tag.is-delete:not(body):focus,.content kbd.is-delete:not(body):focus,.docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#e8e8e8}.tag.is-delete:not(body):active,.content kbd.is-delete:not(body):active,.docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#dbdbdb}.tag.is-rounded:not(body),#documenter .docs-sidebar form.docs-search>input:not(body),.content kbd.is-rounded:not(body),#documenter .docs-sidebar .content form.docs-search>input:not(body),.docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}a.tag:hover,.docstring>section>a.docs-sourcelink:hover{text-decoration:underline}.title,.subtitle{word-break:break-word}.title em,.title span,.subtitle em,.subtitle span{font-weight:inherit}.title sub,.subtitle sub{font-size:.75em}.title sup,.subtitle sup{font-size:.75em}.title .tag,.title .content kbd,.content .title kbd,.title .docstring>section>a.docs-sourcelink,.subtitle .tag,.subtitle .content kbd,.content .subtitle kbd,.subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}.title{color:#222;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#222;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#222;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.number{align-items:center;background-color:#f5f5f5;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#222}.select select::-moz-placeholder,.textarea::-moz-placeholder,.input::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#707070}.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder,.input::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#707070}.select select:-moz-placeholder,.textarea:-moz-placeholder,.input:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#707070}.select select:-ms-input-placeholder,.textarea:-ms-input-placeholder,.input:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#707070}.select select:hover,.textarea:hover,.input:hover,#documenter .docs-sidebar form.docs-search>input:hover,.select select.is-hovered,.is-hovered.textarea,.is-hovered.input,#documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#b5b5b5}.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{border-color:#2e63b8;box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#6b6b6b}.select select[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder,.input[disabled]::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] .select select::-moz-placeholder,.select fieldset[disabled] select::-moz-placeholder,fieldset[disabled] .textarea::-moz-placeholder,fieldset[disabled] .input::-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,.input[disabled]::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,.select fieldset[disabled] select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-webkit-input-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder,.input[disabled]:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] .select select:-moz-placeholder,.select fieldset[disabled] select:-moz-placeholder,fieldset[disabled] .textarea:-moz-placeholder,fieldset[disabled] .input:-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder,.input[disabled]:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] .select select:-ms-input-placeholder,.select fieldset[disabled] select:-ms-input-placeholder,fieldset[disabled] .textarea:-ms-input-placeholder,fieldset[disabled] .input:-ms-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-ms-input-placeholder{color:rgba(107,107,107,0.3)}.textarea,.input,#documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}.textarea[readonly],.input[readonly],#documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}.is-white.textarea,.is-white.input,#documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}.is-white.textarea:focus,.is-white.input:focus,#documenter .docs-sidebar form.docs-search>input.is-white:focus,.is-white.is-focused.textarea,.is-white.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-white.textarea:active,.is-white.input:active,#documenter .docs-sidebar form.docs-search>input.is-white:active,.is-white.is-active.textarea,.is-white.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.is-black.textarea,.is-black.input,#documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}.is-black.textarea:focus,.is-black.input:focus,#documenter .docs-sidebar form.docs-search>input.is-black:focus,.is-black.is-focused.textarea,.is-black.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-black.textarea:active,.is-black.input:active,#documenter .docs-sidebar form.docs-search>input.is-black:active,.is-black.is-active.textarea,.is-black.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.is-light.textarea,.is-light.input,#documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}.is-light.textarea:focus,.is-light.input:focus,#documenter .docs-sidebar form.docs-search>input.is-light:focus,.is-light.is-focused.textarea,.is-light.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-light.textarea:active,.is-light.input:active,#documenter .docs-sidebar form.docs-search>input.is-light:active,.is-light.is-active.textarea,.is-light.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.is-dark.textarea,.content kbd.textarea,.is-dark.input,#documenter .docs-sidebar form.docs-search>input.is-dark,.content kbd.input{border-color:#363636}.is-dark.textarea:focus,.content kbd.textarea:focus,.is-dark.input:focus,#documenter .docs-sidebar form.docs-search>input.is-dark:focus,.content kbd.input:focus,.is-dark.is-focused.textarea,.content kbd.is-focused.textarea,.is-dark.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.content kbd.is-focused.input,#documenter .docs-sidebar .content form.docs-search>input.is-focused,.is-dark.textarea:active,.content kbd.textarea:active,.is-dark.input:active,#documenter .docs-sidebar form.docs-search>input.is-dark:active,.content kbd.input:active,.is-dark.is-active.textarea,.content kbd.is-active.textarea,.is-dark.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.content kbd.is-active.input,#documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.is-primary.textarea,.docstring>section>a.textarea.docs-sourcelink,.is-primary.input,#documenter .docs-sidebar form.docs-search>input.is-primary,.docstring>section>a.input.docs-sourcelink{border-color:#4eb5de}.is-primary.textarea:focus,.docstring>section>a.textarea.docs-sourcelink:focus,.is-primary.input:focus,#documenter .docs-sidebar form.docs-search>input.is-primary:focus,.docstring>section>a.input.docs-sourcelink:focus,.is-primary.is-focused.textarea,.docstring>section>a.is-focused.textarea.docs-sourcelink,.is-primary.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.docstring>section>a.is-focused.input.docs-sourcelink,.is-primary.textarea:active,.docstring>section>a.textarea.docs-sourcelink:active,.is-primary.input:active,#documenter .docs-sidebar form.docs-search>input.is-primary:active,.docstring>section>a.input.docs-sourcelink:active,.is-primary.is-active.textarea,.docstring>section>a.is-active.textarea.docs-sourcelink,.is-primary.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.is-link.textarea,.is-link.input,#documenter .docs-sidebar form.docs-search>input.is-link{border-color:#2e63b8}.is-link.textarea:focus,.is-link.input:focus,#documenter .docs-sidebar form.docs-search>input.is-link:focus,.is-link.is-focused.textarea,.is-link.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-link.textarea:active,.is-link.input:active,#documenter .docs-sidebar form.docs-search>input.is-link:active,.is-link.is-active.textarea,.is-link.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.is-info.textarea,.is-info.input,#documenter .docs-sidebar form.docs-search>input.is-info{border-color:#209cee}.is-info.textarea:focus,.is-info.input:focus,#documenter .docs-sidebar form.docs-search>input.is-info:focus,.is-info.is-focused.textarea,.is-info.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-info.textarea:active,.is-info.input:active,#documenter .docs-sidebar form.docs-search>input.is-info:active,.is-info.is-active.textarea,.is-info.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.is-success.textarea,.is-success.input,#documenter .docs-sidebar form.docs-search>input.is-success{border-color:#22c35b}.is-success.textarea:focus,.is-success.input:focus,#documenter .docs-sidebar form.docs-search>input.is-success:focus,.is-success.is-focused.textarea,.is-success.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-success.textarea:active,.is-success.input:active,#documenter .docs-sidebar form.docs-search>input.is-success:active,.is-success.is-active.textarea,.is-success.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.is-warning.textarea,.is-warning.input,#documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ffdd57}.is-warning.textarea:focus,.is-warning.input:focus,#documenter .docs-sidebar form.docs-search>input.is-warning:focus,.is-warning.is-focused.textarea,.is-warning.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-warning.textarea:active,.is-warning.input:active,#documenter .docs-sidebar form.docs-search>input.is-warning:active,.is-warning.is-active.textarea,.is-warning.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.is-danger.textarea,.is-danger.input,#documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#da0b00}.is-danger.textarea:focus,.is-danger.input:focus,#documenter .docs-sidebar form.docs-search>input.is-danger:focus,.is-danger.is-focused.textarea,.is-danger.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-danger.textarea:active,.is-danger.input:active,#documenter .docs-sidebar form.docs-search>input.is-danger:active,.is-danger.is-active.textarea,.is-danger.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.is-small.textarea,.is-small.input,#documenter .docs-sidebar form.docs-search>input{border-radius:2px;font-size:.75rem}.is-medium.textarea,.is-medium.input,#documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}.is-large.textarea,.is-large.input,#documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}.is-fullwidth.textarea,.is-fullwidth.input,#documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}.is-inline.textarea,.is-inline.input,#documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}.input.is-rounded,#documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}.input.is-static,#documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}.textarea:not([rows]){max-height:40em;min-height:8em}.textarea[rows]{height:initial}.textarea.has-fixed-size{resize:none}.radio,.checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.radio input,.checkbox input{cursor:pointer}.radio:hover,.checkbox:hover{color:#222}.radio[disabled],.checkbox[disabled],fieldset[disabled] .radio,fieldset[disabled] .checkbox,.radio input[disabled],.checkbox input[disabled]{color:#6b6b6b;cursor:not-allowed}.radio+.radio{margin-left:.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.5em}.select:not(.is-multiple):not(.is-loading)::after{border-color:#2e63b8;right:1.125em;z-index:4}.select.is-rounded select,#documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}.select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}.select select::-ms-expand{display:none}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-right:2.5em}.select select[multiple]{height:auto;padding:0}.select select[multiple] option{padding:0.5em 1em}.select:not(.is-multiple):not(.is-loading):hover::after{border-color:#222}.select.is-white:not(:hover)::after{border-color:#fff}.select.is-white select{border-color:#fff}.select.is-white select:hover,.select.is-white select.is-hovered{border-color:#f2f2f2}.select.is-white select:focus,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.select.is-black:not(:hover)::after{border-color:#0a0a0a}.select.is-black select{border-color:#0a0a0a}.select.is-black select:hover,.select.is-black select.is-hovered{border-color:#000}.select.is-black select:focus,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.select.is-light:not(:hover)::after{border-color:#f5f5f5}.select.is-light select{border-color:#f5f5f5}.select.is-light select:hover,.select.is-light select.is-hovered{border-color:#e8e8e8}.select.is-light select:focus,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.select.is-dark:not(:hover)::after,.content kbd.select:not(:hover)::after{border-color:#363636}.select.is-dark select,.content kbd.select select{border-color:#363636}.select.is-dark select:hover,.content kbd.select select:hover,.select.is-dark select.is-hovered,.content kbd.select select.is-hovered{border-color:#292929}.select.is-dark select:focus,.content kbd.select select:focus,.select.is-dark select.is-focused,.content kbd.select select.is-focused,.select.is-dark select:active,.content kbd.select select:active,.select.is-dark select.is-active,.content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.select.is-primary:not(:hover)::after,.docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#4eb5de}.select.is-primary select,.docstring>section>a.select.docs-sourcelink select{border-color:#4eb5de}.select.is-primary select:hover,.docstring>section>a.select.docs-sourcelink select:hover,.select.is-primary select.is-hovered,.docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#39acda}.select.is-primary select:focus,.docstring>section>a.select.docs-sourcelink select:focus,.select.is-primary select.is-focused,.docstring>section>a.select.docs-sourcelink select.is-focused,.select.is-primary select:active,.docstring>section>a.select.docs-sourcelink select:active,.select.is-primary select.is-active,.docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.select.is-link:not(:hover)::after{border-color:#2e63b8}.select.is-link select{border-color:#2e63b8}.select.is-link select:hover,.select.is-link select.is-hovered{border-color:#2958a4}.select.is-link select:focus,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select.is-info:not(:hover)::after{border-color:#209cee}.select.is-info select{border-color:#209cee}.select.is-info select:hover,.select.is-info select.is-hovered{border-color:#1190e3}.select.is-info select:focus,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.select.is-success:not(:hover)::after{border-color:#22c35b}.select.is-success select{border-color:#22c35b}.select.is-success select:hover,.select.is-success select.is-hovered{border-color:#1ead51}.select.is-success select:focus,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.select.is-warning:not(:hover)::after{border-color:#ffdd57}.select.is-warning select{border-color:#ffdd57}.select.is-warning select:hover,.select.is-warning select.is-hovered{border-color:#ffd83e}.select.is-warning select:focus,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.select.is-danger:not(:hover)::after{border-color:#da0b00}.select.is-danger select{border-color:#da0b00}.select.is-danger select:hover,.select.is-danger select.is-hovered{border-color:#c10a00}.select.is-danger select:focus,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.select.is-small,#documenter .docs-sidebar form.docs-search>input.select{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#6b6b6b !important;opacity:0.5}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}.select.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white:hover .file-cta,.file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white:focus .file-cta,.file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}.file.is-white:active .file-cta,.file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black:hover .file-cta,.file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black:focus .file-cta,.file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}.file.is-black:active .file-cta,.file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:hover .file-cta,.file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:focus .file-cta,.file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}.file.is-light:active .file-cta,.file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-dark .file-cta,.content kbd.file .file-cta{background-color:#363636;border-color:transparent;color:#fff}.file.is-dark:hover .file-cta,.content kbd.file:hover .file-cta,.file.is-dark.is-hovered .file-cta,.content kbd.file.is-hovered .file-cta{background-color:#2f2f2f;border-color:transparent;color:#fff}.file.is-dark:focus .file-cta,.content kbd.file:focus .file-cta,.file.is-dark.is-focused .file-cta,.content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(54,54,54,0.25);color:#fff}.file.is-dark:active .file-cta,.content kbd.file:active .file-cta,.file.is-dark.is-active .file-cta,.content kbd.file.is-active .file-cta{background-color:#292929;border-color:transparent;color:#fff}.file.is-primary .file-cta,.docstring>section>a.file.docs-sourcelink .file-cta{background-color:#4eb5de;border-color:transparent;color:#fff}.file.is-primary:hover .file-cta,.docstring>section>a.file.docs-sourcelink:hover .file-cta,.file.is-primary.is-hovered .file-cta,.docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#43b1dc;border-color:transparent;color:#fff}.file.is-primary:focus .file-cta,.docstring>section>a.file.docs-sourcelink:focus .file-cta,.file.is-primary.is-focused .file-cta,.docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(78,181,222,0.25);color:#fff}.file.is-primary:active .file-cta,.docstring>section>a.file.docs-sourcelink:active .file-cta,.file.is-primary.is-active .file-cta,.docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#39acda;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#2e63b8;border-color:transparent;color:#fff}.file.is-link:hover .file-cta,.file.is-link.is-hovered .file-cta{background-color:#2b5eae;border-color:transparent;color:#fff}.file.is-link:focus .file-cta,.file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(46,99,184,0.25);color:#fff}.file.is-link:active .file-cta,.file.is-link.is-active .file-cta{background-color:#2958a4;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#209cee;border-color:transparent;color:#fff}.file.is-info:hover .file-cta,.file.is-info.is-hovered .file-cta{background-color:#1497ed;border-color:transparent;color:#fff}.file.is-info:focus .file-cta,.file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(32,156,238,0.25);color:#fff}.file.is-info:active .file-cta,.file.is-info.is-active .file-cta{background-color:#1190e3;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#22c35b;border-color:transparent;color:#fff}.file.is-success:hover .file-cta,.file.is-success.is-hovered .file-cta{background-color:#20b856;border-color:transparent;color:#fff}.file.is-success:focus .file-cta,.file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(34,195,91,0.25);color:#fff}.file.is-success:active .file-cta,.file.is-success.is-active .file-cta{background-color:#1ead51;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:hover .file-cta,.file.is-warning.is-hovered .file-cta{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:focus .file-cta,.file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,221,87,0.25);color:rgba(0,0,0,0.7)}.file.is-warning:active .file-cta,.file.is-warning.is-active .file-cta{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-danger .file-cta{background-color:#da0b00;border-color:transparent;color:#fff}.file.is-danger:hover .file-cta,.file.is-danger.is-hovered .file-cta{background-color:#cd0a00;border-color:transparent;color:#fff}.file.is-danger:focus .file-cta,.file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(218,11,0,0.25);color:#fff}.file.is-danger:active .file-cta,.file.is-danger.is-active .file-cta{background-color:#c10a00;border-color:transparent;color:#fff}.file.is-small,#documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}.file.is-normal{font-size:1rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:4px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{flex-direction:column}.file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa,#documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:4px 4px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 4px 4px;border-width:0 1px 1px}.file.is-centered{justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{flex-grow:1;max-width:none}.file.is-right{justify-content:flex-end}.file.is-right .file-cta{border-radius:0 4px 4px 0}.file.is-right .file-name{border-radius:4px 0 0 4px;border-width:1px 0 1px 1px;order:-1}.file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#222}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#222}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}.file-cta,.file-name{border-color:#dbdbdb;border-radius:4px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta{background-color:#f5f5f5;color:#222}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}.file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#222;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:0.5em}.label.is-small,#documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:0.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark,.content kbd.help{color:#363636}.help.is-primary,.docstring>section>a.help.docs-sourcelink{color:#4eb5de}.help.is-link{color:#2e63b8}.help.is-info{color:#209cee}.help.is-success{color:#22c35b}.help.is-warning{color:#ffdd57}.help.is-danger{color:#da0b00}.field:not(:last-child){margin-bottom:0.75rem}.field.has-addons{display:flex;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-right:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child:not(:only-child) .button,.field.has-addons .control:first-child:not(:only-child) .input,.field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,.field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control:last-child:not(:only-child) .button,.field.has-addons .control:last-child:not(:only-child) .input,.field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,.field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control .button:not([disabled]):hover,.field.has-addons .control .button.is-hovered:not([disabled]),.field.has-addons .control .input:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,.field.has-addons .control .input.is-hovered:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),.field.has-addons .control .select select:not([disabled]):hover,.field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}.field.has-addons .control .button:not([disabled]):focus,.field.has-addons .control .button.is-focused:not([disabled]),.field.has-addons .control .button:not([disabled]):active,.field.has-addons .control .button.is-active:not([disabled]),.field.has-addons .control .input:not([disabled]):focus,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,.field.has-addons .control .input.is-focused:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),.field.has-addons .control .input:not([disabled]):active,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,.field.has-addons .control .input.is-active:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),.field.has-addons .control .select select:not([disabled]):focus,.field.has-addons .control .select select.is-focused:not([disabled]),.field.has-addons .control .select select:not([disabled]):active,.field.has-addons .control .select select.is-active:not([disabled]){z-index:3}.field.has-addons .control .button:not([disabled]):focus:hover,.field.has-addons .control .button.is-focused:not([disabled]):hover,.field.has-addons .control .button:not([disabled]):active:hover,.field.has-addons .control .button.is-active:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):focus:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,.field.has-addons .control .input.is-focused:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):active:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,.field.has-addons .control .input.is-active:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):focus:hover,.field.has-addons .control .select select.is-focused:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):active:hover,.field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}.field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}.field.has-addons.has-addons-centered{justify-content:center}.field.has-addons.has-addons-right{justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}.field.is-grouped{display:flex;justify-content:flex-start}.field.is-grouped>.control{flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}.field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{justify-content:center}.field.is-grouped.is-grouped-right{justify-content:flex-end}.field.is-grouped.is-grouped-multiline{flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{.field.is-horizontal{display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width: 768px){.field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{.field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}.field-label.is-small,#documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}.field-label.is-normal{padding-top:0.375em}.field-label.is-medium{font-size:1.25rem;padding-top:0.375em}.field-label.is-large{font-size:1.5rem;padding-top:0.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{.field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{flex-shrink:1}.field-body>.field:not(.is-narrow){flex-grow:1}.field-body>.field:not(:last-child){margin-right:.75rem}}.control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}.control.has-icons-left .input:focus~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#222}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}.control.has-icons-left .input,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input,.control.has-icons-left .select select{padding-left:2.5em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input,.control.has-icons-right .select select{padding-right:2.5em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}.control.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.breadcrumb{font-size:1rem;white-space:nowrap}.breadcrumb a{align-items:center;color:#2e63b8;display:flex;justify-content:center;padding:0 .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{align-items:center;display:flex}.breadcrumb li:first-child a{padding-left:0}.breadcrumb li.is-active a{color:#222;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#b5b5b5;content:"\0002f"}.breadcrumb ul,.breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}.breadcrumb .icon:first-child{margin-right:.5em}.breadcrumb .icon:last-child{margin-left:.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{justify-content:flex-end}.breadcrumb.is-small,#documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;border-radius:.25rem;box-shadow:#bbb;color:#222;max-width:100%;position:relative}.card-footer:first-child,.card-content:first-child,.card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-footer:last-child,.card-content:last-child,.card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}.card-header-title{align-items:center;color:#222;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}.card-header-title.is-centered{justify-content:center}.card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}.card-image{display:block;position:relative}.card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-content{background-color:rgba(0,0,0,0);padding:1.5rem}.card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}.card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-right:1px solid #ededed}.card .media:not(:last-child){margin-bottom:1.5rem}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:#bbb;padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#222;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#2e63b8;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}.level{align-items:center;justify-content:space-between}.level code{border-radius:4px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}.level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{.level{display:flex}.level>.level-item:not(.is-narrow){flex-grow:1}}.level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}.level-item .title,.level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-right:.75rem}}.level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{.level-left{display:flex}}.level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{.level-right{display:flex}}.media{align-items:flex-start;display:flex;text-align:inherit}.media .content:not(:last-child){margin-bottom:.75rem}.media .media{border-top:1px solid rgba(219,219,219,0.5);display:flex;padding-top:.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:.5rem}.media .media .media{padding-top:.5rem}.media .media .media+.media{margin-top:.5rem}.media+.media{border-top:1px solid rgba(219,219,219,0.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.media-left{margin-right:1rem}.media-right{margin-left:1rem}.media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){.media-content{overflow-x:auto}}.menu{font-size:1rem}.menu.is-small,#documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#222;display:block;padding:0.5em 0.75em}.menu-list a:hover{background-color:#f5f5f5;color:#222}.menu-list a.is-active{background-color:#2e63b8;color:#fff}.menu-list li ul{border-left:1px solid #dbdbdb;margin:.75em;padding-left:.75em}.menu-label{color:#6b6b6b;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:4px;font-size:1rem}.message strong{color:currentColor}.message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}.message.is-small,#documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.message.is-light .message-body{border-color:#f5f5f5}.message.is-dark,.content kbd.message{background-color:#fafafa}.message.is-dark .message-header,.content kbd.message .message-header{background-color:#363636;color:#fff}.message.is-dark .message-body,.content kbd.message .message-body{border-color:#363636}.message.is-primary,.docstring>section>a.message.docs-sourcelink{background-color:#eef8fc}.message.is-primary .message-header,.docstring>section>a.message.docs-sourcelink .message-header{background-color:#4eb5de;color:#fff}.message.is-primary .message-body,.docstring>section>a.message.docs-sourcelink .message-body{border-color:#4eb5de;color:#1a6d8e}.message.is-link{background-color:#eff3fb}.message.is-link .message-header{background-color:#2e63b8;color:#fff}.message.is-link .message-body{border-color:#2e63b8;color:#3169c4}.message.is-info{background-color:#ecf7fe}.message.is-info .message-header{background-color:#209cee;color:#fff}.message.is-info .message-body{border-color:#209cee;color:#0e72b4}.message.is-success{background-color:#eefcf3}.message.is-success .message-header{background-color:#22c35b;color:#fff}.message.is-success .message-body{border-color:#22c35b;color:#198f43}.message.is-warning{background-color:#fffbeb}.message.is-warning .message-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.message.is-warning .message-body{border-color:#ffdd57;color:#947600}.message.is-danger{background-color:#ffeceb}.message.is-danger .message-header{background-color:#da0b00;color:#fff}.message.is-danger .message-body{border-color:#da0b00;color:#f50c00}.message-header{align-items:center;background-color:#222;border-radius:4px 4px 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}.message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}.message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}.message-body{border-color:#dbdbdb;border-radius:4px;border-style:solid;border-width:0 0 0 4px;color:#222;padding:1.25em 1.5em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:rgba(0,0,0,0)}.modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:flex}.modal-background{background-color:rgba(10,10,10,0.86)}.modal-content,.modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){.modal-content,.modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}.modal-card-head,.modal-card-foot{align-items:center;background-color:#f5f5f5;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:6px;border-top-right-radius:6px}.modal-card-title{color:#222;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-right:.5em}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative;z-index:30}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand>.navbar-item,.navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-brand>a.navbar-item:focus,.navbar.is-white .navbar-brand>a.navbar-item:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand .navbar-link:focus,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){.navbar.is-white .navbar-start>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-start>a.navbar-item:focus,.navbar.is-white .navbar-start>a.navbar-item:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start .navbar-link:focus,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-end>a.navbar-item:focus,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end .navbar-link:focus,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-start .navbar-link::after,.navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand>.navbar-item,.navbar.is-black .navbar-brand .navbar-link{color:#fff}.navbar.is-black .navbar-brand>a.navbar-item:focus,.navbar.is-black .navbar-brand>a.navbar-item:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand .navbar-link:focus,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-black .navbar-start>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-end .navbar-link{color:#fff}.navbar.is-black .navbar-start>a.navbar-item:focus,.navbar.is-black .navbar-start>a.navbar-item:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start .navbar-link:focus,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-end>a.navbar-item:focus,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end .navbar-link:focus,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-start .navbar-link::after,.navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>.navbar-item,.navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>a.navbar-item:focus,.navbar.is-light .navbar-brand>a.navbar-item:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand .navbar-link:focus,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-light .navbar-start>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start>a.navbar-item:focus,.navbar.is-light .navbar-start>a.navbar-item:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start .navbar-link:focus,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-end>a.navbar-item:focus,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end .navbar-link:focus,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start .navbar-link::after,.navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}.navbar.is-dark,.content kbd.navbar{background-color:#363636;color:#fff}.navbar.is-dark .navbar-brand>.navbar-item,.content kbd.navbar .navbar-brand>.navbar-item,.navbar.is-dark .navbar-brand .navbar-link,.content kbd.navbar .navbar-brand .navbar-link{color:#fff}.navbar.is-dark .navbar-brand>a.navbar-item:focus,.content kbd.navbar .navbar-brand>a.navbar-item:focus,.navbar.is-dark .navbar-brand>a.navbar-item:hover,.content kbd.navbar .navbar-brand>a.navbar-item:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.content kbd.navbar .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand .navbar-link:focus,.content kbd.navbar .navbar-brand .navbar-link:focus,.navbar.is-dark .navbar-brand .navbar-link:hover,.content kbd.navbar .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand .navbar-link.is-active,.content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-brand .navbar-link::after,.content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-burger,.content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-dark .navbar-start>.navbar-item,.content kbd.navbar .navbar-start>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.content kbd.navbar .navbar-start .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.content kbd.navbar .navbar-end>.navbar-item,.navbar.is-dark .navbar-end .navbar-link,.content kbd.navbar .navbar-end .navbar-link{color:#fff}.navbar.is-dark .navbar-start>a.navbar-item:focus,.content kbd.navbar .navbar-start>a.navbar-item:focus,.navbar.is-dark .navbar-start>a.navbar-item:hover,.content kbd.navbar .navbar-start>a.navbar-item:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.content kbd.navbar .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start .navbar-link:focus,.content kbd.navbar .navbar-start .navbar-link:focus,.navbar.is-dark .navbar-start .navbar-link:hover,.content kbd.navbar .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.content kbd.navbar .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-end>a.navbar-item:focus,.content kbd.navbar .navbar-end>a.navbar-item:focus,.navbar.is-dark .navbar-end>a.navbar-item:hover,.content kbd.navbar .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.content kbd.navbar .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end .navbar-link:focus,.content kbd.navbar .navbar-end .navbar-link:focus,.navbar.is-dark .navbar-end .navbar-link:hover,.content kbd.navbar .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end .navbar-link.is-active,.content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-start .navbar-link::after,.content kbd.navbar .navbar-start .navbar-link::after,.navbar.is-dark .navbar-end .navbar-link::after,.content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#292929;color:#fff}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active,.content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#fff}}.navbar.is-primary,.docstring>section>a.navbar.docs-sourcelink{background-color:#4eb5de;color:#fff}.navbar.is-primary .navbar-brand>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,.navbar.is-primary .navbar-brand .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}.navbar.is-primary .navbar-brand>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,.navbar.is-primary .navbar-brand>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,.navbar.is-primary .navbar-brand .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-burger,.docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-primary .navbar-start>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,.navbar.is-primary .navbar-end .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}.navbar.is-primary .navbar-start>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,.navbar.is-primary .navbar-start>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,.navbar.is-primary .navbar-start .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-end>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,.navbar.is-primary .navbar-end>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,.navbar.is-primary .navbar-end .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-start .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,.navbar.is-primary .navbar-end .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#4eb5de;color:#fff}}.navbar.is-link{background-color:#2e63b8;color:#fff}.navbar.is-link .navbar-brand>.navbar-item,.navbar.is-link .navbar-brand .navbar-link{color:#fff}.navbar.is-link .navbar-brand>a.navbar-item:focus,.navbar.is-link .navbar-brand>a.navbar-item:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand .navbar-link:focus,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-link .navbar-start>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-end .navbar-link{color:#fff}.navbar.is-link .navbar-start>a.navbar-item:focus,.navbar.is-link .navbar-start>a.navbar-item:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start .navbar-link:focus,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-end>a.navbar-item:focus,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end .navbar-link:focus,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-start .navbar-link::after,.navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#2e63b8;color:#fff}}.navbar.is-info{background-color:#209cee;color:#fff}.navbar.is-info .navbar-brand>.navbar-item,.navbar.is-info .navbar-brand .navbar-link{color:#fff}.navbar.is-info .navbar-brand>a.navbar-item:focus,.navbar.is-info .navbar-brand>a.navbar-item:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand .navbar-link:focus,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-info .navbar-start>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-end .navbar-link{color:#fff}.navbar.is-info .navbar-start>a.navbar-item:focus,.navbar.is-info .navbar-start>a.navbar-item:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start .navbar-link:focus,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-end>a.navbar-item:focus,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end .navbar-link:focus,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-start .navbar-link::after,.navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#209cee;color:#fff}}.navbar.is-success{background-color:#22c35b;color:#fff}.navbar.is-success .navbar-brand>.navbar-item,.navbar.is-success .navbar-brand .navbar-link{color:#fff}.navbar.is-success .navbar-brand>a.navbar-item:focus,.navbar.is-success .navbar-brand>a.navbar-item:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand .navbar-link:focus,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-success .navbar-start>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-end .navbar-link{color:#fff}.navbar.is-success .navbar-start>a.navbar-item:focus,.navbar.is-success .navbar-start>a.navbar-item:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start .navbar-link:focus,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-end>a.navbar-item:focus,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end .navbar-link:focus,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-start .navbar-link::after,.navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#22c35b;color:#fff}}.navbar.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>.navbar-item,.navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>a.navbar-item:focus,.navbar.is-warning .navbar-brand>a.navbar-item:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand .navbar-link:focus,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-warning .navbar-start>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start>a.navbar-item:focus,.navbar.is-warning .navbar-start>a.navbar-item:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start .navbar-link:focus,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-end>a.navbar-item:focus,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end .navbar-link:focus,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start .navbar-link::after,.navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ffdd57;color:rgba(0,0,0,0.7)}}.navbar.is-danger{background-color:#da0b00;color:#fff}.navbar.is-danger .navbar-brand>.navbar-item,.navbar.is-danger .navbar-brand .navbar-link{color:#fff}.navbar.is-danger .navbar-brand>a.navbar-item:focus,.navbar.is-danger .navbar-brand>a.navbar-item:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand .navbar-link:focus,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-danger .navbar-start>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-end .navbar-link{color:#fff}.navbar.is-danger .navbar-start>a.navbar-item:focus,.navbar.is-danger .navbar-start>a.navbar-item:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start .navbar-link:focus,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-end>a.navbar-item:focus,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end .navbar-link:focus,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-start .navbar-link::after,.navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#da0b00;color:#fff}}.navbar>.container{align-items:stretch;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{box-shadow:0 2px 0 0 #f5f5f5}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #f5f5f5}.navbar.is-fixed-top{top:0}html.has-navbar-fixed-top,body.has-navbar-fixed-top{padding-top:3.25rem}html.has-navbar-fixed-bottom,body.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:3.25rem}.navbar-brand a.navbar-item:focus,.navbar-brand a.navbar-item:hover{background-color:transparent}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{color:#222;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-left:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,0.05)}.navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#222;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}.navbar-item .icon:only-child,.navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}a.navbar-item,.navbar-link{cursor:pointer}a.navbar-item:focus,a.navbar-item:focus-within,a.navbar-item:hover,a.navbar-item.is-active,.navbar-link:focus,.navbar-link:focus-within,.navbar-link:hover,.navbar-link.is-active{background-color:#fafafa;color:#2e63b8}.navbar-item{flex-grow:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{flex-grow:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(0.5rem - 1px)}.navbar-item.is-tab:focus,.navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8}.navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8;border-bottom-style:solid;border-bottom-width:3px;color:#2e63b8;padding-bottom:calc(0.5rem - 3px)}.navbar-content{flex-grow:1;flex-shrink:1}.navbar-link:not(.is-arrowless){padding-right:2.5em}.navbar-link:not(.is-arrowless)::after{border-color:#2e63b8;margin-top:-0.375em;right:1.125em}.navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#f5f5f5;border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{align-items:center;display:flex}.navbar-link::after{display:none}.navbar-menu{background-color:#fff;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}html.has-navbar-fixed-top-touch,body.has-navbar-fixed-top-touch{padding-top:3.25rem}html.has-navbar-fixed-bottom-touch,body.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width: 1056px){.navbar,.navbar-menu,.navbar-start,.navbar-end{align-items:stretch;display:flex}.navbar{min-height:3.25rem}.navbar.is-spaced{padding:1rem 2rem}.navbar.is-spaced .navbar-start,.navbar.is-spaced .navbar-end{align-items:center}.navbar.is-spaced a.navbar-item,.navbar.is-spaced .navbar-link{border-radius:4px}.navbar.is-transparent a.navbar-item:focus,.navbar.is-transparent a.navbar-item:hover,.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent .navbar-link:focus,.navbar.is-transparent .navbar-link:hover,.navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}.navbar.is-transparent .navbar-dropdown a.navbar-item:focus,.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar-burger{display:none}.navbar-item,.navbar-link{align-items:center;display:flex}.navbar-item.has-dropdown{align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:2px solid #dbdbdb;border-radius:6px 6px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced .navbar-item.is-active .navbar-dropdown,.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}.navbar-menu{flex-grow:1;flex-shrink:0}.navbar-start{justify-content:flex-start;margin-right:auto}.navbar-end{justify-content:flex-end;margin-left:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:2px solid #dbdbdb;box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-right:3rem}.navbar-dropdown a.navbar-item:focus,.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar.is-spaced .navbar-dropdown,.navbar-dropdown.is-boxed{border-radius:6px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.navbar>.container .navbar-brand,.container>.navbar .navbar-brand{margin-left:-.75rem}.navbar>.container .navbar-menu,.container>.navbar .navbar-menu{margin-right:-.75rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-desktop{top:0}html.has-navbar-fixed-top-desktop,body.has-navbar-fixed-top-desktop{padding-top:3.25rem}html.has-navbar-fixed-bottom-desktop,body.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}html.has-spaced-navbar-fixed-top,body.has-spaced-navbar-fixed-top{padding-top:5.25rem}html.has-spaced-navbar-fixed-bottom,body.has-spaced-navbar-fixed-bottom{padding-bottom:5.25rem}a.navbar-item.is-active,.navbar-link.is-active{color:#0a0a0a}a.navbar-item.is-active:not(:focus):not(:hover),.navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}.navbar-item.has-dropdown:focus .navbar-link,.navbar-item.has-dropdown:hover .navbar-link,.navbar-item.has-dropdown.is-active .navbar-link{background-color:#fafafa}}.hero.is-fullheight-with-navbar{min-height:calc(100vh - 3.25rem)}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small,#documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-previous,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,.pagination.is-rounded .pagination-next,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}.pagination.is-rounded .pagination-link,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}.pagination,.pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}.pagination-previous,.pagination-next,.pagination-link{border-color:#dbdbdb;color:#222;min-width:2.5em}.pagination-previous:hover,.pagination-next:hover,.pagination-link:hover{border-color:#b5b5b5;color:#363636}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus{border-color:#3c5dcd}.pagination-previous:active,.pagination-next:active,.pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}.pagination-previous[disabled],.pagination-previous.is-disabled,.pagination-next[disabled],.pagination-next.is-disabled,.pagination-link[disabled],.pagination-link.is-disabled{background-color:#dbdbdb;border-color:#dbdbdb;box-shadow:none;color:#6b6b6b;opacity:0.5}.pagination-previous,.pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}.pagination-link.is-current{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{flex-wrap:wrap}.pagination-list li{list-style:none}@media screen and (max-width: 768px){.pagination{flex-wrap:wrap}.pagination-previous,.pagination-next{flex-grow:1;flex-shrink:1}.pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{.pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{margin-bottom:0;margin-top:0}.pagination-previous{order:2}.pagination-next{order:3}.pagination{justify-content:space-between;margin-bottom:0;margin-top:0}.pagination.is-centered .pagination-previous{order:1}.pagination.is-centered .pagination-list{justify-content:center;order:2}.pagination.is-centered .pagination-next{order:3}.pagination.is-right .pagination-previous{order:1}.pagination.is-right .pagination-next{order:2}.pagination.is-right .pagination-list{justify-content:flex-end;order:3}}.panel{border-radius:6px;box-shadow:#bbb;font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}.panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}.panel.is-white .panel-block.is-active .panel-icon{color:#fff}.panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}.panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}.panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}.panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}.panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}.panel.is-dark .panel-heading,.content kbd.panel .panel-heading{background-color:#363636;color:#fff}.panel.is-dark .panel-tabs a.is-active,.content kbd.panel .panel-tabs a.is-active{border-bottom-color:#363636}.panel.is-dark .panel-block.is-active .panel-icon,.content kbd.panel .panel-block.is-active .panel-icon{color:#363636}.panel.is-primary .panel-heading,.docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#4eb5de;color:#fff}.panel.is-primary .panel-tabs a.is-active,.docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#4eb5de}.panel.is-primary .panel-block.is-active .panel-icon,.docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#4eb5de}.panel.is-link .panel-heading{background-color:#2e63b8;color:#fff}.panel.is-link .panel-tabs a.is-active{border-bottom-color:#2e63b8}.panel.is-link .panel-block.is-active .panel-icon{color:#2e63b8}.panel.is-info .panel-heading{background-color:#209cee;color:#fff}.panel.is-info .panel-tabs a.is-active{border-bottom-color:#209cee}.panel.is-info .panel-block.is-active .panel-icon{color:#209cee}.panel.is-success .panel-heading{background-color:#22c35b;color:#fff}.panel.is-success .panel-tabs a.is-active{border-bottom-color:#22c35b}.panel.is-success .panel-block.is-active .panel-icon{color:#22c35b}.panel.is-warning .panel-heading{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ffdd57}.panel.is-warning .panel-block.is-active .panel-icon{color:#ffdd57}.panel.is-danger .panel-heading{background-color:#da0b00;color:#fff}.panel.is-danger .panel-tabs a.is-active{border-bottom-color:#da0b00}.panel.is-danger .panel-block.is-active .panel-icon{color:#da0b00}.panel-tabs:not(:last-child),.panel-block:not(:last-child){border-bottom:1px solid #ededed}.panel-heading{background-color:#ededed;border-radius:6px 6px 0 0;color:#222;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}.panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:0.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#222}.panel-list a:hover{color:#2e63b8}.panel-block{align-items:center;color:#222;display:flex;justify-content:flex-start;padding:0.5em 0.75em}.panel-block input[type="checkbox"]{margin-right:.75em}.panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{flex-wrap:wrap}.panel-block.is-active{border-left-color:#2e63b8;color:#363636}.panel-block.is-active .panel-icon{color:#2e63b8}.panel-block:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#6b6b6b;margin-right:.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs a{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#222;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#222;color:#222}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#2e63b8;color:#2e63b8}.tabs ul{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}.tabs ul.is-left{padding-right:0.75em}.tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}.tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}.tabs .icon:first-child{margin-right:.5em}.tabs .icon:last-child{margin-left:.5em}.tabs.is-centered ul{justify-content:center}.tabs.is-right ul{justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:4px 4px 0 0}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:rgba(0,0,0,0) !important}.tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-top-left-radius:4px;border-bottom-left-radius:4px}.tabs.is-toggle li:last-child a{border-top-right-radius:4px;border-bottom-right-radius:4px}.tabs.is-toggle li.is-active a{background-color:#2e63b8;border-color:#2e63b8;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}.tabs.is-small,#documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{flex:none;width:unset}.columns.is-mobile>.column.is-full{flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{flex:none;width:50%}.columns.is-mobile>.column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>.column.is-0{flex:none;width:0%}.columns.is-mobile>.column.is-offset-0{margin-left:0%}.columns.is-mobile>.column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>.column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>.column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>.column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>.column.is-3{flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>.column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>.column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>.column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>.column.is-6{flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>.column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>.column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>.column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>.column.is-9{flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>.column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>.column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>.column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>.column.is-12{flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){.column.is-narrow-mobile{flex:none;width:unset}.column.is-full-mobile{flex:none;width:100%}.column.is-three-quarters-mobile{flex:none;width:75%}.column.is-two-thirds-mobile{flex:none;width:66.6666%}.column.is-half-mobile{flex:none;width:50%}.column.is-one-third-mobile{flex:none;width:33.3333%}.column.is-one-quarter-mobile{flex:none;width:25%}.column.is-one-fifth-mobile{flex:none;width:20%}.column.is-two-fifths-mobile{flex:none;width:40%}.column.is-three-fifths-mobile{flex:none;width:60%}.column.is-four-fifths-mobile{flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-left:75%}.column.is-offset-two-thirds-mobile{margin-left:66.6666%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-one-third-mobile{margin-left:33.3333%}.column.is-offset-one-quarter-mobile{margin-left:25%}.column.is-offset-one-fifth-mobile{margin-left:20%}.column.is-offset-two-fifths-mobile{margin-left:40%}.column.is-offset-three-fifths-mobile{margin-left:60%}.column.is-offset-four-fifths-mobile{margin-left:80%}.column.is-0-mobile{flex:none;width:0%}.column.is-offset-0-mobile{margin-left:0%}.column.is-1-mobile{flex:none;width:8.33333337%}.column.is-offset-1-mobile{margin-left:8.33333337%}.column.is-2-mobile{flex:none;width:16.66666674%}.column.is-offset-2-mobile{margin-left:16.66666674%}.column.is-3-mobile{flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{flex:none;width:33.33333337%}.column.is-offset-4-mobile{margin-left:33.33333337%}.column.is-5-mobile{flex:none;width:41.66666674%}.column.is-offset-5-mobile{margin-left:41.66666674%}.column.is-6-mobile{flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{flex:none;width:58.33333337%}.column.is-offset-7-mobile{margin-left:58.33333337%}.column.is-8-mobile{flex:none;width:66.66666674%}.column.is-offset-8-mobile{margin-left:66.66666674%}.column.is-9-mobile{flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{flex:none;width:83.33333337%}.column.is-offset-10-mobile{margin-left:83.33333337%}.column.is-11-mobile{flex:none;width:91.66666674%}.column.is-offset-11-mobile{margin-left:91.66666674%}.column.is-12-mobile{flex:none;width:100%}.column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{.column.is-narrow,.column.is-narrow-tablet{flex:none;width:unset}.column.is-full,.column.is-full-tablet{flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-left:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-left:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-left:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-left:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-left:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-left:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-left:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-left:80%}.column.is-0,.column.is-0-tablet{flex:none;width:0%}.column.is-offset-0,.column.is-offset-0-tablet{margin-left:0%}.column.is-1,.column.is-1-tablet{flex:none;width:8.33333337%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.33333337%}.column.is-2,.column.is-2-tablet{flex:none;width:16.66666674%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.66666674%}.column.is-3,.column.is-3-tablet{flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{flex:none;width:33.33333337%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.33333337%}.column.is-5,.column.is-5-tablet{flex:none;width:41.66666674%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.66666674%}.column.is-6,.column.is-6-tablet{flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{flex:none;width:58.33333337%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.33333337%}.column.is-8,.column.is-8-tablet{flex:none;width:66.66666674%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.66666674%}.column.is-9,.column.is-9-tablet{flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{flex:none;width:83.33333337%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.33333337%}.column.is-11,.column.is-11-tablet{flex:none;width:91.66666674%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.66666674%}.column.is-12,.column.is-12-tablet{flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){.column.is-narrow-touch{flex:none;width:unset}.column.is-full-touch{flex:none;width:100%}.column.is-three-quarters-touch{flex:none;width:75%}.column.is-two-thirds-touch{flex:none;width:66.6666%}.column.is-half-touch{flex:none;width:50%}.column.is-one-third-touch{flex:none;width:33.3333%}.column.is-one-quarter-touch{flex:none;width:25%}.column.is-one-fifth-touch{flex:none;width:20%}.column.is-two-fifths-touch{flex:none;width:40%}.column.is-three-fifths-touch{flex:none;width:60%}.column.is-four-fifths-touch{flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-left:75%}.column.is-offset-two-thirds-touch{margin-left:66.6666%}.column.is-offset-half-touch{margin-left:50%}.column.is-offset-one-third-touch{margin-left:33.3333%}.column.is-offset-one-quarter-touch{margin-left:25%}.column.is-offset-one-fifth-touch{margin-left:20%}.column.is-offset-two-fifths-touch{margin-left:40%}.column.is-offset-three-fifths-touch{margin-left:60%}.column.is-offset-four-fifths-touch{margin-left:80%}.column.is-0-touch{flex:none;width:0%}.column.is-offset-0-touch{margin-left:0%}.column.is-1-touch{flex:none;width:8.33333337%}.column.is-offset-1-touch{margin-left:8.33333337%}.column.is-2-touch{flex:none;width:16.66666674%}.column.is-offset-2-touch{margin-left:16.66666674%}.column.is-3-touch{flex:none;width:25%}.column.is-offset-3-touch{margin-left:25%}.column.is-4-touch{flex:none;width:33.33333337%}.column.is-offset-4-touch{margin-left:33.33333337%}.column.is-5-touch{flex:none;width:41.66666674%}.column.is-offset-5-touch{margin-left:41.66666674%}.column.is-6-touch{flex:none;width:50%}.column.is-offset-6-touch{margin-left:50%}.column.is-7-touch{flex:none;width:58.33333337%}.column.is-offset-7-touch{margin-left:58.33333337%}.column.is-8-touch{flex:none;width:66.66666674%}.column.is-offset-8-touch{margin-left:66.66666674%}.column.is-9-touch{flex:none;width:75%}.column.is-offset-9-touch{margin-left:75%}.column.is-10-touch{flex:none;width:83.33333337%}.column.is-offset-10-touch{margin-left:83.33333337%}.column.is-11-touch{flex:none;width:91.66666674%}.column.is-offset-11-touch{margin-left:91.66666674%}.column.is-12-touch{flex:none;width:100%}.column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){.column.is-narrow-desktop{flex:none;width:unset}.column.is-full-desktop{flex:none;width:100%}.column.is-three-quarters-desktop{flex:none;width:75%}.column.is-two-thirds-desktop{flex:none;width:66.6666%}.column.is-half-desktop{flex:none;width:50%}.column.is-one-third-desktop{flex:none;width:33.3333%}.column.is-one-quarter-desktop{flex:none;width:25%}.column.is-one-fifth-desktop{flex:none;width:20%}.column.is-two-fifths-desktop{flex:none;width:40%}.column.is-three-fifths-desktop{flex:none;width:60%}.column.is-four-fifths-desktop{flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-left:75%}.column.is-offset-two-thirds-desktop{margin-left:66.6666%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-one-third-desktop{margin-left:33.3333%}.column.is-offset-one-quarter-desktop{margin-left:25%}.column.is-offset-one-fifth-desktop{margin-left:20%}.column.is-offset-two-fifths-desktop{margin-left:40%}.column.is-offset-three-fifths-desktop{margin-left:60%}.column.is-offset-four-fifths-desktop{margin-left:80%}.column.is-0-desktop{flex:none;width:0%}.column.is-offset-0-desktop{margin-left:0%}.column.is-1-desktop{flex:none;width:8.33333337%}.column.is-offset-1-desktop{margin-left:8.33333337%}.column.is-2-desktop{flex:none;width:16.66666674%}.column.is-offset-2-desktop{margin-left:16.66666674%}.column.is-3-desktop{flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{flex:none;width:33.33333337%}.column.is-offset-4-desktop{margin-left:33.33333337%}.column.is-5-desktop{flex:none;width:41.66666674%}.column.is-offset-5-desktop{margin-left:41.66666674%}.column.is-6-desktop{flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{flex:none;width:58.33333337%}.column.is-offset-7-desktop{margin-left:58.33333337%}.column.is-8-desktop{flex:none;width:66.66666674%}.column.is-offset-8-desktop{margin-left:66.66666674%}.column.is-9-desktop{flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{flex:none;width:83.33333337%}.column.is-offset-10-desktop{margin-left:83.33333337%}.column.is-11-desktop{flex:none;width:91.66666674%}.column.is-offset-11-desktop{margin-left:91.66666674%}.column.is-12-desktop{flex:none;width:100%}.column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){.column.is-narrow-widescreen{flex:none;width:unset}.column.is-full-widescreen{flex:none;width:100%}.column.is-three-quarters-widescreen{flex:none;width:75%}.column.is-two-thirds-widescreen{flex:none;width:66.6666%}.column.is-half-widescreen{flex:none;width:50%}.column.is-one-third-widescreen{flex:none;width:33.3333%}.column.is-one-quarter-widescreen{flex:none;width:25%}.column.is-one-fifth-widescreen{flex:none;width:20%}.column.is-two-fifths-widescreen{flex:none;width:40%}.column.is-three-fifths-widescreen{flex:none;width:60%}.column.is-four-fifths-widescreen{flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-left:75%}.column.is-offset-two-thirds-widescreen{margin-left:66.6666%}.column.is-offset-half-widescreen{margin-left:50%}.column.is-offset-one-third-widescreen{margin-left:33.3333%}.column.is-offset-one-quarter-widescreen{margin-left:25%}.column.is-offset-one-fifth-widescreen{margin-left:20%}.column.is-offset-two-fifths-widescreen{margin-left:40%}.column.is-offset-three-fifths-widescreen{margin-left:60%}.column.is-offset-four-fifths-widescreen{margin-left:80%}.column.is-0-widescreen{flex:none;width:0%}.column.is-offset-0-widescreen{margin-left:0%}.column.is-1-widescreen{flex:none;width:8.33333337%}.column.is-offset-1-widescreen{margin-left:8.33333337%}.column.is-2-widescreen{flex:none;width:16.66666674%}.column.is-offset-2-widescreen{margin-left:16.66666674%}.column.is-3-widescreen{flex:none;width:25%}.column.is-offset-3-widescreen{margin-left:25%}.column.is-4-widescreen{flex:none;width:33.33333337%}.column.is-offset-4-widescreen{margin-left:33.33333337%}.column.is-5-widescreen{flex:none;width:41.66666674%}.column.is-offset-5-widescreen{margin-left:41.66666674%}.column.is-6-widescreen{flex:none;width:50%}.column.is-offset-6-widescreen{margin-left:50%}.column.is-7-widescreen{flex:none;width:58.33333337%}.column.is-offset-7-widescreen{margin-left:58.33333337%}.column.is-8-widescreen{flex:none;width:66.66666674%}.column.is-offset-8-widescreen{margin-left:66.66666674%}.column.is-9-widescreen{flex:none;width:75%}.column.is-offset-9-widescreen{margin-left:75%}.column.is-10-widescreen{flex:none;width:83.33333337%}.column.is-offset-10-widescreen{margin-left:83.33333337%}.column.is-11-widescreen{flex:none;width:91.66666674%}.column.is-offset-11-widescreen{margin-left:91.66666674%}.column.is-12-widescreen{flex:none;width:100%}.column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){.column.is-narrow-fullhd{flex:none;width:unset}.column.is-full-fullhd{flex:none;width:100%}.column.is-three-quarters-fullhd{flex:none;width:75%}.column.is-two-thirds-fullhd{flex:none;width:66.6666%}.column.is-half-fullhd{flex:none;width:50%}.column.is-one-third-fullhd{flex:none;width:33.3333%}.column.is-one-quarter-fullhd{flex:none;width:25%}.column.is-one-fifth-fullhd{flex:none;width:20%}.column.is-two-fifths-fullhd{flex:none;width:40%}.column.is-three-fifths-fullhd{flex:none;width:60%}.column.is-four-fifths-fullhd{flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-left:75%}.column.is-offset-two-thirds-fullhd{margin-left:66.6666%}.column.is-offset-half-fullhd{margin-left:50%}.column.is-offset-one-third-fullhd{margin-left:33.3333%}.column.is-offset-one-quarter-fullhd{margin-left:25%}.column.is-offset-one-fifth-fullhd{margin-left:20%}.column.is-offset-two-fifths-fullhd{margin-left:40%}.column.is-offset-three-fifths-fullhd{margin-left:60%}.column.is-offset-four-fifths-fullhd{margin-left:80%}.column.is-0-fullhd{flex:none;width:0%}.column.is-offset-0-fullhd{margin-left:0%}.column.is-1-fullhd{flex:none;width:8.33333337%}.column.is-offset-1-fullhd{margin-left:8.33333337%}.column.is-2-fullhd{flex:none;width:16.66666674%}.column.is-offset-2-fullhd{margin-left:16.66666674%}.column.is-3-fullhd{flex:none;width:25%}.column.is-offset-3-fullhd{margin-left:25%}.column.is-4-fullhd{flex:none;width:33.33333337%}.column.is-offset-4-fullhd{margin-left:33.33333337%}.column.is-5-fullhd{flex:none;width:41.66666674%}.column.is-offset-5-fullhd{margin-left:41.66666674%}.column.is-6-fullhd{flex:none;width:50%}.column.is-offset-6-fullhd{margin-left:50%}.column.is-7-fullhd{flex:none;width:58.33333337%}.column.is-offset-7-fullhd{margin-left:58.33333337%}.column.is-8-fullhd{flex:none;width:66.66666674%}.column.is-offset-8-fullhd{margin-left:66.66666674%}.column.is-9-fullhd{flex:none;width:75%}.column.is-offset-9-fullhd{margin-left:75%}.column.is-10-fullhd{flex:none;width:83.33333337%}.column.is-offset-10-fullhd{margin-left:83.33333337%}.column.is-11-fullhd{flex:none;width:91.66666674%}.column.is-offset-11-fullhd{margin-left:91.66666674%}.column.is-12-fullhd{flex:none;width:100%}.column.is-offset-12-fullhd{margin-left:100%}}.columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{justify-content:center}.columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0 !important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:flex}.columns.is-multiline{flex-wrap:wrap}.columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{.columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){.columns.is-desktop{display:flex}}.columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}.columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){.columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-0-fullhd{--columnGap: 0rem}}.columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){.columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-1-fullhd{--columnGap: .25rem}}.columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){.columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-2-fullhd{--columnGap: .5rem}}.columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){.columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-3-fullhd{--columnGap: .75rem}}.columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){.columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-4-fullhd{--columnGap: 1rem}}.columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){.columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}.columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){.columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}.columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){.columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}.columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){.columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-8-fullhd{--columnGap: 2rem}}.tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0 !important}.tile.is-parent{padding:.75rem}.tile.is-vertical{flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{.tile:not(.is-child){display:flex}.tile.is-1{flex:none;width:8.33333337%}.tile.is-2{flex:none;width:16.66666674%}.tile.is-3{flex:none;width:25%}.tile.is-4{flex:none;width:33.33333337%}.tile.is-5{flex:none;width:41.66666674%}.tile.is-6{flex:none;width:50%}.tile.is-7{flex:none;width:58.33333337%}.tile.is-8{flex:none;width:66.66666674%}.tile.is-9{flex:none;width:75%}.tile.is-10{flex:none;width:83.33333337%}.tile.is-11{flex:none;width:91.66666674%}.tile.is-12{flex:none;width:100%}}.hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}.hero .navbar{background:none}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,0.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}.hero.is-white a.navbar-item:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white .navbar-link:hover,.hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,0.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-black a.navbar-item:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black .navbar-link:hover,.hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:0.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-light strong{color:inherit}.hero.is-light .title{color:rgba(0,0,0,0.7)}.hero.is-light .subtitle{color:rgba(0,0,0,0.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-light a.navbar-item:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light .navbar-link:hover,.hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}.hero.is-dark,.content kbd.hero{background-color:#363636;color:#fff}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-dark strong,.content kbd.hero strong{color:inherit}.hero.is-dark .title,.content kbd.hero .title{color:#fff}.hero.is-dark .subtitle,.content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}.hero.is-dark .subtitle a:not(.button),.content kbd.hero .subtitle a:not(.button),.hero.is-dark .subtitle strong,.content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-dark .navbar-menu,.content kbd.hero .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.content kbd.hero .navbar-item,.hero.is-dark .navbar-link,.content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-dark a.navbar-item:hover,.content kbd.hero a.navbar-item:hover,.hero.is-dark a.navbar-item.is-active,.content kbd.hero a.navbar-item.is-active,.hero.is-dark .navbar-link:hover,.content kbd.hero .navbar-link:hover,.hero.is-dark .navbar-link.is-active,.content kbd.hero .navbar-link.is-active{background-color:#292929;color:#fff}.hero.is-dark .tabs a,.content kbd.hero .tabs a{color:#fff;opacity:0.9}.hero.is-dark .tabs a:hover,.content kbd.hero .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a,.content kbd.hero .tabs li.is-active a{color:#363636 !important;opacity:1}.hero.is-dark .tabs.is-boxed a,.content kbd.hero .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a,.content kbd.hero .tabs.is-toggle a{color:#fff}.hero.is-dark .tabs.is-boxed a:hover,.content kbd.hero .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover,.content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.content kbd.hero .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.content kbd.hero .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#363636}.hero.is-dark.is-bold,.content kbd.hero.is-bold{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}@media screen and (max-width: 768px){.hero.is-dark.is-bold .navbar-menu,.content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}}.hero.is-primary,.docstring>section>a.hero.docs-sourcelink{background-color:#4eb5de;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-primary strong,.docstring>section>a.hero.docs-sourcelink strong{color:inherit}.hero.is-primary .title,.docstring>section>a.hero.docs-sourcelink .title{color:#fff}.hero.is-primary .subtitle,.docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}.hero.is-primary .subtitle a:not(.button),.docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),.hero.is-primary .subtitle strong,.docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-primary .navbar-menu,.docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#4eb5de}}.hero.is-primary .navbar-item,.docstring>section>a.hero.docs-sourcelink .navbar-item,.hero.is-primary .navbar-link,.docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-primary a.navbar-item:hover,.docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,.hero.is-primary a.navbar-item.is-active,.docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,.hero.is-primary .navbar-link:hover,.docstring>section>a.hero.docs-sourcelink .navbar-link:hover,.hero.is-primary .navbar-link.is-active,.docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#39acda;color:#fff}.hero.is-primary .tabs a,.docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}.hero.is-primary .tabs a:hover,.docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#4eb5de !important;opacity:1}.hero.is-primary .tabs.is-boxed a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#4eb5de}.hero.is-primary.is-bold,.docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}@media screen and (max-width: 768px){.hero.is-primary.is-bold .navbar-menu,.docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}}.hero.is-link{background-color:#2e63b8;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,0.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-link .navbar-menu{background-color:#2e63b8}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-link a.navbar-item:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link .navbar-link:hover,.hero.is-link .navbar-link.is-active{background-color:#2958a4;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:0.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{color:#2e63b8 !important;opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#2e63b8}.hero.is-link.is-bold{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}@media screen and (max-width: 768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}}.hero.is-info{background-color:#209cee;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,0.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-info .navbar-menu{background-color:#209cee}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-info a.navbar-item:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info .navbar-link:hover,.hero.is-info .navbar-link.is-active{background-color:#1190e3;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:0.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{color:#209cee !important;opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#209cee}.hero.is-info.is-bold{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}@media screen and (max-width: 768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}}.hero.is-success{background-color:#22c35b;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,0.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-success .navbar-menu{background-color:#22c35b}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-success a.navbar-item:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success .navbar-link:hover,.hero.is-success .navbar-link.is-active{background-color:#1ead51;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:0.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{color:#22c35b !important;opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#22c35b}.hero.is-success.is-bold{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}@media screen and (max-width: 768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}}.hero.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:rgba(0,0,0,0.7)}.hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-warning .navbar-menu{background-color:#ffdd57}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-warning a.navbar-item:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{color:#ffdd57 !important;opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ffdd57}.hero.is-warning.is-bold{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}@media screen and (max-width: 768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}}.hero.is-danger{background-color:#da0b00;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-danger .navbar-menu{background-color:#da0b00}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-danger a.navbar-item:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger .navbar-link.is-active{background-color:#c10a00;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:0.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{color:#da0b00 !important;opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#da0b00}.hero.is-danger.is-bold{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}@media screen and (max-width: 768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}}.hero.is-small .hero-body,#documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{.hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{.hero.is-large .hero-body{padding:18rem 6rem}}.hero.is-halfheight .hero-body,.hero.is-fullheight .hero-body,.hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}.hero.is-halfheight .hero-body>.container,.hero.is-fullheight .hero-body>.container,.hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}.hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){.hero-buttons .button{display:flex}.hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{.hero-buttons{display:flex;justify-content:center}.hero-buttons .button:not(:last-child){margin-right:1.5rem}}.hero-head,.hero-foot{flex-grow:0;flex-shrink:0}.hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{.hero-body{padding:3rem 3rem}}.section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){.section{padding:3rem 3rem}.section.is-medium{padding:9rem 4.5rem}.section.is-large{padding:18rem 6rem}}.footer{background-color:#fafafa;padding:3rem 1.5rem 6rem}h1 .docs-heading-anchor,h1 .docs-heading-anchor:hover,h1 .docs-heading-anchor:visited,h2 .docs-heading-anchor,h2 .docs-heading-anchor:hover,h2 .docs-heading-anchor:visited,h3 .docs-heading-anchor,h3 .docs-heading-anchor:hover,h3 .docs-heading-anchor:visited,h4 .docs-heading-anchor,h4 .docs-heading-anchor:hover,h4 .docs-heading-anchor:visited,h5 .docs-heading-anchor,h5 .docs-heading-anchor:hover,h5 .docs-heading-anchor:visited,h6 .docs-heading-anchor,h6 .docs-heading-anchor:hover,h6 .docs-heading-anchor:visited{color:#222}h1 .docs-heading-anchor-permalink,h2 .docs-heading-anchor-permalink,h3 .docs-heading-anchor-permalink,h4 .docs-heading-anchor-permalink,h5 .docs-heading-anchor-permalink,h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}h1 .docs-heading-anchor-permalink::before,h2 .docs-heading-anchor-permalink::before,h3 .docs-heading-anchor-permalink::before,h4 .docs-heading-anchor-permalink::before,h5 .docs-heading-anchor-permalink::before,h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}h1:hover .docs-heading-anchor-permalink,h2:hover .docs-heading-anchor-permalink,h3:hover .docs-heading-anchor-permalink,h4:hover .docs-heading-anchor-permalink,h5:hover .docs-heading-anchor-permalink,h6:hover .docs-heading-anchor-permalink{visibility:visible}.docs-dark-only{display:none !important}pre{position:relative;overflow:hidden}pre code,pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}pre code:first-of-type,pre code.hljs:first-of-type{padding-top:0.5rem !important}pre code:last-of-type,pre code.hljs:last-of-type{padding-bottom:0.5rem !important}pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#222;cursor:pointer;text-align:center}pre .copy-button:focus,pre .copy-button:hover{opacity:1;background:rgba(34,34,34,0.1);color:#2e63b8}pre .copy-button.success{color:#259a12;opacity:1}pre .copy-button.error{color:#cb3c33;opacity:1}pre:hover .copy-button{opacity:1}.admonition{background-color:#b5b5b5;border-style:solid;border-width:1px;border-color:#363636;border-radius:4px;font-size:1rem}.admonition strong{color:currentColor}.admonition.is-small,#documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}.admonition.is-medium{font-size:1.25rem}.admonition.is-large{font-size:1.5rem}.admonition.is-default{background-color:#b5b5b5;border-color:#363636}.admonition.is-default>.admonition-header{background-color:#363636;color:#fff}.admonition.is-default>.admonition-body{color:#fff}.admonition.is-info{background-color:#def0fc;border-color:#209cee}.admonition.is-info>.admonition-header{background-color:#209cee;color:#fff}.admonition.is-info>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-success{background-color:#bdf4d1;border-color:#22c35b}.admonition.is-success>.admonition-header{background-color:#22c35b;color:#fff}.admonition.is-success>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-warning{background-color:#fff3c5;border-color:#ffdd57}.admonition.is-warning>.admonition-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.admonition.is-warning>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-danger{background-color:#ffaba7;border-color:#da0b00}.admonition.is-danger>.admonition-header{background-color:#da0b00;color:#fff}.admonition.is-danger>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-compat{background-color:#bdeff5;border-color:#1db5c9}.admonition.is-compat>.admonition-header{background-color:#1db5c9;color:#fff}.admonition.is-compat>.admonition-body{color:rgba(0,0,0,0.7)}.admonition-header{color:#fff;background-color:#363636;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}details.admonition.is-details>.admonition-header{list-style:none}details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}.admonition-body{color:#222;padding:0.5rem .75rem}.admonition-body pre{background-color:#f5f5f5}.admonition-body code{background-color:rgba(0,0,0,0.05)}.docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #dbdbdb;box-shadow:2px 2px 3px rgba(10,10,10,0.1);max-width:100%}.docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#f5f5f5;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #dbdbdb}.docstring>header code{background-color:transparent}.docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}.docstring>header .docstring-binding{margin-right:0.3em}.docstring>header .docstring-category{margin-left:0.3em}.docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #dbdbdb}.docstring>section:last-child{border-bottom:none}.docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}.docstring>section>a.docs-sourcelink:focus{opacity:1 !important}.docstring:hover>section>a.docs-sourcelink{opacity:0.2}.docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}.docstring>section:hover a.docs-sourcelink{opacity:1}.documenter-example-output{background-color:#fff}.outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#ffaba7;color:rgba(0,0,0,0.7);border-bottom:3px solid #da0b00;padding:10px 35px;text-align:center;font-size:15px}.outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}.outdated-warning-overlay a{color:#2e63b8}.outdated-warning-overlay a:hover{color:#363636}.content pre{border:1px solid #dbdbdb}.content code{font-weight:inherit}.content a code{color:#2e63b8}.content h1 code,.content h2 code,.content h3 code,.content h4 code,.content h5 code,.content h6 code{color:#222}.content table{display:block;width:initial;max-width:100%;overflow-x:auto}.content blockquote>ul:first-child,.content blockquote>ol:first-child,.content .admonition-body>ul:first-child,.content .admonition-body>ol:first-child{margin-top:0}pre,code{font-variant-ligatures:no-contextual}.breadcrumb a.is-disabled{cursor:default;pointer-events:none}.breadcrumb a.is-disabled,.breadcrumb a.is-disabled:hover{color:#222}.hljs{background:initial !important}.katex .katex-mathml{top:0;right:0}.katex-display,mjx-container,.MathJax_Display{margin:0.5em 0 !important}html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}li.no-marker{list-style:none}#documenter .docs-main>article{overflow-wrap:break-word}#documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){#documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){#documenter .docs-main{width:100%}#documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}#documenter .docs-main>header,#documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}#documenter .docs-main header.docs-navbar{background-color:#fff;border-bottom:1px solid #dbdbdb;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}#documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1}#documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}#documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}#documenter .docs-main header.docs-navbar .docs-right .docs-icon,#documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}#documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}#documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}#documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #bbb;transition-duration:0.7s;-webkit-transition-duration:0.7s}#documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}#documenter .docs-main section.footnotes{border-top:1px solid #dbdbdb}#documenter .docs-main section.footnotes li .tag:first-child,#documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,#documenter .docs-main section.footnotes li .content kbd:first-child,.content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}#documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #dbdbdb;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){#documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}#documenter .docs-main .docs-footer .docs-footer-nextpage,#documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}#documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}#documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}#documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}#documenter .docs-sidebar{display:flex;flex-direction:column;color:#0a0a0a;background-color:#f5f5f5;border-right:1px solid #dbdbdb;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}#documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #bbb}@media screen and (min-width: 1056px){#documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){#documenter .docs-sidebar{left:0;top:0}}#documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}#documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}#documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}#documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}#documenter .docs-sidebar .docs-package-name a,#documenter .docs-sidebar .docs-package-name a:hover{color:#0a0a0a}#documenter .docs-sidebar .docs-version-selector{border-top:1px solid #dbdbdb;display:none;padding:0.5rem}#documenter .docs-sidebar .docs-version-selector.visible{display:flex}#documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #dbdbdb;padding-bottom:1.5rem}#documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}#documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}#documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}#documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}#documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}#documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}#documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}#documenter .docs-sidebar ul.docs-menu .tocitem,#documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#0a0a0a;background:#f5f5f5}#documenter .docs-sidebar ul.docs-menu a.tocitem:hover,#documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#0a0a0a;background-color:#ebebeb}#documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #dbdbdb;border-bottom:1px solid #dbdbdb;background-color:#fff}#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#fff;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#ebebeb;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}#documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}#documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}#documenter .docs-sidebar form.docs-search>input{width:14.4rem}#documenter .docs-sidebar #documenter-search-query{color:#707070;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){#documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#ccc}}@media screen and (max-width: 1055px){#documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#ccc}}kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(0,0,0,0.6);box-shadow:0 2px 0 1px rgba(0,0,0,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}.search-min-width-50{min-width:50%}.search-min-height-100{min-height:100%}.search-modal-card-body{max-height:calc(100vh - 15rem)}.search-result-link{border-radius:0.7em;transition:all 300ms}.search-result-link:hover,.search-result-link:focus{background-color:rgba(0,128,128,0.1)}.search-result-link .property-search-result-badge,.search-result-link .search-filter{transition:all 300ms}.property-search-result-badge,.search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}.search-result-link:hover .property-search-result-badge,.search-result-link:hover .search-filter,.search-result-link:focus .property-search-result-badge,.search-result-link:focus .search-filter{color:#f1f5f9;background-color:#333}.search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}.search-filter:hover,.search-filter:focus{color:#333}.search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}.search-filter-selected:hover,.search-filter-selected:focus{color:#f5f5f5}.search-result-highlight{background-color:#ffdd57;color:black}.search-divider{border-bottom:1px solid #dbdbdb}.search-result-title{width:85%;color:#333}.search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}#search-modal .modal-card-body::-webkit-scrollbar,#search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}#search-modal .modal-card-body::-webkit-scrollbar-thumb,#search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}#search-modal .modal-card-body::-webkit-scrollbar-track,#search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}.w-100{width:100%}.gap-2{gap:0.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.ansi span.sgr1{font-weight:bolder}.ansi span.sgr2{font-weight:lighter}.ansi span.sgr3{font-style:italic}.ansi span.sgr4{text-decoration:underline}.ansi span.sgr7{color:#fff;background-color:#222}.ansi span.sgr8{color:transparent}.ansi span.sgr8 span{color:transparent}.ansi span.sgr9{text-decoration:line-through}.ansi span.sgr30{color:#242424}.ansi span.sgr31{color:#a7201f}.ansi span.sgr32{color:#066f00}.ansi span.sgr33{color:#856b00}.ansi span.sgr34{color:#2149b0}.ansi span.sgr35{color:#7d4498}.ansi span.sgr36{color:#007989}.ansi span.sgr37{color:gray}.ansi span.sgr40{background-color:#242424}.ansi span.sgr41{background-color:#a7201f}.ansi span.sgr42{background-color:#066f00}.ansi span.sgr43{background-color:#856b00}.ansi span.sgr44{background-color:#2149b0}.ansi span.sgr45{background-color:#7d4498}.ansi span.sgr46{background-color:#007989}.ansi span.sgr47{background-color:gray}.ansi span.sgr90{color:#616161}.ansi span.sgr91{color:#cb3c33}.ansi span.sgr92{color:#0e8300}.ansi span.sgr93{color:#a98800}.ansi span.sgr94{color:#3c5dcd}.ansi span.sgr95{color:#9256af}.ansi span.sgr96{color:#008fa3}.ansi span.sgr97{color:#f5f5f5}.ansi span.sgr100{background-color:#616161}.ansi span.sgr101{background-color:#cb3c33}.ansi span.sgr102{background-color:#0e8300}.ansi span.sgr103{background-color:#a98800}.ansi span.sgr104{background-color:#3c5dcd}.ansi span.sgr105{background-color:#9256af}.ansi span.sgr106{background-color:#008fa3}.ansi span.sgr107{background-color:#f5f5f5}code.language-julia-repl>span.hljs-meta{color:#066f00;font-weight:bolder}/*! + Theme: Default + Description: Original highlight.js style + Author: (c) Ivan Sagalaev + Maintainer: @highlightjs/core-team + Website: https://highlightjs.org/ + License: see project LICENSE + Touched: 2021 +*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#F3F3F3;color:#444}.hljs-comment{color:#697070}.hljs-tag,.hljs-punctuation{color:#444a}.hljs-tag .hljs-name,.hljs-tag .hljs-attr{color:#444}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta .hljs-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-operator,.hljs-selector-pseudo{color:#ab5656}.hljs-literal{color:#695}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} diff --git a/previews/PR2274/assets/themeswap.js b/previews/PR2274/assets/themeswap.js new file mode 100644 index 0000000000..9f5eebe6aa --- /dev/null +++ b/previews/PR2274/assets/themeswap.js @@ -0,0 +1,84 @@ +// Small function to quickly swap out themes. Gets put into the tag.. +function set_theme_from_local_storage() { + // Initialize the theme to null, which means default + var theme = null; + // If the browser supports the localstorage and is not disabled then try to get the + // documenter theme + if (window.localStorage != null) { + // Get the user-picked theme from localStorage. May be `null`, which means the default + // theme. + theme = window.localStorage.getItem("documenter-theme"); + } + // Check if the users preference is for dark color scheme + var darkPreference = + window.matchMedia("(prefers-color-scheme: dark)").matches === true; + // Initialize a few variables for the loop: + // + // - active: will contain the index of the theme that should be active. Note that there + // is no guarantee that localStorage contains sane values. If `active` stays `null` + // we either could not find the theme or it is the default (primary) theme anyway. + // Either way, we then need to stick to the primary theme. + // + // - disabled: style sheets that should be disabled (i.e. all the theme style sheets + // that are not the currently active theme) + var active = null; + var disabled = []; + var primaryLightTheme = null; + var primaryDarkTheme = null; + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // To distinguish the default (primary) theme, it needs to have the data-theme-primary + // attribute set. + if (ss.ownerNode.getAttribute("data-theme-primary") !== null) { + primaryLightTheme = themename; + } + // Check if the theme is primary dark theme so that we could store its name in darkTheme + if (ss.ownerNode.getAttribute("data-theme-primary-dark") !== null) { + primaryDarkTheme = themename; + } + // If we find a matching theme (and it's not the default), we'll set active to non-null + if (themename === theme) active = i; + // Store the style sheets of inactive themes so that we could disable them + if (themename !== theme) disabled.push(ss); + } + var activeTheme = null; + if (active !== null) { + // If we did find an active theme, we'll (1) add the theme--$(theme) class to + document.getElementsByTagName("html")[0].className = "theme--" + theme; + activeTheme = theme; + } else { + // If we did _not_ find an active theme, then we need to fall back to the primary theme + // which can either be dark or light, depending on the user's OS preference. + var activeTheme = darkPreference ? primaryDarkTheme : primaryLightTheme; + // In case it somehow happens that the relevant primary theme was not found in the + // preceding loop, we abort without doing anything. + if (activeTheme === null) { + console.error("Unable to determine primary theme."); + return; + } + // When switching to the primary light theme, then we must not have a class name + // for the tag. That's only for non-primary or the primary dark theme. + if (darkPreference) { + document.getElementsByTagName("html")[0].className = + "theme--" + activeTheme; + } else { + document.getElementsByTagName("html")[0].className = ""; + } + } + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // we'll disable all the stylesheets, except for the active one + ss.disabled = !(themename == activeTheme); + } +} +set_theme_from_local_storage(); diff --git a/previews/PR2274/assets/warner.js b/previews/PR2274/assets/warner.js new file mode 100644 index 0000000000..3f6f5d0083 --- /dev/null +++ b/previews/PR2274/assets/warner.js @@ -0,0 +1,52 @@ +function maybeAddWarning() { + // DOCUMENTER_NEWEST is defined in versions.js, DOCUMENTER_CURRENT_VERSION and DOCUMENTER_STABLE + // in siteinfo.js. + // If either of these are undefined something went horribly wrong, so we abort. + if ( + window.DOCUMENTER_NEWEST === undefined || + window.DOCUMENTER_CURRENT_VERSION === undefined || + window.DOCUMENTER_STABLE === undefined + ) { + return; + } + + // Current version is not a version number, so we can't tell if it's the newest version. Abort. + if (!/v(\d+\.)*\d+/.test(window.DOCUMENTER_CURRENT_VERSION)) { + return; + } + + // Current version is newest version, so no need to add a warning. + if (window.DOCUMENTER_NEWEST === window.DOCUMENTER_CURRENT_VERSION) { + return; + } + + // Add a noindex meta tag (unless one exists) so that search engines don't index this version of the docs. + if (document.body.querySelector('meta[name="robots"]') === null) { + const meta = document.createElement("meta"); + meta.name = "robots"; + meta.content = "noindex"; + + document.getElementsByTagName("head")[0].appendChild(meta); + } + + const div = document.createElement("div"); + div.classList.add("outdated-warning-overlay"); + const closer = document.createElement("button"); + closer.classList.add("outdated-warning-closer", "delete"); + closer.addEventListener("click", function () { + document.body.removeChild(div); + }); + const href = window.documenterBaseURL + "/../" + window.DOCUMENTER_STABLE; + div.innerHTML = + 'This documentation is not for the latest stable release, but for either the development version or an older release.
Click here to go to the documentation for the latest stable release.'; + div.appendChild(closer); + document.body.appendChild(div); +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", maybeAddWarning); +} else { + maybeAddWarning(); +} diff --git a/previews/PR2274/background/duality/index.html b/previews/PR2274/background/duality/index.html new file mode 100644 index 0000000000..c777f2af3b --- /dev/null +++ b/previews/PR2274/background/duality/index.html @@ -0,0 +1,80 @@ + +Duality · MathOptInterface

Duality

Conic duality is the starting point for MOI's duality conventions. When all functions are affine (or coordinate projections), and all constraint sets are closed convex cones, the model may be called a conic optimization problem.

For a minimization problem in geometric conic form, the primal is:

\[\begin{align} +& \min_{x \in \mathbb{R}^n} & a_0^T x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m +\end{align}\]

and the dual is a maximization problem in standard conic form:

\[\begin{align} +& \max_{y_1, \ldots, y_m} & -\sum_{i=1}^m b_i^T y_i + b_0 +\\ +& \;\;\text{s.t.} & a_0 - \sum_{i=1}^m A_i^T y_i & = 0 +\\ +& & y_i & \in \mathcal{C}_i^* & i = 1 \ldots m +\end{align}\]

where each $\mathcal{C}_i$ is a closed convex cone and $\mathcal{C}_i^*$ is its dual cone.

For a maximization problem in geometric conic form, the primal is:

\[\begin{align} +& \max_{x \in \mathbb{R}^n} & a_0^T x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m +\end{align}\]

and the dual is a minimization problem in standard conic form:

\[\begin{align} +& \min_{y_1, \ldots, y_m} & \sum_{i=1}^m b_i^T y_i + b_0 +\\ +& \;\;\text{s.t.} & a_0 + \sum_{i=1}^m A_i^T y_i & = 0 +\\ +& & y_i & \in \mathcal{C}_i^* & i = 1 \ldots m +\end{align}\]

A linear inequality constraint $a^T x + b \ge c$ is equivalent to $a^T x + b - c \in \mathbb{R}_+$, and $a^T x + b \le c$ is equivalent to $a^T x + b - c \in \mathbb{R}_-$. Variable-wise constraints are affine constraints with the appropriate identity mapping in place of $A_i$.

For the special case of minimization LPs, the MOI primal form can be stated as:

\[\begin{align} +& \min_{x \in \mathbb{R}^n} & a_0^T x &+ b_0 +\\ +& \;\;\text{s.t.} +&A_1 x & \ge b_1\\ +&& A_2 x & \le b_2\\ +&& A_3 x & = b_3 +\end{align}\]

By applying the stated transformations to conic form, taking the dual, and transforming back into linear inequality form, one obtains the following dual:

\[\begin{align} +& \max_{y_1,y_2,y_3} & b_1^Ty_1 + b_2^Ty_2 + b_3^Ty_3 &+ b_0 +\\ +& \;\;\text{s.t.} +&A_1^Ty_1 + A_2^Ty_2 + A_3^Ty_3 & = a_0\\ +&& y_1 &\ge 0\\ +&& y_2 &\le 0 +\end{align}\]

For maximization LPs, the MOI primal form can be stated as:

\[\begin{align} +& \max_{x \in \mathbb{R}^n} & a_0^T x &+ b_0 +\\ +& \;\;\text{s.t.} +&A_1 x & \ge b_1\\ +&& A_2 x & \le b_2\\ +&& A_3 x & = b_3 +\end{align}\]

and similarly, the dual is:

\[\begin{align} +& \min_{y_1,y_2,y_3} & -b_1^Ty_1 - b_2^Ty_2 - b_3^Ty_3 &+ b_0 +\\ +& \;\;\text{s.t.} +&A_1^Ty_1 + A_2^Ty_2 + A_3^Ty_3 & = -a_0\\ +&& y_1 &\ge 0\\ +&& y_2 &\le 0 +\end{align}\]

Warning

For the LP case, the signs of the feasible dual variables depend only on the sense of the corresponding primal inequality and not on the objective sense.

Duality and scalar product

The scalar product is different from the canonical one for the sets PositiveSemidefiniteConeTriangle, LogDetConeTriangle, RootDetConeTriangle.

If the set $C_i$ of the section Duality is one of these three cones, then the rows of the matrix $A_i$ corresponding to off-diagonal entries are twice the value of the coefficients field in the VectorAffineFunction for the corresponding rows. See PositiveSemidefiniteConeTriangle for details.

Dual for problems with quadratic functions

Quadratic Programs (QPs)

For quadratic programs with only affine conic constraints,

\[\begin{align*} +& \min_{x \in \mathbb{R}^n} & \frac{1}{2}x^TQ_0x + a_0^T x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m. +\end{align*}\]

with cones $\mathcal{C}_i \subseteq \mathbb{R}^{m_i}$ for $i = 1, \ldots, m$, consider the Lagrangian function

\[L(x, y) = \frac{1}{2}x^TQ_0x + a_0^T x + b_0 - \sum_{i = 1}^m y_i^T (A_i x + b_i).\]

Let $z(y)$ denote $\sum_{i = 1}^m A_i^T y_i - a_0$, the Lagrangian can be rewritten as

\[L(x, y) = \frac{1}{2}{x}^TQ_0x - z(y)^T x + b_0 - \sum_{i = 1}^m y_i^T b_i.\]

The condition $\nabla_x L(x, y) = 0$ gives

\[0 = \nabla_x L(x, y) = Q_0x + a_0 - \sum_{i = 1}^m y_i^T b_i\]

which gives $Q_0x = z(y)$. This allows to obtain that

\[\min_{x \in \mathbb{R}^n} L(x, y) = -\frac{1}{2}x^TQ_0x + b_0 - \sum_{i = 1}^m y_i^T b_i\]

so the dual problem is

\[\max_{y_i \in \mathcal{C}_i^*} \min_{x \in \mathbb{R}^n} -\frac{1}{2}x^TQ_0x + b_0 - \sum_{i = 1}^m y_i^T b_i.\]

If $Q_0$ is invertible, we have $x = Q_0^{-1}z(y)$ hence

\[\min_{x \in \mathbb{R}^n} L(x, y) = -\frac{1}{2}z(y)^TQ_0^{-1}z(y) + b_0 - \sum_{i = 1}^m y_i^T b_i\]

so the dual problem is

\[\max_{y_i \in \mathcal{C}_i^*} -\frac{1}{2}z(y)^TQ_0^{-1}z(y) + b_0 - \sum_{i = 1}^m y_i^T b_i.\]

Quadratically Constrained Quadratic Programs (QCQPs)

Given a problem with both quadratic function and quadratic objectives:

\[\begin{align*} +& \min_{x \in \mathbb{R}^n} & \frac{1}{2}x^TQ_0x + a_0^T x + b_0 +\\ +& \;\;\text{s.t.} & \frac{1}{2}x^TQ_ix + a_i^T x + b_i & \in \mathcal{C}_i & i = 1 \ldots m. +\end{align*}\]

with cones $\mathcal{C}_i \subseteq \mathbb{R}$ for $i = 1 \ldots m$, consider the Lagrangian function

\[L(x, y) = \frac{1}{2}x^TQ_0x + a_0^T x + b_0 - \sum_{i = 1}^m y_i (\frac{1}{2}x^TQ_ix + a_i^T x + b_i)\]

A pair of primal-dual variables $(x^\star, y^\star)$ is optimal if

  • $x^\star$ is a minimizer of

    \[\min_{x \in \mathbb{R}^n} L(x, y^\star).\]

    That is,

    \[0 = \nabla_x L(x, y^\star) = Q_0x + a_0 - \sum_{i = 1}^m y_i^\star (Q_ix + a_i).\]

  • and $y^\star$ is a maximizer of

    \[\max_{y_i \in \mathcal{C}_i^*} L(x^\star, y).\]

    That is, for all $i = 1, \ldots, m$, $\frac{1}{2}x^TQ_ix + a_i^T x + b_i$ is either zero or in the normal cone of $\mathcal{C}_i^*$ at $y^\star$. For instance, if $\mathcal{C}_i$ is $\{ z \in \mathbb{R} : z \le 0 \}$, this means that if $\frac{1}{2}x^TQ_ix + a_i^T x + b_i$ is nonzero at $x^\star$ then $y_i^\star = 0$. This is the classical complementary slackness condition.

If $\mathcal{C}_i$ is a vector set, the discussion remains valid with $y_i(\frac{1}{2}x^TQ_ix + a_i^T x + b_i)$ replaced with the scalar product between $y_i$ and the vector of scalar-valued quadratic functions.

Dual for square semidefinite matrices

The set PositiveSemidefiniteConeTriangle is a self-dual. That is, querying ConstraintDual of a PositiveSemidefiniteConeTriangle constraint returns a vector that is itself a member of PositiveSemidefiniteConeTriangle.

However, the dual of PositiveSemidefiniteConeSquare is not so straight forward. This section explains the duality convention we use, and how it is derived.

Info

If you have a PositiveSemidefiniteConeSquare constraint, the result matrix $A$ from ConstraintDual is not positive semidefinite. However, $A + A^\top$ is positive semidefinite.

Let $\mathcal{S}_+$ be the cone of symmetric semidefinite matrices in the $\frac{n(n+1)}{2}$ dimensional space of symmetric $\mathbb{R}^{n \times n}$ matrices. That is, $\mathcal{S}_+$ is the set PositiveSemidefiniteConeTriangle. It is well known that $\mathcal{S}_+$ is a self-dual proper cone.

Let $\mathcal{P}_+$ be the cone of symmetric semidefinite matrices in the $n^2$ dimensional space of $\mathbb{R}^{n \times n}$ matrices. That is $\mathcal{P}_+$ is the set PositiveSemidefiniteConeSquare.

In addition, let $\mathcal{D}_+$ be the cone of matrices $A$ such that $A+A^\top \in \mathcal{P}_+$.

$\mathcal{P}_+$ is not proper because it is not solid (it is not $n^2$ dimensional), so it is not necessarily true that $\mathcal{P}_+^{**} = \mathcal{P}_+$.

However, this is the case, because we will show that $\mathcal{P}_+^{*} = \mathcal{D}_+$ and $\mathcal{D}_+^{*} = \mathcal{P}_+$.

First, let us see why $\mathcal{P}_+^{*} = \mathcal{D}_+$.

If $B$ is symmetric, then

\[\langle A,B \rangle = \langle A^\top, B^\top \rangle = \langle A^\top, B\rangle\]

so

\[2\langle A, B \rangle = \langle A, B \rangle + \langle A^\top, B \rangle = \langle A + A^\top , B \rangle.\]

Therefore, $\langle A,B\rangle \ge 0$ for all $B \in \mathcal{P}_+$ if and only if $\langle A+A^\top,B\rangle \ge 0$ for all $B \in \mathcal{P}_+$. Since $A+A^\top$ is symmetric, and we know that $\mathcal{S}_+$ is self-dual, we have shown that $\mathcal{P}_+^{*}$ is the set of matrices $A$ such that $A+A^\top \in \mathcal{P}_+$.

Second, let us see why $\mathcal{D}_+^{*} = \mathcal{P}_+$.

Since $A \in \mathcal{D}_+$ implies that $A^\top \in \mathcal{D}_+$, $B \in \mathcal{D}_+^{*}$ means that $\langle A+A^\top,B\rangle \ge 0$ for all $A \in \mathcal{D}_+$, and hence $B \in \\mathcal{P}_+$.

To see why it should be symmetric, simply notice that if $B_{i,j} < B_{j,i}$, then $\langle A,B\rangle$ can be made arbitrarily small by setting $A_{i,j} = A_{i,j} + s$ and $A_{j,i} = A_{j,i} - s$, with $s$ arbitrarily large, and $A$ stays in $\mathcal{D}_+$ because $A+A^\top$ does not change.

Typically, the primal/dual pair for semidefinite programs is presented as:

\[\begin{align} + \min & \langle C, X \rangle \\ +\text{s.t.} \;\; & \langle A_k, X\rangle = b_k \forall k \\ + & X \in \mathcal{S}_+ +\end{align}\]

with the dual

\[\begin{align} + \max & \sum_k b_k y_k \\ +\text{s.t.} \;\; & C - \sum A_k y_k \in \mathcal{S}_+ +\end{align}\]

If we allow $A_k$ to be non-symmetric, we should instead use:

\[\begin{align} + \min & \langle C, X \rangle \\ +\text{s.t.} \;\; & \langle A_k, X\rangle = b_k \forall k \\ + & X \in \mathcal{D}_+ +\end{align}\]

with the dual

\[\begin{align} + \max & \sum b_k y_k \\ +\text{s.t.} \;\; & C - \sum A_k y_k \in \mathcal{P}_+ +\end{align}\]

This is implemented as:

\[\begin{align} + \min & \langle C, Z \rangle + \langle C - C^\top, S \rangle \\ +\text{s.t.} \;\; & \langle A_k, Z \rangle + \langle A_k - A_k^\top, S \rangle = b_k \forall k \\ + & Z \in \mathcal{S}_+ +\end{align}\]

with the dual

\[\begin{align} + \max & \sum b_k y_k \\ +\text{s.t.} \;\; & C+C^\top - \sum (A_k+A_k^\top) y_k \in \mathcal{S}_+ \\ + & C-C^\top - \sum(A_k-A_k^\top) y_k = 0 +\end{align}\]

and we recover $Z = X + X^\top$.

diff --git a/previews/PR2274/background/infeasibility_certificates/index.html b/previews/PR2274/background/infeasibility_certificates/index.html new file mode 100644 index 0000000000..e3d37043ca --- /dev/null +++ b/previews/PR2274/background/infeasibility_certificates/index.html @@ -0,0 +1,28 @@ + +Infeasibility certificates · MathOptInterface

Infeasibility certificates

When given a conic problem that is infeasible or unbounded, some solvers can produce a certificate of infeasibility. This page explains what a certificate of infeasibility is, and the related conventions that MathOptInterface adopts.

Conic duality

MathOptInterface uses conic duality to define infeasibility certificates. A full explanation is given in the section Duality, but here is a brief overview.

Minimization problems

For a minimization problem in geometric conic form, the primal is:

\[\begin{align} +& \min_{x \in \mathbb{R}^n} & a_0^\top x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m, +\end{align}\]

and the dual is a maximization problem in standard conic form:

\[\begin{align} +& \max_{y_1, \ldots, y_m} & -\sum_{i=1}^m b_i^\top y_i + b_0 +\\ +& \;\;\text{s.t.} & a_0 - \sum_{i=1}^m A_i^\top y_i & = 0 +\\ +& & y_i & \in \mathcal{C}_i^* & i = 1 \ldots m, +\end{align}\]

where each $\mathcal{C}_i$ is a closed convex cone and $\mathcal{C}_i^*$ is its dual cone.

Maximization problems

For a maximization problem in geometric conic form, the primal is:

\[\begin{align} +& \max_{x \in \mathbb{R}^n} & a_0^\top x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m, +\end{align}\]

and the dual is a minimization problem in standard conic form:

\[\begin{align} +& \min_{y_1, \ldots, y_m} & \sum_{i=1}^m b_i^\top y_i + b_0 +\\ +& \;\;\text{s.t.} & a_0 + \sum_{i=1}^m A_i^\top y_i & = 0 +\\ +& & y_i & \in \mathcal{C}_i^* & i = 1 \ldots m. +\end{align}\]

Unbounded problems

A problem is unbounded if and only if:

  1. there exists a feasible primal solution
  2. the dual is infeasible.

A feasible primal solution—if one exists—can be obtained by setting ObjectiveSense to FEASIBILITY_SENSE before optimizing. Therefore, most solvers stop after they prove the dual is infeasible via a certificate of dual infeasibility, but before they have found a feasible primal solution. This is also the reason that MathOptInterface defines the DUAL_INFEASIBLE status instead of UNBOUNDED.

A certificate of dual infeasibility is an improving ray of the primal problem. That is, there exists some vector $d$ such that for all $\eta > 0$:

\[A_i (x + \eta d) + b_i \in \mathcal{C}_i,\ \ i = 1 \ldots m,\]

and (for minimization problems):

\[a_0^\top (x + \eta d) + b_0 < a_0^\top x + b_0,\]

for any feasible point $x$. The latter simplifies to $a_0^\top d < 0$. For maximization problems, the inequality is reversed, so that $a_0^\top d > 0$.

If the solver has found a certificate of dual infeasibility:

Note

The choice of whether to scale the ray $d$ to have magnitude 1 is left to the solver.

Infeasible problems

A certificate of primal infeasibility is an improving ray of the dual problem. However, because infeasibility is independent of the objective function, we first homogenize the primal problem by removing its objective.

For a minimization problem, a dual improving ray is some vector $d$ such that for all $\eta > 0$:

\[\begin{align} +-\sum_{i=1}^m A_i^\top (y_i + \eta d_i) & = 0 \\ +(y_i + \eta d_i) & \in \mathcal{C}_i^* & i = 1 \ldots m, +\end{align}\]

and:

\[-\sum_{i=1}^m b_i^\top (y_i + \eta d_i) > -\sum_{i=1}^m b_i^\top y_i,\]

for any feasible dual solution $y$. The latter simplifies to $-\sum_{i=1}^m b_i^\top d_i > 0$. For a maximization problem, the inequality is $\sum_{i=1}^m b_i^\top d_i < 0$. (Note that these are the same inequality, modulo a - sign.)

If the solver has found a certificate of primal infeasibility:

Note

The choice of whether to scale the ray $d$ to have magnitude 1 is left to the solver.

Infeasibility certificates of variable bounds

Many linear solvers (for example, Gurobi) do not provide explicit access to the primal infeasibility certificate of a variable bound. However, given a set of linear constraints:

\[\begin{align} +l_A \le A x \le u_A \\ +l_x \le x \le u_x, +\end{align}\]

the primal certificate of the variable bounds can be computed using the primal certificate associated with the affine constraints, $d$. (Note that $d$ will have one element for each row of the $A$ matrix, and that some or all of the elements in the vectors $l_A$ and $u_A$ may be $\pm \infty$. If both $l_A$ and $u_A$ are finite for some row, the corresponding element in `d must be 0.)

Given $d$, compute $\bar{d} = d^\top A$. If the bound is finite, a certificate for the lower variable bound of $x_i$ is $\max\{\bar{d}_i, 0\}$, and a certificate for the upper variable bound is $\min\{\bar{d}_i, 0\}$.

diff --git a/previews/PR2274/background/motivation/index.html b/previews/PR2274/background/motivation/index.html new file mode 100644 index 0000000000..003a79b46a --- /dev/null +++ b/previews/PR2274/background/motivation/index.html @@ -0,0 +1,2 @@ + +Motivation · MathOptInterface

Motivation

MathOptInterface (MOI) is a replacement for MathProgBase, the first-generation abstraction layer for mathematical optimization previously used by JuMP and Convex.jl.

To address a number of limitations of MathProgBase, MOI is designed to:

  • Be simple and extensible
    • unifying linear, quadratic, and conic optimization,
    • seamlessly facilitating extensions to essentially arbitrary constraints and functions (for example, indicator constraints, complementarity constraints, and piecewise-linear functions)
  • Be fast
    • by allowing access to a solver's in-memory representation of a problem without writing intermediate files (when possible)
    • by using multiple dispatch and avoiding requiring containers of non-concrete types
  • Allow a solver to return multiple results (for example, a pool of solutions)
  • Allow a solver to return extra arbitrary information via attributes (for example, variable- and constraint-wise membership in an irreducible inconsistent subset for infeasibility analysis)
  • Provide a greatly expanded set of status codes explaining what happened during the optimization procedure
  • Enable a solver to more precisely specify which problem classes it supports
  • Enable both primal and dual warm starts
  • Enable adding and removing both variables and constraints by indices that are not required to be consecutive
  • Enable any modification that the solver supports to an existing model
  • Avoid requiring the solver wrapper to store an additional copy of the problem data
diff --git a/previews/PR2274/background/naming_conventions/index.html b/previews/PR2274/background/naming_conventions/index.html new file mode 100644 index 0000000000..12ca1a1191 --- /dev/null +++ b/previews/PR2274/background/naming_conventions/index.html @@ -0,0 +1,2 @@ + +Naming conventions · MathOptInterface

Naming conventions

MOI follows several conventions for naming functions and structures. These should also be followed by packages extending MOI.

Sets

Sets encode the structure of constraints. Their names should follow the following conventions:

  • Abstract types in the set hierarchy should begin with Abstract and end in Set, for example, AbstractScalarSet, AbstractVectorSet.
  • Vector-valued conic sets should end with Cone, for example, NormInfinityCone, SecondOrderCone.
  • Vector-valued Cartesian products should be plural and not end in Cone, for example, Nonnegatives, not NonnegativeCone.
  • Matrix-valued conic sets should provide two representations: ConeSquare and ConeTriangle, for example, RootDetConeTriangle and RootDetConeSquare. See Matrix cones for more details.
  • Scalar sets should be singular, not plural, for example, Integer, not Integers.
  • As much as possible, the names should follow established conventions in the domain where this set is used: for instance, convex sets should have names close to those of CVX, and constraint-programming sets should follow MiniZinc's constraints.
diff --git a/previews/PR2274/changelog/index.html b/previews/PR2274/changelog/index.html new file mode 100644 index 0000000000..d483786946 --- /dev/null +++ b/previews/PR2274/changelog/index.html @@ -0,0 +1,30 @@ + +Release notes · MathOptInterface

Release notes

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

v1.20.0 (September 7, 2023)

Added

Other

  • Updated dependencies (#2258)
  • Improved performance of ScalarNonlinearFunction utilities (#2259)
  • Fixed docstrings (#2261)

v1.19.0 (August 15, 2023)

Added

Fixed

Other

  • Added extensions to solver-tests.yml (#2229)
  • Refactored test/Benchmarks (#2234)
  • Fixed warnings in tests (#2241) (#2243)
  • Small refactoring of bridges for upcoming VectorNonlinearFunction (#2244) (#2245)
  • Fixed various typos (#2251) (#2255)
  • Partitioned how we run the tests on GitHub actions (#2252) (#2253)

v1.18.0 (June 23, 2023)

Added

Fixed

  • Fixed a missing @require in MOI.Test (#2195) (#2196)
  • Fixed incorrect usage of Utilities.operate! in bridges (#2207) (#2216)
  • Fixed splatting nonlinear expression with univariate operator (#2221)

Other

  • Removed unused argument names (#2199)
  • Reduced memory requirement for tests (#2204)
  • Refactored Utilities.promote_operation (#2206)
  • Improved code style in Utilities/mutable_arithmetics.jl (#2209)
  • Refactored various methods in Utilities/functions.jl (#2208) (#2212) (#2213) (#2214) (#2215)

v1.17.1 (June 6, 2023)

Fixed

Other

  • Added documentation for enum instances (#2186)
  • Updated chatroom links in documentation (#2188)
  • Changed the documentation to build on Julia v1.9 (#2191)

v1.17.0 (June 1, 2023)

Added

Fixed

  • Fixed support for external sets in Utilities.loadfromstring! (#2177)
  • Fixed promote_operation for ScalarNonlinearFunction (#2179)
  • Fixed two issues in FileFormats.LP when reading files with quadratic functions (#2182) (#2184)

v1.16.0 (May 16, 2023)

Added

Fixed

  • Fixed support for Julia v1.9 to work around a bug in the upstream Julia compiler (#2161) (#2163)
  • Fixed a correctness bug in Bridges.Constraint.HermitianToSymmetricPSDBridge (#2171)
  • Fixed convert(::VariableIndex, ::ScalarAffineFunction) when the function has terms with 0coefficients (#2173)

Other

  • Fixed solver-tests.yml (#2157)
  • Updated documentation links to developer chatroom (#2160)
  • Added various tests for bridges (#2156)
  • Added checklists to the developer documentation (#2167) (#2168)

v1.15.1 (April 25, 2023)

Fixed

  • Fixed deleting a variable in a bridged objective (#2150)

v1.15.0 (April 19, 2023)

Added

Fixed

Other

  • Add a test for variables in one-sided open Interval sets (#2133)
  • Minor style fixes in the source code (#2148)

v1.14.1 (April 6, 2023)

Fixed

Other

  • Added a warning when an ambiguous string is passed to exclude in Test.runtests (#2136)

v1.14.0 (April 4, 2023)

Added

Fixed

  • Fixed ResultCount when parsing .sol files in FileFormats.NL (#2130)

v1.13.2 (March 21, 2023)

Fixed

Other

  • Fixed typos in the documentation (#2114)
  • Functions now print to the REPL in algebraic form. This is potentially breaking if you have tests which rely on a specific String form of MOI functions. (#2112) (#2126)

v1.13.1 (March 3, 2023)

Other

  • Added the Google style guide to the documentation linter Vale, and fixed the resulting warnings (#2110)
  • Improved the docstrings in src/functions.jl (#2108)

v1.13.0 (February 28, 2023)

Added

Fixed

Other

  • Added tests for vector-valued objective functions in FileFormats.MOF (#2093)
  • Used and documented preference for import MathOptInterface as MOI (#2096)
  • Fix and test links in the documentation with linkcheck = true (#2098)
  • Improved docstrings of sets in src/sets.jl (#2099)
  • Skip checking flakey links in documentation with linkcheck_ignore (#2103)

v1.12.0 (February 10, 2023)

Added

Fixed

  • Fixed a number of constraint bridges so that Bridges.final_touch can be called multiple times without forcing a rebuild of the reformulation (#2089)

Other

v1.11.5 (January 24, 2023)

Fixed

  • Fixed a bug writing .lp files with an off-diagonal quadratic objective (#2082)

Other

  • Added SnoopPrecompile directives for reduced time-to-first-X in Julia v1.9 (#2080)

v1.11.4 (January 12, 2023)

Fixed

  • Fixed a bug reading .lp files with an Integer section (#2078)

v1.11.3 (January 12, 2023)

Fixed

  • Fixed a performance bug when deleting a vector of constraints (#2072)
  • Fixed a bug reading .lp files with terms like x -1 y (#2076)

Other

  • Documented the two-argument method of optimize! (#2074)

v1.11.2 (January 2, 2023)

Fixed

  • Fixed a bug reading .mof.json files with ConstraintName set for VariableIndex constraints (#2066)
  • Fixed a bug reading .mof.json files with nonlinear objectives and no constraints (#2068)

v1.11.1 (December 22, 2022)

Fixed

  • Fixed a bug reading .mof.json files with integer coefficients for affine and quadratic functions (#2063)

v1.11.0 (December 2, 2022)

Added

Other

  • Tidied these release notes (#2055)

v1.10.0 (November 22, 2022)

Added

Fixed

  • Fixed Bridges.Objective.SlackBridge when the objective function is complex-valued (#2036) (#2038)
  • Fixed docstring of Test.runtests to clarify the warn_unsupported argument (#2037)
  • Fixed reading of free variables in FileFormats.LP (#2044)
  • Fixed numerous edge cases reading files from QPLIB using FileFormats.LP (#2042) (#2044)
  • Fixed situations in which x^y returns a complex value in Nonlinear (#2050)

Other

  • Improved the error message thrown when a user-defined nonlinear function does not accept splatted input (#2032)
  • Removed specialized iterators for keys and values in Utilities.CleverDicts (#2051)

v1.9.0 (October 29, 2022)

Added

  • Added default fallback for getting ListOfConstraintIndices and NumberOfConstraints when the constraint type is unsupported by the model (#2021)
  • Added support for min and max in nonlinear expressions (#2023)
  • Added support for Indicator{EqualTo{T}} constraints in FileFormats.MPS (#2022)
  • Added default fallback for write_to_file and read_from_file (#2029)

Fixed

  • Fixed Constraint.ZeroOneBridge by adding new bounds as affine constraints instead of variable bounds (#1879)
  • Fixed reading free rows in FileFormats.MPS files (#2009)
  • Fixed parsing of OBJSENSE blocks in FileFormats.MPS files (#2016) (#2019)
  • Fixed the parsing of deeply nested nonlinear expressions by removing the use of recursion (#2020)
  • Fixed the requirements check in Test.test_constrainnt_get_ConstraintIndex (#2024)

v1.8.2 (September 20, 2022)

Documentation

  • Added vale as a documentation linter (#2002)
  • Improved styling of code blocks in the PDF (#1999) (#2000)
  • Fixed a number of typos in the documentation (#2001) (#2003)

v1.8.1 (September 12, 2022)

Fixed

  • Fixed a bug in supports(::AbstractBridgeOptimizer for constraint attributes (#1991) (#1992)

v1.8.0 (September 1, 2022)

Added

Fixed

  • Lazily construct expressions in Nonlinear so that expressions are updated when Nonlinear.Parameter values are updated (#1984)
  • Allow NORM_LIMIT as a TerminationStatus for unbounded problems in Test (#1990)

v1.7.0 (August 16, 2022)

Added

Fixed

  • Fixed some missing promotion rules

Other

  • Improved the performance of Jacobian products in Nonlinear
  • Removed an un-needed copy in Utilities.modify_function
  • Various clean-ups in Bridges/bridge_optimizer.jl

v1.6.1 (July 23, 2022)

Fixed

  • Added support for ExponentialCone in MatrixOfConstraints
  • Fix PSDSquare_3 test to reflect a previously fixed bug getting the ConstraintDual of a PositiveSemidefiniteConeSquare constraint

v1.6.0 (July 2, 2022)

Added

  • Added Bridges.needs_final_touch and Bridges.final_touch
  • Added new bridges from constraint programming sets to mixed-integer linear programs:
    • AllDifferentToCountDistinctBridge
    • CountAtLeastToCountBelongsBridge
    • CountBelongsToMILPBridge
    • CountDistinctToMILPBridge
    • CountGreaterThanToMILPBridge
    • CircuitToMILPBridge

Fixed

  • Relax an instance of ::Vector to ::AbstractVector in MOI.Nonlinear
  • Fix BinPackingToMILPBridge to respect variable bounds
  • Fix SemiToBinaryBridge to throw error if other bounds are set

v1.5.0 (June 27, 2022)

Added

  • Added GetAttributeNotAllowed for solvers to indicate when getting an attribute encounters an error
  • Added Utilities.get_fallback support for ObjectiveValue and DualObjectiveValue
  • Added new bridges:
    • RootDetConeSquare to RootDetConeTriangle
    • LogDetConeSquare to LogDetConeTriangle
    • BinPacking to a mixed-integer linear program
    • Table to a mixed-integer linear program
  • Added Bridges.print_active_bridges to display the current optimal hyper-path in a Bridges.LazyBridgeOptimizer

Fixed

  • Fixed ZeroOne tests with lower and upper bounds
  • Fixed error in FileFormats.LP when reading a malformed file
  • Fixed reading of nonlinear programs in FileFormats.MOF
  • Fixed bug in ConstraintDual when using SquareBridge

Other

  • Improved documentation of nonlinear API
  • Documented duality convention for PositiveSemidefiniteConeSquare sets
  • Fixed typo in Bridges.Constraint.QuadToSOCBridge docstring

v1.4.0 (June 9, 2022)

Added

  • Added a number of sets for constraint programming:
    • AllDifferent
    • BinPacking
    • Circuit
    • CountAtLeast
    • CountBelongs
    • CountDistinct
    • CountGreaterThan
    • Cumulative
    • Path
    • Table
  • Added support for user-defined hessians in Nonlinear
  • Added Bridges.runtests to simplify the testing of bridge implementations

Fixed

  • Fixed a bug in FileFormats.NL when writing univariate *

Other

  • Began a large refactoring of the Bridges submodule, with greatly improved documentation.

v1.3.0 (May 27, 2022)

Added

  • Add MOI.Nonlinear submodule. This is a large new submodule that has been refactored from code that was in JuMP. For now, it should be considered experimental.
  • Add FileFormats.NL.SolFileResults(::IO, ::Model)
  • Add FileFormats.NL.read!(::IO, ::Model)
  • Add MOI.modify that accepts a vector of modifications

Fixed

  • Fixed a bug in Test which attempted to include non-.jl files
  • Fixed a bug in FileFormats for models with open interval constraints

Other

  • Fixed a performance issue in Utilities.DoubleDict
  • Various minor improvements to the documentation

v1.2.0 (April 25, 2022)

Added

  • Add support for the FORMAT_REW/.rew file format in FileFormats.

Fixed

  • Fix bug handling of default variable bounds in FileFormats.LP
  • Fix FileFormats.MPS to not write OBJSENSE by default since this is only supported by some readers.

v1.1.2 (March 31, 2022)

Fixed

  • Fix a range of bugs in FileFormats.LP
  • Fix reading of problem dimensions in FileFormats.SDPA

v1.1.1 (March 23, 2022)

Fixed

  • Fix bug in test_model_UpperBoundAlreadySet
  • Fix bug in test_infeasible_ tests
  • Fix bug in test_objective_ObjectiveFunction_blank
  • Relax restriction of MOI.AbstractOptimizer to MOI.ModelLike in Utilities.CachingOptimizer and instantiate.

New tests

  • Add test_conic_empty_matrix that checks conic solvers support problems with no variables.

v1.1.0 (March 2, 2022)

Added

  • Added MOI.Utilities.throw_unsupported(::UniversalFallback) for simplifying solver wrappers which copy from a UniversalFallback.

v1.0.2 (March 1, 2022)

Fixed

  • Fixed a bug in the test_model_ScalarFunctionConstantNotZero test
  • Fixed the error type when an AbstractFunctionConversionBridge cannot get or set an attribute
  • Identified a correctness bug in RSOCtoPSDBridge. We now thrown an error instead of returning an incorrect result.

v1.0.1 (February 25, 2022)

Fixed

  • Fixed a bug in which OptimizerAttributes were not copied in CachingOptimizer
  • Fixed a bug in which shift_constant did not promote mixed types of coefficients
  • Fixed a bug in which deleting a constraint of a bridged variable threw ErrorException instead of MOI.DeleteNotAllowed
  • Fixed a bug in which add_constraint in MatrixOfConstraints did not canonicalize the function
  • Fixed a bug when modifying scalar constants of a function containing a bridged variable
  • Fixed a bug in which final_touch was not always called with a CachingOptimizer

v1.0.0 (February 17, 2022)

Although tagged as a breaking release, v1.0.0 is v0.10.9 with deprecations removed, similar to how Julia 1.0 was Julia 0.7 with deprecations removed.

Breaking

  • Julia 1.6 is now the minimum supported version
  • All deprecations have been removed

Troubleshooting problems when updating

If you experience problems when updating, you are likely using previously deprecated features. (By default, Julia does not warn when you use deprecated features.)

To find the deprecated features you are using, start Julia with --depwarn=yes:

$ julia --depwarn=yes

Then install MathOptInterface v0.10.9:

julia> using Pkg
+julia> pkg"add MathOptInterface@0.10"

And then run your code. Apply any suggestions, or search the release notes below for advice on updating a specific deprecated feature.

v0.10.9 (February 16, 2022)

Added

  • Added MOI.Utilities.FreeVariables as a new VariablesConstrainer for conic solvers
  • Added MOI.default_cache for specifying the model used in CachingOptimizer

Fixed

  • Fixed LaTeX printing of MOI.Interval sets

Other

  • Added Aqua.jl as a CI check, and fixed suggested issues
  • The constructors of GeoMeanBridge, StructOfConstraints, and CachingOptimizer were changed from outer to inner constructors. This change is technically breaking, but does not impact users who followed the documented API.

v0.10.8 (February 3, 2022)

Added

  • Added a Base.read! for FileFormats.LP.

Fixed

  • Fixed a bug in MutableSparseMatrix
  • Fixed a bug when calling operate!(vcat, ...) with Number arguments
  • Removed unintended export of deprecated symbols
  • Fixed a bug with PowerCone and DualPowerCone in MatrixOfConstraints.

v0.10.7 (January 5, 2022)

Added

  • Added test for modifying the constant vector in a VectorAffineFunction-in-Zeros constraint.

Fixed

  • Fixed the order in which sets are added to a LazyBridgeOptimizer. Compared to v0.10.6, this may result in bridged models being created with a different number (and order) of variables and constraints. However, it was necessary to fix cases which were previously rejected as unsupported, even though there was a valid bridge transformation.
  • Fixed an error message in FileFormats.CBF
  • Fixed comparison in test_linear_integration_Interval
  • Fixed errors for ConstraintPrimal in a CachingOptimizer
  • Fixed printing of models with non-Float64 coefficients.

Other

  • Various improvements to reduce time-to-first-solve latency
  • Improved error message when an optimizer does not support compute_conflict!

v0.10.6 (November 30, 2021)

Added

  • Added new documentation and tests for infeasibility certificates
  • Added a version control system for the tests in MOI.Test.runtests. Pass exclude_tests_after = v"0.10.5" to run tests added in v0.10.5 and earlier.
  • MOI.Test.runtests now supports generic number types. To specify the number type T, pass MOI.Test.Config(T).
  • Added infeasible_status to MOI.Test.Config for solvers which return LOCALLY_INFEASIBLE
  • CachingOptimizers now use a fallback for ConstraintPrimal. This should enable solvers using a CachingOptimizer to pass tests requiring ConstraintPrimal.

Fixed

  • Fixed a StackOverflow bug in copy_to
  • Fixed error thrown when nonconvex quadratic constraints cannot be bridged
  • Fixed a bug in copy_to for FileFormats.NL.Model
  • Fixed a bug in FileFormats.NL when printing large integers
  • Remove a common test failure for LowerBoundAlreadySet tests
  • Utilities.num_rows is now exported
  • Remove parts of failing test_model_copy_to_xxx tests due to bridges

v0.10.5 (November 7, 2021)

Fixed

  • Fixed getter in UniversalFallback
  • Fixed test_solve_conflict_zeroone_ii

Other

  • Make normalize_and_add_constraint more flexible
  • Update paper BibTeX

v0.10.4 (October 26, 2021)

Added

  • Add SolverVersion attribute
  • Add new tests:
    • test_solve_conflict_zeroone_ii
    • test_nonlinear_objective
  • Utilities.VariablesContainer now supports ConstraintFunction and ConstraintSet
  • The documentation is now available as a PDF

Other

  • Update to MutableArithmetics 0.3
  • Various improvements to the documentation

v0.10.3 (September 18, 2021)

Fixed

  • Fixed bug which prevented callbacks from working through a CachingOptimizer
  • Fixed bug in Test submodule

v0.10.2 (September 16, 2021)

  • Updated MathOptFormat to v1.0
  • Updated JSONSchema to v1.0
  • Added Utilities.set_with_dimension
  • Added two-argument optimize!(::AbstractOptimizer, ::ModelLike)
  • The experimental feature copy_to_and_optimize! has been removed
  • Det bridges now support getting ConstraintFunction and ConstraintSet
  • Various minor bug fixes identified by improved testing

v0.10.1 (September 8, 2021)

  • Various fixes to MOI.Test

v0.10.0 (September 6, 2021)

MOI v0.10 is a significant breaking release. There are a large number of user-visible breaking changes and code refactors, as well as a substantial number of new features.

Breaking in MOI

  • SingleVariable has been removed; use VariableIndex instead
  • SingleVariableConstraintNameError has been renamed to VariableIndexConstraintNameError
  • SettingSingleVariableFunctionNotAllowed has been renamed to SettingVariableIndexFunctionNotAllowed
  • VariableIndex constraints should not support ConstraintName
  • VariableIndex constraints should not support ConstraintBasisStatus; implement VariableBasisStatus instead
  • ListOfConstraints has been renamed to ListOfConstraintTypesPresent
  • ListOfConstraintTypesPresent should now return Tuple{Type,Type} instead of Tuple{DataType,DataType}
  • SolveTime has been renamed to SolveTimeSec
  • IndicatorSet has been renamed to Indicator
  • RawParameter has been renamed to RawOptimizerAttribute and now takes String instead of Any as the only argument
  • The .N field in result attributes has been renamed to .result_index
  • The .variable_index field in ScalarAffineTerm has been renamed to .variable
  • The .variable_index_1 field in ScalarQuadraticTerm has been renamed to .variable_1
  • The .variable_index_2 field in ScalarQuadraticTerm has been renamed to .variable_2
  • The order of affine_terms and quadratic_terms in ScalarQuadraticFunction and VectorQuadraticFunction have been reversed. Both functions now accept quadratic, affine, and constant terms in that order.
  • The index_value function has been removed. Use .value instead.
  • isapprox has been removed for SOS1 and SOS2.
  • The dimension argument to Complements(dimension::Int) should now be the length of the corresponding function, instead of half the length. An ArgumentError is thrown if dimension is not even.
  • copy_to no longer takes keyword arguments:
    • copy_names: now copy names if they are supported by the destination solver
    • filter_constraints: use Utilities.ModelFilter instead
    • warn_attributes: never warn about optimizer attributes

Breaking in Bridges

  • Constraint.RSOCBridge has been renamed to Constraint.RSOCtoSOCBridge
  • Constraint.SOCRBridge has been renamed to Constraint.SOCtoRSOCBridge
  • Bridges now return vectors that can be modified by the user. Previously, some bridges returned views instead of copies.
  • Bridges.IndexInVector has been unified into a single type. Previously, there was a different type for each submodule within Bridges
  • The signature of indicator bridges has been fixed. Use MOI.Bridges.Constraint.IndicatortoSOS1{Float64}(model).

Breaking in FileFormats

  • FileFormats.MOF.Model no longer accepts validate argument. Use the JSONSchema package to validate the MOF file. See the documentation for more information.

Breaking in Utilities

  • The datastructure of Utilities.Model (and models created with Utilities.@model) has been significantly refactored in a breaking way. This includes the way that objective functions and variable-related information is stored.
  • Utilities.supports_default_copy has been renamed to supports_incremental_interface
  • Utilities.automatic_copy_to has been renamed to Utilities.default_copy_to
  • The allocate-load API has been removed
  • CachingOptimizers are now initialized as EMPTY_OPTIMIZER instead of ATTACHED_OPTIMIZER. If your code relies on the optimizer being attached, call MOIU.attach_optimizer(model) after creation.
  • The field names of Utilities.IndexMap have been renamed to var_map and con_map. Accessing these fields directly is considered a private detail that may change. Use the public getindex and setindex! API instead.
  • The size argument to Utilities.CleverDicts.CleverDict(::Integer) has been removed.
  • The size argument to Utilities.IndexMap(::Integer) has been removed.
  • Utilities.DoubleDicts have been significantly refactored. Consult the source code for details.
  • Utilities.test_models_equal has been moved to MOI.Test

Breaking in Test

  • MOI.Test has been renamed to MOI.DeprecatedTest
  • An entirely new MOI.Test submodule has been written. See the documentation for details. The new MOI.Test submodule may find many bugs in the implementations of existing solvers that were previously untested.

Other changes:

  • attribute_value_type has been added
  • copy_to_and_optimize! has been added
  • VariableBasisStatus has been added
  • print(model) now prints a human-readable description of the model
  • Various improvements to the FileFormats submodule
    • FileFormats.CBF was refactored and received bugfixes
    • Support for MathOptFormat v0.6 was added in FileFormats.MOF
    • FileFormats.MPS has had bugfixes and support for more features such as OBJSENSE and objective constants.
    • FileFormats.NL has been added to support nonlinear files
  • Improved type inference throughout to reduce latency

Updating

A helpful script when updating is:

for (root, dirs, files) in walkdir(".")
+    for file in files
+        if !endswith(file, ".jl")
+            continue
+        end
+        path = joinpath(root, file)
+        s = read(path, String)
+        for pair in [
+            ".variable_index" => ".variable",
+            "RawParameter" => "RawOptimizerAttribute",
+            "ListOfConstraints" => "ListOfConstraintTypesPresent",
+            "TestConfig" => "Config",
+            "attr.N" => "attr.result_index",
+            "SolveTime" => "SolveTimeSec",
+            "DataType" => "Type",
+            "Utilities.supports_default_copy_to" =>
+                "supports_incremental_interface",
+            "SingleVariableConstraintNameError" =>
+                "VariableIndexConstraintNameError",
+            "SettingSingleVariableFunctionNotAllowed" =>
+                "SettingVariableIndexFunctionNotAllowed",
+            "automatic_copy_to" => "default_copy_to",
+        ]
+            s = replace(s, pair)
+        end
+        write(path, s)
+    end
+end

v0.9.22 (May 22, 2021)

This release contains backports from the ongoing development of the v0.10 release.

  • Improved type inference in Utilities, Bridges and FileFormats submodules to reduce latency.
  • Improved performance of Utilities.is_canonical.
  • Fixed Utilities.pass_nonvariable_constraints with bridged variables.
  • Fixed performance regression of Utilities.Model.
  • Fixed ordering of objective setting in parser.

v0.9.21 (April 23, 2021)

  • Added supports_shift_constant.
  • Improve performance of bridging quadratic constraints.
  • Add precompilation statements.
  • Large improvements to the documentation.
  • Fix a variety of inference issues, benefiting precompilation and reducing initial latency.
  • RawParameters are now ignored when resetting a CachingOptimizer. Previously, changing the underlying optimizer after RawParameters were set would throw an error.
  • Utilities.AbstractModel is being refactored. This may break users interacting with private fields of a model generated using @model.

v0.9.20 (February 20, 2021)

  • Improved performance of Utilities.ScalarFunctionIterator
  • Added support for compute_conflict to MOI layers
  • Added test with zero off-diagonal quadratic term in objective
  • Fixed double deletion of nested bridged SingleVariable/VectorOfVariables constraints
  • Fixed modification of un-set objective
  • Fixed function modification with duplicate terms
  • Made unit tests abort without failing if the problem class is not supported
  • Formatted code with JuliaFormatter
  • Clarified BasisStatusCode's docstring

v0.9.19 (December 1, 2020)

  • Added CallbackNodeStatus attribute
  • Added bridge from GreaterThan or LessThan to Interval
  • Added tests for infeasibility certificates and double optimize
  • Fixed support for Julia v1.6
  • Re-organized MOI docs and added documentation for adding a test

v0.9.18 (November 3, 2020)

  • Various improvements for working with complex numbers
  • Added GeoMeantoRelEntrBridge to bridge a GeometricMeanCone constraint to a relative entropy constraint

v0.9.17 (September 21, 2020)

  • Fixed CleverDict with variable of negative index value
  • Implement supports_add_constrained_variable for MockOptimizer

v0.9.16 (September 17, 2020)

  • Various fixes:
    • 32-bit support
    • CleverDict with abstract value type
    • Checks in test suite

v0.9.15 (September 14, 2020)

  • Bridges improvements:
    • (R)SOCtoNonConvexQuad bridge
    • ZeroOne bridge
    • Use supports_add_constrained_variable in LazyBridgeOptimizer
    • Exposed VariableBridgeCost and ConstraintBridgeCost attributes
    • Prioritize constraining variables on creation according to these costs
    • Refactor bridge debugging
  • Large performance improvements across all submodules
  • Lots of documentation improvements
  • FileFormats improvements:
    • Update MathOptFormat to v0.5
    • Fix supported objectives in FileFormats
  • Testing improvements:
    • Add name option for basic_constraint_test
  • Bug fixes and missing methods
    • Add length for iterators
    • Fix bug with duplicate terms
    • Fix order of LinearOfConstraintIndices

v0.9.14 (May 30, 2020)

  • Add a solver-independent interface for accessing the set of conflicting constraints an Irreducible Inconsistent Subsystem (#1056).
  • Bump JSONSchema dependency from v0.2 to v0.3 (#1090).
  • Documentation improvements:
    • Fix typos (#1054, #1060, #1061, #1064, #1069, #1070).
    • Remove the outdated recommendation for a package implementing MOI for a solver XXX to be called MathOptInterfaceXXX (#1087).
  • Utilities improvements:
    • Fix is_canonical for quadratic functions (#1081, #1089).
    • Implement add_constrained_variable[s] for CachingOptimizer so that it is added as constrained variables to the underlying optimizer (#1084).
    • Add support for custom objective functions for UniversalFallback (#1086).
    • Deterministic ordering of constraints in UniversalFallback (#1088).
  • Testing improvements:
    • Add NormOneCone/NormInfinityCone tests (#1045).
  • Bridges improvements:
    • Add bridges from Semiinteger and Semicontinuous (#1059).
    • Implement getting ConstraintSet for Variable.FlipSignBridge (#1066).
    • Fix setting ConstraintFunction for Constraint.ScalarizeBridge (#1093).
    • Fix NormOne/NormInf bridges with nonzero constants (#1045).
    • Fix StackOverflow in debug (#1063).
  • FileFormats improvements:
    • [SDPA] Implement the extension for integer variables (#1079).
    • [SDPA] Ignore comments after m and nblocks and detect dat-s extension (#1077).
    • [SDPA] No scaling of off-diagonal coefficient (#1076).
    • [SDPA] Add missing negation of constant (#1075).

v0.9.13 (March 24, 2020)

  • Added tests for Semicontinuous and Semiinteger variables (#1033).
  • Added tests for using ExprGraphs from NLP evaluators (#1043).
  • Update version compatibilities of dependencies (#1034, #1051, #1052).
  • Fixed typos in documentation (#1044).

v0.9.12 (February 28, 2020)

  • Fixed writing NLPBlock in MathOptFormat (#1037).
  • Fixed MockOptimizer for result attributes with non-one result index (#1039).
  • Updated test template with instantiate (#1032).

v0.9.11 (February 21, 2020)

  • Add an option for the model created by Utilities.@model to be a subtype of AbstractOptimizer (#1031).
  • Described dual cone in docstrings of GeoMeanCone and RelativeEntropyCone (#1018, #1028).
  • Fixed typos in documentation (#1022, #1024).
  • Fixed warning of unsupported attribute (#1027).
  • Added more rootdet/logdet conic tests (#1026).
  • Implemented ConstraintDual for Constraint.GeoMeanBridge, Constraint.RootDetBridge and Constraint.LogDetBridge and test duals in tests with GeoMeanCone and RootDetConeTriangle and LogDetConeTriangle cones (#1025, #1026).

v0.9.10 (January 31, 2020)

  • Added OptimizerWithAttributes grouping an optimizer constructor and a list of optimizer attributes (#1008).
  • Added RelativeEntropyCone with corresponding bridge into exponential cone constraints (#993).
  • Added NormSpectralCone and NormNuclearCone with corresponding bridges into positive semidefinite constraints (#976).
  • Added supports_constrained_variable(s) (#1004).
  • Added dual_set_type (#1002).
  • Added tests for vector specialized version of delete (#989, #1011).
  • Added PSD3 test (#1007).
  • Clarified dual solution of Tests.pow1v and Tests.pow1f (#1013).
  • Added support for EqualTo and Zero in Bridges.Constraint.SplitIntervalBridge (#1005).
  • Fixed Utilities.vectorize for empty vector (#1003).
  • Fixed free variables in LP writer (#1006).

v0.9.9 (December 29, 2019)

  • Incorporated MathOptFormat.jl as the FileFormats submodule. FileFormats provides readers and writers for a number of standard file formats and MOF, a file format specialized for MOI (#969).
  • Improved performance of deletion of vector of variables in MOI.Utilities.Model (#983).
  • Updated to MutableArithmetics v0.2 (#981).
  • Added MutableArithmetics.promote_operation allocation tests (#975).
  • Fixed inference issue on Julia v1.1 (#982).

v0.9.8 (December 19, 2019)

  • Implemented MutableArithmetics API (#924).
  • Fixed callbacks with CachingOptimizer (#959).
  • Fixed MOI.dimension for MOI.Complements (#948).
  • Added fallback for add_variables (#972).
  • Added is_diagonal_vectorized_index utility (#965).
  • Improved linear constraints display in manual (#963, #964).
  • Bridges improvements:
    • Added IndicatorSet to SOS1 bridge (#877).
    • Added support for starting values for Variable.VectorizeBridge (#944).
    • Fixed MOI.add_constraints with non-bridged variable constraint on bridged variable (#951).
    • Fixed corner cases and docstring of GeoMeanBridge (#961, #962, #966).
    • Fixed choice between variable or constraint bridges for constrained variables (#973).
    • Improve performance of bridge shortest path (#945, #946, #956).
    • Added docstring for test_delete_bridge (#954).
    • Added Variable bridge tests (#952).

v0.9.7 (October 30, 2019)

  • Implemented _result_index_field for NLPBlockDual (#934).
  • Fixed copy of model with starting values for vector constraints (#941).
  • Bridges improvements:
    • Improved performance of add_bridge and added has_bridge (#935).
    • Added AbstractSetMapBridge for bridges between sets S1, S2 such that there is a linear map A such that A*S1 = S2 (#933).
    • Added support for starting values for FlipSignBridge, VectorizeBridge, ScalarizeBridge, SlackBridge, SplitIntervalBridge, RSOCBridge, SOCRBridge NormInfinityBridge, SOCtoPSDBridge and RSOCtoPSDBridge (#933, #936, #937, #938, #939).

v0.9.6 (October 25, 2019)

  • Added complementarity constraints (#913).
  • Allowed ModelLike objects as value of attributes (#928).
  • Testing improvements:
    • Added dual_objective_value option to MOI.Test.TestConfig (#922).
    • Added InvalidIndex tests in basic_constraint_tests (#921).
    • Added tests for the constant term in indicator constraint (#929).
  • Bridges improvements:
    • Added support for starting values for Functionize bridges (#923).
    • Added variable indices context to variable bridges (#920).
    • Fixed a typo in printing o debug_supports (#927).

v0.9.5 (October 9, 2019)

  • Clarified PrimalStatus/DualStatus to be NO_SOLUTION if result_index is out of bounds (#912).
  • Added tolerance for checks and use ResultCount + 1 for the result_index in MOI.Test.solve_result_status (#910, #917).
  • Use 0.5 instead of 2.0 for power in PowerCone in basic_constraint_test (#916).
  • Bridges improvements:
    • Added debug utilities for unsupported variable/constraint/objective (#861).
    • Fixed deletion of variables in bridged VectorOfVariables constraints (#909).
    • Fixed result_index with objective bridges (#911).

v0.9.4 (October 2, 2019)

  • Added solver-independent MIP callbacks (#782).
  • Implements submit for Utilities.CachingOptimizer and Bridges.AbstractBridgeOptimizer (#906).
  • Added tests for result count of solution attributes (#901, #904).
  • Added NumberOfThreads attribute (#892).
  • Added Utilities.get_bounds to get the bounds on a variable (#890).
  • Added a note on duplicate coefficients in documentation (#581).
  • Added result index in ConstraintBasisStatus (#898).
  • Added extension dictionary to Utilities.Model (#884, #895).
  • Fixed deletion of constrained variables for CachingOptimizer (#905).
  • Implemented Utilities.shift_constraint for Test.UnknownScalarSet (#896).
  • Bridges improvements:
    • Added Variable.RSOCtoSOCBridge (#907).
    • Implemented MOI.get for ConstraintFunction/ConstraintSet for Bridges.Constraint.SquareBridge (#899).

v0.9.3 (September 20, 2019)

  • Fixed ambiguity detected in Julia v1.3 (#891, #893).
  • Fixed missing sets from ListOfSupportedConstraints (#880).
  • Fixed copy of VectorOfVariables constraints with duplicate indices (#886).
  • Added extension dictionary to MOIU.Model (#884).
  • Implemented MOI.get for function and set for GeoMeanBridge (#888).
  • Updated documentation for SingleVariable indices and bridges (#885).
  • Testing improvements:
    • Added more comprehensive tests for names (#882).
    • Added tests for SingleVariable duals (#883).
    • Added tests for DualExponentialCone and DualPowerCone (#873).
  • Improvements for arbitrary coefficient type:
    • Fixed == for sets with mutable fields (#887).
    • Removed some Float64 assumptions in bridges (#878).
    • Automatic selection of Constraint.[Scalar|Vector]FunctionizeBridge (#889).

v0.9.2 (September 5, 2019)

  • Implemented model printing for MOI.ModelLike and specialized it for models defined in MOI (864).
  • Generalized contlinear tests for arbitrary coefficient type (#855).
  • Fixed supports_constraint for Semiinteger and Semicontinuous and supports for ObjectiveFunction (#859).
  • Fixed Allocate-Load copy for single variable constraints (#856).
  • Bridges improvements:
    • Add objective bridges (#789).
    • Fixed Variable.RSOCtoPSDBridge for dimension 2 (#869).
    • Added Variable.SOCtoRSOCBridge (#865).
    • Added Constraint.SOCRBridge and disable MOI.Bridges.Constraint.SOCtoPSDBridge (#751).
    • Fixed added_constraint_types for Contraint.LogDetBridge and Constraint.RootDetBridge (#870).

v0.9.1 (August 22, 2019)

  • Fix support for Julia v1.2 (#834).
  • L1 and L∞ norm epigraph cones and corresponding bridges to LP were added (#818).
  • Added tests to MOI.Test.nametest (#833).
  • Fix MOI.Test.soc3test for solvers not supporting infeasibility certificates (#839).
  • Implements operate for operators * and / between vector function and constant (#837).
  • Implements show for MOI.Utilities.IndexMap (#847).
  • Fix corner cases for mapping of variables in MOI.Utilities.CachingOptimizer and substitution of variables in MOI.Bridges.AbstractBridgeOptimizer (#848).
  • Fix transformation of constant terms for MOI.Bridges.Constraint.SOCtoPSDBridge and MOI.Bridges.Constraint.RSOCtoPSDBridge (#840).

v0.9.0 (August 13, 2019)

  • Support for Julia v0.6 and v0.7 was dropped (#714, #717).
  • A MOI.Utilities.Model implementation of ModelLike, this should replace most use cases of MOI.Utilities.@model (#781).
  • add_constrained_variable and add_constrained_variables were added (#759).
  • Support for indicator constraints was added (#709, #712).
  • DualObjectiveValue attribute was added (#473).
  • RawParameter attribute was added (#733).
  • A dual_set function was added (#804).
  • A Benchmarks submodule was added to facilitate solver benchmarking (#769).
  • A submit function was added, this may for instance allow the user to submit solutions or cuts to the solver from a callback (#775).
  • The field of ObjectiveValue was renamed to result_index (#729).
  • The _constant and Utilities.getconstant function were renamed to constant
  • REDUCTION_CERTIFICATE result status was added (#734).
  • Abstract matrix sets were added (#731).
  • Testing improvements:
    • The testing guideline was updated (#728).
    • Quadratic tests were added (#697).
    • Unit tests for RawStatusString, SolveTime, Silent and SolverName were added (#726, #741).
    • A rotated second-order cone test was added (#759).
    • A power cone test was added (#768).
    • Tests for ZeroOne variables with variable bounds were added (#772).
    • An unbounded test was added (#773).
    • Existing tests had a few updates (#702, #703, #763).
  • Documentation improvements:
    • Added a section on CachingOptimizer (#777).
    • Added a section on UniversalFallback, Model and @model (#762).
    • Transition the knapsack example to a doctest with MockOptimizer (#786).
  • Utilities improvements:
    • A CleverDict utility was added for a vector that automatically transform into a dictionary once a first index is removed (#767).
    • The Utilities.constant function was renamed to Utilities.constant_vector (#740).
    • Implement optimizer attributes for CachingOptimizer (#745).
    • Rename Utilities.add_scalar_constraint to Utilities.normalize_and_add_constraint (#801).
    • operate with vcat, SingleVariable and VectorOfVariables now returns a VectorOfVariables (#616).
    • Fix a type piracy of operate (#784).
    • The load_constraint fallback signature was fixed (#760).
    • The set_dot function was extended to work with sparse arrays (#805).
  • Bridges improvements:
    • The bridges no longer store the constraint function and set before it is bridged, the bridges now have to implement ConstraintFunction and ConstraintSet if the user wants to recover them. As a consequence, the @bridge macro was removed (#722).
    • Bridge are now instantiated with a bridge_constraint function instead of using a constructor (#730).
    • Fix constraint attributes for bridges (#699).
    • Constraint bridges were moved to the Bridges/Constraint submodule so they should now inherit from MOI.Bridges.Constraint.Abstract and should implement MOI.Bridges.Constraint.concrete_bridge_type instead of MOI.Bridges.concrete_bridge_type (#756).
    • Variable bridges were added in (#759).
    • Various improvements (#746, #747).

v0.8.4 (March 13, 2019)

  • Performance improvement in default_copy_to and bridge optimizer (#696).
  • Add Silent and implement setting optimizer attributes in caching and mock optimizers (#695).
  • Add Functionize bridges (SingleVariable and VectorOfVariables) (#659).
  • Minor typo fixes (#694).

v0.8.3 (March 6, 2019)

  • Use zero constant in scalar constraint function of MOI.Test.copytest (#691).
  • Fix variable deletion with SingleVariable objective function (#690).
  • Fix LazyBridgeOptimizer with bridges that add no constraints (#689).
  • Error message improvements (#673, #685, #686, #688).
  • Documentation improvements (#682, #683, #687).
  • Basis status:
    • Remove VariableBasisStatus (#679).
    • Test ConstraintBasisStatus and implement it in bridges (#678).
  • Fix inference of NumberOfVariables and NumberOfConstraints (#677).
  • Implement division between a quadratic function and a number (#675).

v0.8.2 (February 7, 2019)

  • Add RawStatusString attribute (#629).
  • Do not set names to the optimizer but only to the cache in CachingOptimizer (#638).
  • Make scalar MOI functions act as scalars in broadcast (#646).
  • Add function utilities:
    • Implement Base.zero (#634), Base.iszero (#643), add missing arithmetic operations (#644, #645) and fix division (#648).
    • Add a vectorize function that turns a vector of ScalarAffineFunction into a VectorAffineFunction (#642).
  • Improve support for starting values:
    • Show a warning in copy when starting values are not supported instead of throwing an error (#630).
    • Fix UniversalFallback for getting an variable or constraint attribute set to no indices (#623).
    • Add a test in contlineartest with partially set VariablePrimalStart.
  • Bridges improvements:
    • Fix StackOverFlow in LazyBridgeOptimizer when there is a cycle in the graph of bridges.
    • Add Slack bridges (#610, #650).
    • Add FlipSign bridges (#658).
  • Add tests with duplicate coefficients in ScalarAffineFunction and VectorAffineFunction (#639).
  • Use tolerance to compare VariablePrimal in rotatedsoc1 test (#632).
  • Use a zero constant in ScalarAffineFunction of constraints in psdt2 (#622).

v0.8.1 (January 7, 2019)

  • Adding an NLP objective now overrides any objective set using the ObjectiveFunction attribute (#619).
  • Rename fullbridgeoptimizer into full_bridge_optimizer (#621).
  • Allow custom constraint types with full_bridge_optimizer (#617).
  • Add Vectorize bridge which transforms scalar linear constraints into vector linear constraints (#615).

v0.8.0 (December 18, 2018)

  • Rename all enum values to follow the JuMP naming guidelines for constants, for example, Optimal becomes OPTIMAL, and DualInfeasible becomes DUAL_INFEASIBLE.
  • Rename CachingOptimizer methods for style compliance.
  • Add an MOI.TerminationStatusCode called ALMOST_DUAL_INFEASIBLE.

v0.7.0 (December 13, 2018)

  • Test that MOI.TerminationStatus is MOI.OptimizeNotCalled before MOI.optimize! is called.
  • Check supports_default_copy_to in tests (#594).
  • Key pieces of information like optimality, infeasibility, etc., are now reported through TerminationStatusCode. It is typically no longer necessary to check the result statuses in addition to the termination status.
  • Add perspective dimension to log-det cone (#593).

v0.6.4 (November 27, 2018)

  • Add OptimizeNotCalled termination status (#577) and improve documentation of other statuses (#575).
  • Add a solver naming guideline (#578).
  • Make FeasibilitySense the default ObjectiveSense (#579).
  • Fix Utilities.@model and Bridges.@bridge macros for functions and sets defined outside MOI (#582).
  • Document solver-specific attributes (#580) and implement them in Utilities.CachingOptimizer (#565).

v0.6.3 (November 16, 2018)

  • Variables and constraints are now allowed to have duplicate names. An error is thrown only on lookup. This change breaks some existing tests. (#549)
  • Attributes may now be partially set (some values could be nothing). (#563)
  • Performance improvements in Utilities.Model (#549, #567, #568)
  • Fix bug in QuadtoSOC (#558).
  • New supports_default_copy_to method that optimizers should implement to control caching behavior.
  • Documentation improvements.

v0.6.2 (October 26, 2018)

  • Improve hygiene of @model macro (#544).
  • Fix bug in copy tests (#543).
  • Fix bug in UniversalFallback attribute getter (#540).
  • Allow all correct solutions for solve_blank_obj unit test (#537).
  • Add errors for Allocate-Load and bad constraints (#534).
  • [performance] Add specialized implementation of hash for VariableIndex (#533).
  • [performance] Construct the name to object dictionaries lazily in model (#535).
  • Add the QuadtoSOC bridge which transforms ScalarQuadraticFunction constraints into RotatedSecondOrderCone (#483).

v0.6.1 (September 22, 2018)

  • Enable PositiveSemidefiniteConeSquare set and quadratic functions in MOIB.fullbridgeoptimizer (#524).
  • Add warning in the bridge between PositiveSemidefiniteConeSquare and PositiveSemidefiniteConeTriangle when the matrix is almost symmetric (#522).
  • Modify MOIT.copytest to not add multiples constraints on the same variable (#521).
  • Add missing keyword argument in one of MOIU.add_scalar_constraint methods (#520).

v0.6.0 (August 30, 2018)

  • The MOIU.@model and MOIB.@bridge macros now support functions and sets defined in external modules. As a consequence, function and set names in the macro arguments need to be prefixed by module name.
  • Rename functions according to the JuMP style guide:
    • copy! with keyword arguments copynames and warnattributes -> copy_to with keyword arguments copy_names and warn_attributes;
    • set! -> set;
    • addvariable[s]! -> add_variable[s];
    • supportsconstraint -> supports_constraint;
    • addconstraint[s]! -> add_constraint[s];
    • isvalid -> is_valid;
    • isempty -> is_empty;
    • Base.delete! -> delete;
    • modify! -> modify;
    • transform! -> transform;
    • initialize! -> initialize;
    • write -> write_to_file; and
    • read! -> read_from_file.
  • Remove free! (use Base.finalize instead).
  • Add the SquarePSD bridge which transforms PositiveSemidefiniteConeTriangle constraints into PositiveSemidefiniteConeTriangle.
  • Add result fallback for ConstraintDual of variable-wise constraint, ConstraintPrimal and ObjectiveValue.
  • Add tests for ObjectiveBound.
  • Add test for empty rows in vector linear constraint.
  • Rework errors: CannotError has been renamed NotAllowedError and the distinction between UnsupportedError and NotAllowedError is now about whether the element is not supported (for example, it cannot be copied a model containing this element) or the operation is not allowed (either because it is not implemented, because it cannot be performed in the current state of the model, or because it cannot be performed for a specific index)
  • canget is removed. NoSolution is added as a result status to indicate that the solver does not have either a primal or dual solution available (See #479).

v0.5.0 (August 5, 2018)

  • Fix names with CachingOptimizer.
  • Cleanup thanks to @mohamed82008.
  • Added a universal fallback for constraints.
  • Fast utilities for function canonicalization thanks to @rdeits.
  • Renamed dimension field to side_dimension in the context of matrix-like sets.
  • New and improved tests for cases like duplicate terms and ObjectiveBound.
  • Removed cantransform, canaddconstraint, canaddvariable, canset, canmodify, and candelete functions from the API. They are replaced by a new set of errors that are thrown: Subtypes of UnsupportedError indicate unsupported operations, while subtypes of CannotError indicate operations that cannot be performed in the current state.
  • The API for copy! is updated to remove the CopyResult type.
  • Updates for the new JuMP style guide.

v0.4.1 (June 28, 2018)

  • Fixes vector function modification on 32 bits.
  • Fixes Bellman-Ford algorithm for bridges.
  • Added an NLP test with FeasibilitySense.
  • Update modification documentation.

v0.4.0 (June 23, 2018)

  • Helper constructors for VectorAffineTerm and VectorQuadraticTerm.
  • Added modify_lhs to TestConfig.
  • Additional unit tests for optimizers.
  • Added a type parameter to CachingOptimizer for the optimizer field.
  • New API for problem modification (#388)
  • Tests pass without deprecation warnings on Julia 0.7.
  • Small fixes and documentation updates.

v0.3.0 (May 25, 2018)

  • Functions have been redefined to use arrays-of-structs instead of structs-of-arrays.
  • Improvements to MockOptimizer.
  • Significant changes to Bridges.
  • New and improved unit tests.
  • Fixes for Julia 0.7.

v0.2.0 (April 24, 2018)

  • Improvements to and better coverage of Tests.
  • Documentation fixes.
  • SolverName attribute.
  • Changes to the NLP interface (new definition of variable order and arrays of structs for bound pairs and sparsity patterns).
  • Addition of NLP tests.
  • Introduction of UniversalFallback.
  • copynames keyword argument to MOI.copy!.
  • Add Bridges submodule.

v0.1.0 (February 28, 2018)

  • Initial public release.
  • The framework for MOI was developed at the JuMP-dev workshop at MIT in June 2017 as a sorely needed replacement for MathProgBase.
diff --git a/previews/PR2274/developer/checklists/index.html b/previews/PR2274/developer/checklists/index.html new file mode 100644 index 0000000000..1bdcd44cee --- /dev/null +++ b/previews/PR2274/developer/checklists/index.html @@ -0,0 +1,112 @@ + +Checklists · MathOptInterface

Checklists

The purpose of this page is to collate a series of checklists for commonly performed changes to the source code of MathOptInterface.

In each case, copy the checklist into the description of the pull request.

Making a release

Use this checklist when making a release of the MathOptInterface repository.

## Basic
+
+ - [ ] `version` field of `Project.toml` has been updated
+       - If a breaking change, increment the MAJOR field and reset others to 0
+       - If adding new features, increment the MINOR field and reset PATCH to 0
+       - If adding bug fixes or documentation changes, increment the PATCH field
+
+## Documentation
+
+ - [ ] Add a new entry to `docs/src/changelog.md`, following existing style
+
+## Tests
+
+ - [ ] The `solver-tests.yml` GitHub action does not have unexpected failures.
+       To run the action, go to:
+       https://github.com/jump-dev/MathOptInterface.jl/actions/workflows/solver-tests.yml
+       and click "Run workflow"

Adding a new set

Use this checklist when adding a new set to the MathOptInterface repository.

## Basic
+
+ - [ ] Add a new `AbstractScalarSet` or `AbstractVectorSet` to `src/sets.jl`
+ - [ ] If `isbitstype(S) == false`, implement `Base.copy(set::S)`
+ - [ ] If `isbitstype(S) == false`, implement `Base.:(==)(x::S, y::S)`
+ - [ ] If an `AbstractVectorSet`, implement `dimension(set::S)`, unless the
+       dimension is given by `set.dimension`.
+
+## Utilities
+
+ - [ ] If an `AbstractVectorSet`, implement `Utilities.set_dot`,
+       unless the dot product between two vectors in the set is equivalent to
+       `LinearAlgebra.dot`
+ - [ ] If an `AbstractVectorSet`, implement `Utilities.set_with_dimension` in
+       `src/Utilities/matrix_of_constraints.jl`
+ - [ ] Add the set to the `@model` macro at the bottom of `src/Utilities.model.jl`
+
+## Documentation
+
+ - [ ] Add a docstring, which gives the mathematical definition of the set,
+       along with an `## Example` block containing a `jldoctest`
+ - [ ] Add the docstring to `docs/src/reference/standard_form.md`
+ - [ ] Add the set to the relevant table in `docs/src/manual/standard_form.md`
+
+## Tests
+
+ - [ ] Define a new `_set(::Type{S})` method in `src/Test/test_basic_constraint.jl`
+       and add the name of the set to the list at the bottom of that files
+ - [ ] If the set has any checks in its constructor, add tests to `test/sets.jl`
+
+## MathOptFormat
+
+ - [ ] Open an issue at `https://github.com/jump-dev/MathOptFormat` to add
+       support for the new set {{ replace with link to the issue }}
+
+## Optional
+
+ - [ ] Implement `dual_set(::S)` and `dual_set_type(::Type{S})`
+ - [ ] Add new tests to the `Test` submodule exercising your new set
+ - [ ] Add new bridges to convert your set into more commonly used sets

Adding a new bridge

Use this checklist when adding a new bridge to the MathOptInterface repository.

The steps are mostly the same, but locations depend on whether the bridge is a Constraint, Objective, or Variable bridge. In each case below, replace XXX with the appropriate type of bridge.

## Basic
+
+ - [ ] Create a new file in `src/Bridges/XXX/bridges`
+ - [ ] Define the bridge, following existing examples. The name of the bridge
+       struct must end in `Bridge`
+ - [ ] Check if your bridge can be a subtype of [`MOI.Bridges.Constraint.SetMapBridge`](@ref)
+ - [ ] Define a new `const` that is a `SingleBridgeOptimizer` wrapping the
+       new bridge. The name of the const must be the name of the bridge, less
+       the `Bridge` suffix
+ - [ ] `include` the file in `src/Bridges/XXX/bridges/XXX.jl`
+ - [ ] If the bridge should be enabled by default, add the bridge to
+       `add_all_bridges` at the bottom of `src/Bridges/XXX/XXX.jl`
+
+## Tests
+
+ - [ ] Create a new file in the appropriate subdirectory of `tests/Bridges/XXX`
+ - [ ] Use `MOI.Bridges.runtests` to test various inputs and outputs of the
+       bridge
+ - [ ] If, after opening the pull request to add the bridge, some lines are not
+       covered by the tests, add additional bridge-specific tests to cover the
+       untested lines.
+
+## Documentation
+
+ - [ ] Add a docstring which uses the same template as existing bridges.
+ - [ ] Add the docstring to `docs/src/submodules/Bridges/list_of_bridges.md`
+
+## Final touch
+
+If the bridge depends on run-time values of other variables and constraints in
+the model:
+
+ - [ ] Implement `MOI.Utilities.needs_final_touch(::Bridge)`
+ - [ ] Implement `MOI.Utilities.final_touch(::Bridge, ::MOI.ModelLike)`
+ - [ ] Ensure that `final_touch` can be called multiple times in a row

Updating MathOptFormat

Use this checklist when updating the version of MathOptFormat.

## Basic
+
+ - [ ] The file at `src/FileFormats/MOF/mof.X.Y.schema.json` is updated
+ - [ ] The constants `SCHEMA_PATH`, `VERSION`, and `SUPPORTED_VERSIONS` are
+       updated in `src/FileFormats/MOF/MOF.jl`
+
+## New sets
+
+ - [ ] New sets are added to the `@model` in `src/FileFormats/MOF/MOF.jl`
+ - [ ] New sets are added to the `@enum` in `src/FileFormats/MOF/read.jl`
+ - [ ] `set_to_moi` is defined for each set in `src/FileFormats/MOF/read.jl`
+ - [ ] `head_name` is defined for each set in `src/FileFormats/MOF/write.jl`
+ - [ ] A new unit test calling `_test_model_equality` is aded to
+       `test/FileFormats/MOF/MOF.jl`
+
+## Tests
+
+ - [ ] The version field in `test/FileFormats/MOF/nlp.mof.json` is updated
+
+## Documentation
+
+ - [ ] The version fields are updated in `docs/src/submodules/FileFormats/overview.md`
diff --git a/previews/PR2274/index.html b/previews/PR2274/index.html new file mode 100644 index 0000000000..0a4dff58ff --- /dev/null +++ b/previews/PR2274/index.html @@ -0,0 +1,9 @@ + +Introduction · MathOptInterface

Introduction

Welcome to the documentation for MathOptInterface.

Note

This documentation is also available in PDF format: MathOptInterface.pdf.

What is MathOptInterface?

MathOptInterface.jl (MOI) is an abstraction layer designed to provide a unified interface to mathematical optimization solvers so that users do not need to understand multiple solver-specific APIs.

Tip

This documentation is aimed at developers writing software interfaces to solvers and modeling languages using the MathOptInterface API. If you are a user interested in solving optimization problems, we encourage you instead to use MOI through a higher-level modeling interface like JuMP or Convex.jl.

How the documentation is structured

Having a high-level overview of how this documentation is structured will help you know where to look for certain things.

  • The Tutorials section contains articles on how to use and implement the MathOptInteraface API. Look here if you want to write a model in MOI, or write an interface to a new solver.
  • The Manual contains short code-snippets that explain how to use the MOI API. Look here for more details on particular areas of MOI.
  • The Background section contains articles on the theory behind MathOptInterface. Look here if you want to understand why, rather than how.
  • The API Reference contains a complete list of functions and types that comprise the MOI API. Look here is you want to know how to use (or implement) a particular function.
  • The Submodules section contains stand-alone documentation for each of the submodules within MOI. These submodules are not required to interface a solver with MOI, but they make the job much easier.

Citing MathOptInterface

A paper describing the design and features of MathOptInterface is available on arXiv.

If you find MathOptInterface useful in your work, we kindly request that you cite the following paper:

@article{legat2021mathoptinterface,
+    title={{MathOptInterface}: a data structure for mathematical optimization problems},
+    author={Legat, Beno{\^\i}t and Dowson, Oscar and Garcia, Joaquim Dias and Lubin, Miles},
+    journal={INFORMS Journal on Computing},
+    year={2021},
+    doi={10.1287/ijoc.2021.1067},
+    publisher={INFORMS}
+}
diff --git a/previews/PR2274/manual/constraints/index.html b/previews/PR2274/manual/constraints/index.html new file mode 100644 index 0000000000..2a6c96ad66 --- /dev/null +++ b/previews/PR2274/manual/constraints/index.html @@ -0,0 +1,22 @@ + +Constraints · MathOptInterface

Constraints

Add a constraint

Use add_constraint to add a single constraint.

julia> c = MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(2))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)

add_constraint returns a ConstraintIndex type, which is used to refer to the added constraint in other calls.

Check if a ConstraintIndex is valid using is_valid.

julia> MOI.is_valid(model, c)
+true

Use add_constraints to add a number of constraints of the same type.

julia> c = MOI.add_constraints(
+           model,
+           [x[1], x[2]],
+           [MOI.GreaterThan(0.0), MOI.GreaterThan(1.0)]
+       )
+2-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(2)

This time, a vector of ConstraintIndex are returned.

Use supports_constraint to check if the model supports adding a constraint type.

julia> MOI.supports_constraint(
+           model,
+           MOI.VariableIndex,
+           MOI.GreaterThan{Float64},
+       )
+true

Delete a constraint

Use delete to delete a constraint.

julia> MOI.delete(model, c)
+
+julia> MOI.is_valid(model, c)
+false

Constraint attributes

The following attributes are available for constraints:

Get and set these attributes using get and set.

julia> MOI.set(model, MOI.ConstraintName(), c, "con_c")
+
+julia> MOI.get(model, MOI.ConstraintName(), c)
+"con_c"

Constraints by function-set pairs

Below is a list of common constraint types and how they are represented as function-set pairs in MOI. In the notation below, $x$ is a vector of decision variables, $x_i$ is a scalar decision variable, $\alpha, \beta$ are scalar constants, $a, b$ are constant vectors, A is a constant matrix and $\mathbb{R}_+$ (resp. $\mathbb{R}_-$) is the set of non-negative (resp. non-positive) real numbers.

Linear constraints

Mathematical ConstraintMOI FunctionMOI Set
$a^Tx \le \beta$ScalarAffineFunctionLessThan
$a^Tx \ge \alpha$ScalarAffineFunctionGreaterThan
$a^Tx = \beta$ScalarAffineFunctionEqualTo
$\alpha \le a^Tx \le \beta$ScalarAffineFunctionInterval
$x_i \le \beta$VariableIndexLessThan
$x_i \ge \alpha$VariableIndexGreaterThan
$x_i = \beta$VariableIndexEqualTo
$\alpha \le x_i \le \beta$VariableIndexInterval
$Ax + b \in \mathbb{R}_+^n$VectorAffineFunctionNonnegatives
$Ax + b \in \mathbb{R}_-^n$VectorAffineFunctionNonpositives
$Ax + b = 0$VectorAffineFunctionZeros

By convention, solvers are not expected to support nonzero constant terms in the ScalarAffineFunctions the first four rows of the preceding table because they are redundant with the parameters of the sets. For example, encode $2x + 1 \le 2$ as $2x \le 1$.

Constraints with VariableIndex in LessThan, GreaterThan, EqualTo, or Interval sets have a natural interpretation as variable bounds. As such, it is typically not natural to impose multiple lower- or upper-bounds on the same variable, and the solver interfaces will throw respectively LowerBoundAlreadySet or UpperBoundAlreadySet.

Moreover, adding two VariableIndex constraints on the same variable with the same set is impossible because they share the same index as it is the index of the variable, see ConstraintIndex.

It is natural, however, to impose upper- and lower-bounds separately as two different constraints on a single variable. The difference between imposing bounds by using a single Interval constraint and by using separate LessThan and GreaterThan constraints is that the latter will allow the solver to return separate dual multipliers for the two bounds, while the former will allow the solver to return only a single dual for the interval constraint.

Conic constraints

Mathematical ConstraintMOI FunctionMOI Set
$\lVert Ax + b\rVert_2 \le c^Tx + d$VectorAffineFunctionSecondOrderCone
$y \ge \lVert x \rVert_2$VectorOfVariablesSecondOrderCone
$2yz \ge \lVert x \rVert_2^2, y,z \ge 0$VectorOfVariablesRotatedSecondOrderCone
$(a_1^Tx + b_1,a_2^Tx + b_2,a_3^Tx + b_3) \in \mathcal{E}$VectorAffineFunctionExponentialCone
$A(x) \in \mathcal{S}_+$VectorAffineFunctionPositiveSemidefiniteConeTriangle
$B(x) \in \mathcal{S}_+$VectorAffineFunctionPositiveSemidefiniteConeSquare
$x \in \mathcal{S}_+$VectorOfVariablesPositiveSemidefiniteConeTriangle
$x \in \mathcal{S}_+$VectorOfVariablesPositiveSemidefiniteConeSquare

where $\mathcal{E}$ is the exponential cone (see ExponentialCone), $\mathcal{S}_+$ is the set of positive semidefinite symmetric matrices, $A$ is an affine map that outputs symmetric matrices and $B$ is an affine map that outputs square matrices.

Quadratic constraints

Mathematical ConstraintMOI FunctionMOI Set
$\frac{1}{2}x^TQx + a^Tx + b \ge 0$ScalarQuadraticFunctionGreaterThan
$\frac{1}{2}x^TQx + a^Tx + b \le 0$ScalarQuadraticFunctionLessThan
$\frac{1}{2}x^TQx + a^Tx + b = 0$ScalarQuadraticFunctionEqualTo
Bilinear matrix inequalityVectorQuadraticFunctionPositiveSemidefiniteCone...
Note

For more details on the internal format of the quadratic functions see ScalarQuadraticFunction or VectorQuadraticFunction.

Discrete and logical constraints

Mathematical ConstraintMOI FunctionMOI Set
$x_i \in \mathbb{Z}$VariableIndexInteger
$x_i \in \{0,1\}$VariableIndexZeroOne
$x_i \in \{0\} \cup [l,u]$VariableIndexSemicontinuous
$x_i \in \{0\} \cup \{l,l+1,\ldots,u-1,u\}$VariableIndexSemiinteger
At most one component of $x$ can be nonzeroVectorOfVariablesSOS1
At most two components of $x$ can be nonzero, and if so they must be adjacent componentsVectorOfVariablesSOS2
$y = 1 \implies a^T x \in S$VectorAffineFunctionIndicator

JuMP mapping

The following bullet points show examples of how JuMP constraints are translated into MOI function-set pairs:

  • @constraint(m, 2x + y <= 10) becomes ScalarAffineFunction-in-LessThan
  • @constraint(m, 2x + y >= 10) becomes ScalarAffineFunction-in-GreaterThan
  • @constraint(m, 2x + y == 10) becomes ScalarAffineFunction-in-EqualTo
  • @constraint(m, 0 <= 2x + y <= 10) becomes ScalarAffineFunction-in-Interval
  • @constraint(m, 2x + y in ArbitrarySet()) becomes ScalarAffineFunction-in-ArbitrarySet.

Variable bounds are handled in a similar fashion:

  • @variable(m, x <= 1) becomes VariableIndex-in-LessThan
  • @variable(m, x >= 1) becomes VariableIndex-in-GreaterThan

One notable difference is that a variable with an upper and lower bound is translated into two constraints, rather than an interval, that is:

  • @variable(m, 0 <= x <= 1) becomes VariableIndex-in-LessThan and VariableIndex-in-GreaterThan.
diff --git a/previews/PR2274/manual/models/index.html b/previews/PR2274/manual/models/index.html new file mode 100644 index 0000000000..ecef34316f --- /dev/null +++ b/previews/PR2274/manual/models/index.html @@ -0,0 +1,2 @@ + +Models · MathOptInterface

Models

The most significant part of MOI is the definition of the model API that is used to specify an instance of an optimization problem (for example, by adding variables and constraints). Objects that implement the model API must inherit from the ModelLike abstract type.

Notably missing from the model API is the method to solve an optimization problem. ModelLike objects may store an instance (for example, in memory or backed by a file format) without being linked to a particular solver. In addition to the model API, MOI defines AbstractOptimizer and provides methods to solve the model and interact with solutions. See the Solutions section for more details.

Info

Throughout the rest of the manual, model is used as a generic ModelLike, and optimizer is used as a generic AbstractOptimizer.

Tip

MOI does not export functions, but for brevity we often omit qualifying names with the MOI module. Best practice is to have

import MathOptInterface as MOI

and prefix all MOI methods with MOI. in user code. If a name is also available in base Julia, we always explicitly use the module prefix, for example, with MOI.get.

Attributes

Attributes are properties of the model that can be queried and modified. These include constants such as the number of variables in a model NumberOfVariables), and properties of variables and constraints such as the name of a variable (VariableName).

There are four types of attributes:

Some attributes are values that can be queried by the user but not modified, while other attributes can be modified by the user.

All interactions with attributes occur through the get and set functions.

Consult the docstrings of each attribute for information on what it represents.

ModelLike API

The following attributes are available:

AbstractOptimizer API

The following attributes are available:

diff --git a/previews/PR2274/manual/modification/index.html b/previews/PR2274/manual/modification/index.html new file mode 100644 index 0000000000..5c2148c7c6 --- /dev/null +++ b/previews/PR2274/manual/modification/index.html @@ -0,0 +1,125 @@ + +Problem modification · MathOptInterface

Problem modification

In addition to adding and deleting constraints and variables, MathOptInterface supports modifying, in-place, coefficients in the constraints and the objective function of a model.

These modifications can be grouped into two categories:

  • modifications which replace the set of function of a constraint with a new set or function
  • modifications which change, in-place, a component of a function
Warning

Some ModelLike objects do not support problem modification.

Modify the set of a constraint

Use set and ConstraintSet to modify the set of a constraint by replacing it with a new instance of the same type.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.EqualTo(2.0));
+
+julia> MOI.get(model, MOI.ConstraintSet(), c) == MOI.EqualTo(2.0)
+true

However, the following will fail as the new set is of a different type to the original set:

julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan(2.0))
+ERROR: [...]

Special cases: set transforms

If our constraint is an affine inequality, then this corresponds to modifying the right-hand side of a constraint in linear programming.

In some special cases, solvers may support efficiently changing the set of a constraint (for example, from LessThan to GreaterThan). For these cases, MathOptInterface provides the transform method.

The transform function returns a new constraint index, and the old constraint index (that is, c) is no longer valid.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.LessThan(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}}(1)
+
+julia> new_c = MOI.transform(model, c, MOI.GreaterThan(2.0));
+
+julia> MOI.is_valid(model, c)
+false
+
+julia> MOI.is_valid(model, new_c)
+true
Note

transform cannot be called with a set of the same type. Use set instead.

Modify the function of a constraint

Use set and ConstraintFunction to modify the function of a constraint by replacing it with a new instance of the same type.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 1.0);
+
+julia> MOI.set(model, MOI.ConstraintFunction(), c, new_f);
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

However, the following will fail as the new function is of a different type to the original function:

julia> MOI.set(model, MOI.ConstraintFunction(), c, x)
+ERROR: [...]

Modify constant term in a scalar function

Use modify and ScalarConstantChange to modify the constant term in a ScalarAffineFunction or ScalarQuadraticFunction.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> MOI.modify(model, c, MOI.ScalarConstantChange(1.0));
+
+julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 1.0);
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

ScalarConstantChange can also be used to modify the objective function by passing an instance of ObjectiveFunction:

julia> MOI.set(
+           model,
+           MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
+           new_f,
+       );
+
+julia> MOI.modify(
+           model,
+           MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
+           MOI.ScalarConstantChange(-1.0)
+       );
+
+julia> MOI.get(
+           model,
+           MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
+       ) ≈ MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], -1.0)
+true

Modify constant terms in a vector function

Use modify and VectorConstantChange to modify the constant vector in a VectorAffineFunction or VectorQuadraticFunction.

julia> c = MOI.add_constraint(
+           model,
+           MOI.VectorAffineFunction([
+                   MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
+                   MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
+               ],
+               [0.0, 0.0],
+           ),
+           MOI.Nonnegatives(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
+
+julia> MOI.modify(model, c, MOI.VectorConstantChange([3.0, 4.0]));
+
+julia> new_f = MOI.VectorAffineFunction(
+           [
+        MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
+        MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
+           ],
+           [3.0, 4.0],
+       );
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

Modify affine coefficients in a scalar function

Use modify and ScalarCoefficientChange to modify the affine coefficient of a ScalarAffineFunction or ScalarQuadraticFunction.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> MOI.modify(model, c, MOI.ScalarCoefficientChange(x, 2.0));
+
+julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 0.0);
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

ScalarCoefficientChange can also be used to modify the objective function by passing an instance of ObjectiveFunction.

Modify affine coefficients in a vector function

Use modify and MultirowChange to modify a vector of affine coefficients in a VectorAffineFunction or a VectorQuadraticFunction.

julia> c = MOI.add_constraint(
+           model,
+           MOI.VectorAffineFunction([
+                   MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
+                   MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
+               ],
+               [0.0, 0.0],
+           ),
+           MOI.Nonnegatives(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
+
+julia> MOI.modify(model, c, MOI.MultirowChange(x, [(1, 3.0), (2, 4.0)]));
+
+julia> new_f = MOI.VectorAffineFunction(
+           [
+        MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(3.0, x)),
+        MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(4.0, x)),
+           ],
+           [0.0, 0.0],
+       );
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true
diff --git a/previews/PR2274/manual/solutions/index.html b/previews/PR2274/manual/solutions/index.html new file mode 100644 index 0000000000..c6eca10056 --- /dev/null +++ b/previews/PR2274/manual/solutions/index.html @@ -0,0 +1,35 @@ + +Solutions · MathOptInterface

Solutions

Solving and retrieving the results

Once an optimizer is loaded with the objective function and all of the constraints, we can ask the solver to solve the model by calling optimize!.

MOI.optimize!(optimizer)

Why did the solver stop?

The optimization procedure may stop for a number of reasons. The TerminationStatus attribute of the optimizer returns a TerminationStatusCode object which explains why the solver stopped.

The termination statuses distinguish between proofs of optimality, infeasibility, local convergence, limits, and termination because of something unexpected like invalid problem data or failure to converge.

A typical usage of the TerminationStatus attribute is as follows:

status = MOI.get(optimizer, TerminationStatus())
+if status == MOI.OPTIMAL
+    # Ok, we solved the problem!
+else
+    # Handle other cases.
+end

After checking the TerminationStatus, check ResultCount. This attribute returns the number of results that the solver has available to return. A result is defined as a primal-dual pair, but either the primal or the dual may be missing from the result. While the OPTIMAL termination status normally implies that at least one result is available, other statuses do not. For example, in the case of infeasibility, a solver may return no result or a proof of infeasibility. The ResultCount attribute distinguishes between these two cases.

Primal solutions

Use the PrimalStatus optimizer attribute to return a ResultStatusCode describing the status of the primal solution.

Common returns are described below in the Common status situations section.

Query the primal solution using the VariablePrimal and ConstraintPrimal attributes.

Query the objective function value using the ObjectiveValue attribute.

Dual solutions

Warning

See Duality for a discussion of the MOI conventions for primal-dual pairs and certificates.

Use the DualStatus optimizer attribute to return a ResultStatusCode describing the status of the dual solution.

Query the dual solution using the ConstraintDual attribute.

Query the dual objective function value using the DualObjectiveValue attribute.

Common status situations

The sections below describe how to interpret typical or interesting status cases for three common classes of solvers. The example cases are illustrative, not comprehensive. Solver wrappers may provide additional information on how the solver's statuses map to MOI statuses.

Info

* in the tables indicate that multiple different values are possible.

Primal-dual convex solver

Linear programming and conic optimization solvers fall into this category.

What happened?TerminationStatusResultCountPrimalStatusDualStatus
Proved optimalityOPTIMAL1FEASIBLE_POINTFEASIBLE_POINT
Proved infeasibleINFEASIBLE1NO_SOLUTIONINFEASIBILITY_CERTIFICATE
Optimal within relaxed tolerancesALMOST_OPTIMAL1FEASIBLE_POINTFEASIBLE_POINT
Optimal within relaxed tolerancesALMOST_OPTIMAL1ALMOST_FEASIBLE_POINTALMOST_FEASIBLE_POINT
Detected an unbounded ray of the primalDUAL_INFEASIBLE1INFEASIBILITY_CERTIFICATENO_SOLUTION
StallSLOW_PROGRESS1**

Global branch-and-bound solvers

Mixed-integer programming solvers fall into this category.

What happened?TerminationStatusResultCountPrimalStatusDualStatus
Proved optimalityOPTIMAL1FEASIBLE_POINTNO_SOLUTION
Presolve detected infeasibility or unboundednessINFEASIBLE_OR_UNBOUNDED0NO_SOLUTIONNO_SOLUTION
Proved infeasibilityINFEASIBLE0NO_SOLUTIONNO_SOLUTION
Timed out (no solution)TIME_LIMIT0NO_SOLUTIONNO_SOLUTION
Timed out (with a solution)TIME_LIMIT1FEASIBLE_POINTNO_SOLUTION
CPXMIP_OPTIMAL_INFEASALMOST_OPTIMAL1INFEASIBLE_POINTNO_SOLUTION
Info

CPXMIP_OPTIMAL_INFEAS is a CPLEX status that indicates that a preprocessed problem was solved to optimality, but the solver was unable to recover a feasible solution to the original problem. Handling this status was one of the motivating drivers behind the design of MOI.

Local search solvers

Nonlinear programming solvers fall into this category. It also includes non-global tree search solvers like Juniper.

What happened?TerminationStatusResultCountPrimalStatusDualStatus
Converged to a stationary pointLOCALLY_SOLVED1FEASIBLE_POINTFEASIBLE_POINT
Completed a non-global tree search (with a solution)LOCALLY_SOLVED1FEASIBLE_POINTFEASIBLE_POINT
Converged to an infeasible pointLOCALLY_INFEASIBLE1INFEASIBLE_POINT*
Completed a non-global tree search (no solution found)LOCALLY_INFEASIBLE0NO_SOLUTIONNO_SOLUTION
Iteration limitITERATION_LIMIT1**
Diverging iteratesNORM_LIMIT or OBJECTIVE_LIMIT1**

Querying solution attributes

Some solvers will not implement every solution attribute. Therefore, a call like MOI.get(model, MOI.SolveTimeSec()) may throw an UnsupportedAttribute error.

If you need to write code that is agnostic to the solver (for example, you are writing a library that an end-user passes their choice of solver to), you can work-around this problem using a try-catch:

function get_solve_time(model)
+    try
+        return MOI.get(model, MOI.SolveTimeSec())
+    catch err
+        if err isa MOI.UnsupportedAttribute
+            return NaN  # Solver doesn't support. Return a placeholder value.
+        end
+        rethrow(err)  # Something else went wrong. Rethrow the error
+    end
+end

If, after careful profiling, you find that the try-catch is taking a significant portion of your runtime, you can improve performance by caching the result of the try-catch:

mutable struct CachedSolveTime{M}
+    model::M
+    supports_solve_time::Bool
+    CachedSolveTime(model::M) where {M} = new(model, true)
+end
+
+function get_solve_time(model::CachedSolveTime)
+    if !model.supports_solve_time
+        return NaN
+    end
+    try
+        return MOI.get(model, MOI.SolveTimeSec())
+    catch err
+        if err isa MOI.UnsupportedAttribute
+            model.supports_solve_time = false
+            return NaN
+        end
+        rethrow(err)  # Something else went wrong. Rethrow the error
+    end
+end
diff --git a/previews/PR2274/manual/standard_form/index.html b/previews/PR2274/manual/standard_form/index.html new file mode 100644 index 0000000000..4e7251bdc6 --- /dev/null +++ b/previews/PR2274/manual/standard_form/index.html @@ -0,0 +1,6 @@ + +Standard form problem · MathOptInterface

Standard form problem

MathOptInterface represents optimization problems in the standard form:

\[\begin{align} + & \min_{x \in \mathbb{R}^n} & f_0(x) + \\ + & \;\;\text{s.t.} & f_i(x) & \in \mathcal{S}_i & i = 1 \ldots m +\end{align}\]

where:

  • the functions $f_0, f_1, \ldots, f_m$ are specified by AbstractFunction objects
  • the sets $\mathcal{S}_1, \ldots, \mathcal{S}_m$ are specified by AbstractSet objects
Tip

For more information on this standard form, read our paper.

MOI defines some commonly used functions and sets, but the interface is extensible to other sets recognized by the solver.

Functions

The function types implemented in MathOptInterface.jl are:

FunctionDescription
VariableIndex$x_j$, the projection onto a single coordinate defined by a variable index $j$.
VectorOfVariablesThe projection onto multiple coordinates (that is, extracting a sub-vector).
ScalarAffineFunction$a^T x + b$, where $a$ is a vector and $b$ scalar.
ScalarNonlinearFunction$f(x)$, where $f$ is a nonlinear function.
VectorAffineFunction$A x + b$, where $A$ is a matrix and $b$ is a vector.
ScalarQuadraticFunction$\frac{1}{2} x^T Q x + a^T x + b$, where $Q$ is a symmetric matrix, $a$ is a vector, and $b$ is a constant.
VectorQuadraticFunctionA vector of scalar-valued quadratic functions.
VectorNonlinearFunction$f(x)$, where $f$ is a vector-valued nonlinear function.

Extensions for nonlinear programming are present but not yet well documented.

One-dimensional sets

The one-dimensional set types implemented in MathOptInterface.jl are:

SetDescription
LessThan(u)$(-\infty, u]$
GreaterThan(l)$[l, \infty)$
EqualTo(v)$\{v\}$
Interval(l, u)$[l, u]$
Integer()$\mathbb{Z}$
ZeroOne()$\{ 0, 1 \}$
Semicontinuous(l, u)$\{ 0\} \cup [l, u]$
Semiinteger(l, u)$\{ 0\} \cup \{l,l+1,\ldots,u-1,u\}$

Vector cones

The vector-valued set types implemented in MathOptInterface.jl are:

SetDescription
Reals(d)$\mathbb{R}^{d}$
Zeros(d)$0^{d}$
Nonnegatives(d)$\{ x \in \mathbb{R}^{d} : x \ge 0 \}$
Nonpositives(d)$\{ x \in \mathbb{R}^{d} : x \le 0 \}$
SecondOrderCone(d)$\{ (t,x) \in \mathbb{R}^{d} : t \ge \lVert x \rVert_2 \}$
RotatedSecondOrderCone(d)$\{ (t,u,x) \in \mathbb{R}^{d} : 2tu \ge \lVert x \rVert_2^2, t \ge 0,u \ge 0 \}$
ExponentialCone()$\{ (x,y,z) \in \mathbb{R}^3 : y \exp (x/y) \le z, y > 0 \}$
DualExponentialCone()$\{ (u,v,w) \in \mathbb{R}^3 : -u \exp (v/u) \le \exp(1) w, u < 0 \}$
GeometricMeanCone(d)$\{ (t,x) \in \mathbb{R}^{1+n} : x \ge 0, t \le \sqrt[n]{x_1 x_2 \cdots x_n} \}$ where $n$ is $d - 1$
PowerCone(α)$\{ (x,y,z) \in \mathbb{R}^3 : x^{\alpha} y^{1-\alpha} \ge |z|, x \ge 0,y \ge 0 \}$
DualPowerCone(α)$\{ (u,v,w) \in \mathbb{R}^3 : \left(\frac{u}{\alpha}\right(^{\alpha}\left(\frac{v}{1-\alpha}\right)^{1-\alpha} \ge |w|, u,v \ge 0 \}$
NormOneCone(d)$\{ (t,x) \in \mathbb{R}^{d} : t \ge \sum_i \lvert x_i \rvert \}$
NormInfinityCone(d)$\{ (t,x) \in \mathbb{R}^{d} : t \ge \max_i \lvert x_i \rvert \}$
RelativeEntropyCone(d)$\{ (u, v, w) \in \mathbb{R}^{d} : u \ge \sum_i w_i \log (\frac{w_i}{v_i}), v_i \ge 0, w_i \ge 0 \}$
HyperRectangle(l, u)$\{x \in \bar{\mathbb{R}}^d: x_i \in [l_i, u_i] \forall i=1,\ldots,d\}$
NormCone(p, d)``{ (t,x) \in \mathbb{R}^{d} : t \ge \left(\sum\limits_i

Matrix cones

The matrix-valued set types implemented in MathOptInterface.jl are:

SetDescription
RootDetConeTriangle(d)$\{ (t,X) \in \mathbb{R}^{1+d(1+d)/2} : t \le \det(X)^{1/d}, X \mbox{ is the upper triangle of a PSD matrix} \}$
RootDetConeSquare(d)$\{ (t,X) \in \mathbb{R}^{1+d^2} : t \le \det(X)^{1/d}, X \mbox{ is a PSD matrix} \}$
PositiveSemidefiniteConeTriangle(d)$\{ X \in \mathbb{R}^{d(d+1)/2} : X \mbox{ is the upper triangle of a PSD matrix} \}$
PositiveSemidefiniteConeSquare(d)$\{ X \in \mathbb{R}^{d^2} : X \mbox{ is a PSD matrix} \}$
LogDetConeTriangle(d)$\{ (t,u,X) \in \mathbb{R}^{2+d(1+d)/2} : t \le u\log(\det(X/u)), X \mbox{ is the upper triangle of a PSD matrix}, u > 0 \}$
LogDetConeSquare(d)$\{ (t,u,X) \in \mathbb{R}^{2+d^2} : t \le u \log(\det(X/u)), X \mbox{ is a PSD matrix}, u > 0 \}$
NormSpectralCone(r, c)$\{ (t, X) \in \mathbb{R}^{1 + r \times c} : t \ge \sigma_1(X), X \mbox{ is a } r\times c\mbox{ matrix} \}$
NormNuclearCone(r, c)$\{ (t, X) \in \mathbb{R}^{1 + r \times c} : t \ge \sum_i \sigma_i(X), X \mbox{ is a } r\times c\mbox{ matrix} \}$
HermitianPositiveSemidefiniteConeTriangle(d)The cone of Hermitian positive semidefinite matrices, with
side_dimension rows and columns.
Scaled(S)The set S scaled so that Utilities.set_dot corresponds to LinearAlgebra.dot

Some of these cones can take two forms: XXXConeTriangle and XXXConeSquare.

In XXXConeTriangle sets, the matrix is assumed to be symmetric, and the elements are provided by a vector, in which the entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row).

In XXXConeSquare sets, the entries of the matrix are given column by column (or equivalently, row by row), and the matrix is constrained to be symmetric. As an example, given a 2-by-2 matrix of variables X and a one-dimensional variable t, we can specify a root-det constraint as [t, X11, X12, X22] ∈ RootDetConeTriangle or [t, X11, X12, X21, X22] ∈ RootDetConeSquare.

We provide both forms to enable flexibility for solvers who may natively support one or the other. Transformations between XXXConeTriangle and XXXConeSquare are handled by bridges, which removes the chance of conversion mistakes by users or solver developers.

Multi-dimensional sets with combinatorial structure

Other sets are vector-valued, with a particular combinatorial structure. Read their docstrings for more information on how to interpret them.

SetDescription
SOS1A Special Ordered Set (SOS) of Type I
SOS2A Special Ordered Set (SOS) of Type II
IndicatorA set to specify an indicator constraint
ComplementsA set to specify a mixed complementarity constraint
AllDifferentThe all_different global constraint
BinPackingThe bin_packing global constraint
CircuitThe circuit global constraint
CountAtLeastThe at_least global constraint
CountBelongsThe nvalue global constraint
CountDistinctThe distinct global constraint
CountGreaterThanThe count_gt global constraint
CumulativeThe cumulative global constraint
PathThe path global constraint
TableThe table global constraint
diff --git a/previews/PR2274/manual/variables/index.html b/previews/PR2274/manual/variables/index.html new file mode 100644 index 0000000000..a748433b1d --- /dev/null +++ b/previews/PR2274/manual/variables/index.html @@ -0,0 +1,13 @@ + +Variables · MathOptInterface

Variables

Add a variable

Use add_variable to add a single variable.

julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)

add_variable returns a VariableIndex type, which is used to refer to the added variable in other calls.

Check if a VariableIndex is valid using is_valid.

julia> MOI.is_valid(model, x)
+true

Use add_variables to add a number of variables.

julia> y = MOI.add_variables(model, 2)
+2-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
Warning

The integer does not necessarily correspond to the column inside an optimizer.

Delete a variable

Delete a variable using delete.

julia> MOI.delete(model, x)
+
+julia> MOI.is_valid(model, x)
+false
Warning

Not all ModelLike models support deleting variables. A DeleteNotAllowed error is thrown if this is not supported.

Variable attributes

The following attributes are available for variables:

Get and set these attributes using get and set.

julia> MOI.set(model, MOI.VariableName(), x, "var_x")
+
+julia> MOI.get(model, MOI.VariableName(), x)
+"var_x"
diff --git a/previews/PR2274/reference/callbacks/index.html b/previews/PR2274/reference/callbacks/index.html new file mode 100644 index 0000000000..dac9c59ba8 --- /dev/null +++ b/previews/PR2274/reference/callbacks/index.html @@ -0,0 +1,32 @@ + +Callbacks · MathOptInterface

Callbacks

MathOptInterface.AbstractCallbackType
abstract type AbstractCallback <: AbstractModelAttribute end

Abstract type for a model attribute representing a callback function. The value set to subtypes of AbstractCallback is a function that may be called during optimize!. As optimize! is in progress, the result attributes (i.e, the attributes attr such that is_set_by_optimize(attr)) may not be accessible from the callback, hence trying to get result attributes might throw a OptimizeInProgress error.

At most one callback of each type can be registered. If an optimizer already has a function for a callback type, and the user registers a new function, then the old one is replaced.

The value of the attribute should be a function taking only one argument, commonly called callback_data, that can be used for instance in LazyConstraintCallback, HeuristicCallback and UserCutCallback.

source
MathOptInterface.submitFunction
submit(
+    optimizer::AbstractOptimizer,
+    sub::AbstractSubmittable,
+    values...,
+)::Nothing

Submit values to the submittable sub of the optimizer optimizer.

An UnsupportedSubmittable error is thrown if model does not support the attribute attr (see supports) and a SubmitNotAllowed error is thrown if it supports the submittable sub but it cannot be submitted.

source

Attributes

MathOptInterface.CallbackNodeStatusCodeType
CallbackNodeStatusCode

An Enum of possible return values from calling get with CallbackNodeStatus.

Values

Possible values are:

source

Lazy constraints

MathOptInterface.LazyConstraintCallbackType
LazyConstraintCallback() <: AbstractCallback

The callback can be used to reduce the feasible set given the current primal solution by submitting a LazyConstraint. For instance, it may be called at an incumbent of a mixed-integer problem. Note that there is no guarantee that the callback is called at every feasible primal solution.

The current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
+MOI.set(optimizer, MOI.LazyConstraintCallback(), callback_data -> begin
+    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
+    if # should add a lazy constraint
+        func = # computes function
+        set = # computes set
+        MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)
+    end
+end)
source
MathOptInterface.LazyConstraintType
LazyConstraint(callback_data)

Lazy constraint func-in-set submitted as func, set. The optimal solution returned by VariablePrimal will satisfy all lazy constraints that have been submitted.

This can be submitted only from the LazyConstraintCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the feasible solution callback.

Examples

Suppose x and y are VariableIndexs of optimizer. To add a LazyConstraint for 2x + 3y <= 1, write

func = 2.0x + 3.0y
+set = MOI.LessThan(1.0)
+MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)

inside a LazyConstraintCallback of data callback_data.

source

User cuts

MathOptInterface.UserCutCallbackType
UserCutCallback() <: AbstractCallback

The callback can be used to submit UserCut given the current primal solution. For instance, it may be called at fractional (i.e., non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is not guarantee that the callback is called everytime the solver has an infeasible solution.

The infeasible solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
+MOI.set(optimizer, MOI.UserCutCallback(), callback_data -> begin
+    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
+    if # can find a user cut
+        func = # computes function
+        set = # computes set
+        MOI.submit(optimizer, MOI.UserCut(callback_data), func, set)
+    end
+end
source
MathOptInterface.UserCutType
UserCut(callback_data)

Constraint func-to-set suggested to help the solver detect the solution given by CallbackVariablePrimal as infeasible. The cut is submitted as func, set. Typically CallbackVariablePrimal will violate integrality constraints, and a cut would be of the form ScalarAffineFunction-in-LessThan or ScalarAffineFunction-in-GreaterThan. Note that, as opposed to LazyConstraint, the provided constraint cannot modify the feasible set, the constraint should be redundant, e.g., it may be a consequence of affine and integrality constraints.

This can be submitted only from the UserCutCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the infeasible solution callback.

Note that the solver may silently ignore the provided constraint.

source

Heuristic solutions

MathOptInterface.HeuristicCallbackType
HeuristicCallback() <: AbstractCallback

The callback can be used to submit HeuristicSolution given the current primal solution. For example, it may be called at fractional (i.e., non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is no guarantee that the callback is called every time the solver has an infeasible solution.

The current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
+MOI.set(optimizer, MOI.HeuristicCallback(), callback_data -> begin
+    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
+    if # can find a heuristic solution
+        values = # computes heuristic solution
+        MOI.submit(optimizer, MOI.HeuristicSolution(callback_data), x,
+                   values)
+    end
+end
source
MathOptInterface.HeuristicSolutionType
HeuristicSolution(callback_data)

Heuristically obtained feasible solution. The solution is submitted as variables, values where values[i] gives the value of variables[i], similarly to set. The submit call returns a HeuristicSolutionStatus indicating whether the provided solution was accepted or rejected.

This can be submitted only from the HeuristicCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the heuristic callback.

Some solvers require a complete solution, others only partial solutions.

source
diff --git a/previews/PR2274/reference/constraints/index.html b/previews/PR2274/reference/constraints/index.html new file mode 100644 index 0000000000..3d8c1ef3c4 --- /dev/null +++ b/previews/PR2274/reference/constraints/index.html @@ -0,0 +1,12 @@ + +Constraints · MathOptInterface

Constraints

Types

MathOptInterface.ConstraintIndexType
ConstraintIndex{F, S}

A type-safe wrapper for Int64 for use in referencing F-in-S constraints in a model. The parameter F is the type of the function in the constraint, and the parameter S is the type of set in the constraint. To allow for deletion, indices need not be consecutive. Indices within a constraint type (i.e. F-in-S) must be unique, but non-unique indices across different constraint types are allowed. If F is VariableIndex then the index is equal to the index of the variable. That is for an index::ConstraintIndex{VariableIndex}, we always have

index.value == MOI.get(model, MOI.ConstraintFunction(), index).value
source

Functions

MathOptInterface.is_validMethod
is_valid(model::ModelLike, index::Index)::Bool

Return a Bool indicating whether this index refers to a valid object in the model model.

source
MathOptInterface.add_constraintFunction
add_constraint(model::ModelLike, func::F, set::S)::ConstraintIndex{F,S} where {F,S}

Add the constraint $f(x) \in \mathcal{S}$ where $f$ is defined by func, and $\mathcal{S}$ is defined by set.

add_constraint(model::ModelLike, v::VariableIndex, set::S)::ConstraintIndex{VariableIndex,S} where {S}
+add_constraint(model::ModelLike, vec::Vector{VariableIndex}, set::S)::ConstraintIndex{VectorOfVariables,S} where {S}

Add the constraint $v \in \mathcal{S}$ where $v$ is the variable (or vector of variables) referenced by v and $\mathcal{S}$ is defined by set.

source
MathOptInterface.add_constraintsFunction
add_constraints(model::ModelLike, funcs::Vector{F}, sets::Vector{S})::Vector{ConstraintIndex{F,S}} where {F,S}

Add the set of constraints specified by each function-set pair in funcs and sets. F and S should be concrete types. This call is equivalent to add_constraint.(model, funcs, sets) but may be more efficient.

source
MathOptInterface.transformFunction

Transform Constraint Set

transform(model::ModelLike, c::ConstraintIndex{F,S1}, newset::S2)::ConstraintIndex{F,S2}

Replace the set in constraint c with newset. The constraint index c will no longer be valid, and the function returns a new constraint index with the correct type.

Solvers may only support a subset of constraint transforms that they perform efficiently (for example, changing from a LessThan to GreaterThan set). In addition, set modification (where S1 = S2) should be performed via the modify function.

Typically, the user should delete the constraint and add a new one.

Examples

If c is a ConstraintIndex{ScalarAffineFunction{Float64},LessThan{Float64}},

c2 = transform(model, c, GreaterThan(0.0))
+transform(model, c, LessThan(0.0)) # errors
source
MathOptInterface.supports_constraintFunction
supports_constraint(
+    model::ModelLike,
+    ::Type{F},
+    ::Type{S},
+)::Bool where {F<:AbstractFunction,S<:AbstractSet}

Return a Bool indicating whether model supports F-in-S constraints, that is, copy_to(model, src) does not throw UnsupportedConstraint when src contains F-in-S constraints. If F-in-S constraints are only not supported in specific circumstances, e.g. F-in-S constraints cannot be combined with another type of constraint, it should still return true.

source
MOI.supports_constraint(
+    BT::Type{<:AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet},
+)::Bool

Return a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.

Implementation notes

  • This method depends only on the type of the inputs, not the runtime values.
  • There is a default fallback, so you need only implement this method for constraint types that the bridge implements.
source

Attributes

MathOptInterface.ConstraintNameType
ConstraintName()

A constraint attribute for a string identifying the constraint.

It is valid for constraints variables to have the same name; however, constraints with duplicate names cannot be looked up using get, regardless of whether they have the same F-in-S type.

ConstraintName has a default value of "" if not set.

Notes

You should not implement ConstraintName for VariableIndex constraints.

source
MathOptInterface.ConstraintPrimalType
ConstraintPrimal(result_index::Int = 1)

A constraint attribute for the assignment to some constraint's primal value(s) in result result_index.

If the constraint is f(x) in S, then in most cases the ConstraintPrimal is the value of f, evaluated at the correspondng VariablePrimal solution.

However, some conic solvers reformulate b - Ax in S to s = b - Ax, s in S. These solvers may return the value of s for ConstraintPrimal, rather than b - Ax. (Although these are constrained by an equality constraint, due to numerical tolerances they may not be identical.)

If the solver does not have a primal value for the constraint because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ConstraintPrimal attribute.

If result_index is omitted, it is 1 by default. See ResultCount for information on how the results are ordered.

source
MathOptInterface.ConstraintDualType
ConstraintDual(result_index::Int = 1)

A constraint attribute for the assignment to some constraint's dual value(s) in result result_index. If result_index is omitted, it is 1 by default.

If the solver does not have a dual value for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check DualStatus before accessing the ConstraintDual attribute.

See ResultCount for information on how the results are ordered.

source
MathOptInterface.ConstraintBasisStatusType
ConstraintBasisStatus(result_index::Int = 1)

A constraint attribute for the BasisStatusCode of some constraint in result result_index, with respect to an available optimal solution basis. If result_index is omitted, it is 1 by default.

If the solver does not have a basis statue for the constraint because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ConstraintBasisStatus attribute.

See ResultCount for information on how the results are ordered.

Notes

For the basis status of a variable, query VariableBasisStatus.

ConstraintBasisStatus does not apply to VariableIndex constraints. You can infer the basis status of a VariableIndex constraint by looking at the result of VariableBasisStatus.

source
MathOptInterface.ConstraintFunctionType
ConstraintFunction()

A constraint attribute for the AbstractFunction object used to define the constraint.

It is guaranteed to be equivalent but not necessarily identical to the function provided by the user.

source
MathOptInterface.CanonicalConstraintFunctionType
CanonicalConstraintFunction()

A constraint attribute for a canonical representation of the AbstractFunction object used to define the constraint.

Getting this attribute is guaranteed to return a function that is equivalent but not necessarily identical to the function provided by the user.

By default, MOI.get(model, MOI.CanonicalConstraintFunction(), ci) fallbacks to MOI.Utilities.canonical(MOI.get(model, MOI.ConstraintFunction(), ci)). However, if model knows that the constraint function is canonical then it can implement a specialized method that directly return the function without calling Utilities.canonical. Therefore, the value returned cannot be assumed to be a copy of the function stored in model. Moreover, Utilities.Model checks with Utilities.is_canonical whether the function stored internally is already canonical and if it's the case, then it returns the function stored internally instead of a copy.

source
MathOptInterface.BasisStatusCodeType
BasisStatusCode

An Enum of possible values for the ConstraintBasisStatus and VariableBasisStatus attributes, explaining the status of a given element with respect to an optimal solution basis.

Notes

  • NONBASIC_AT_LOWER and NONBASIC_AT_UPPER should be used only for

constraints with the Interval set. In this case, they are necessary to distinguish which side of the constraint is active. One-sided constraints (e.g., LessThan and GreaterThan) should use NONBASIC instead of the NONBASIC_AT_* values. This restriction does not apply to VariableBasisStatus, which should return NONBASIC_AT_* regardless of whether the alternative bound exists.

  • In linear programs, SUPER_BASIC occurs when a variable with no bounds is not

in the basis.

Values

Possible values are:

source
diff --git a/previews/PR2274/reference/errors/index.html b/previews/PR2274/reference/errors/index.html new file mode 100644 index 0000000000..7297397b42 --- /dev/null +++ b/previews/PR2274/reference/errors/index.html @@ -0,0 +1,48 @@ + +Errors · MathOptInterface

Errors

When an MOI call fails on a model, precise errors should be thrown when possible instead of simply calling error with a message. The docstrings for the respective methods describe the errors that the implementation should throw in certain situations. This error-reporting system allows code to distinguish between internal errors (that should be shown to the user) and unsupported operations which may have automatic workarounds.

When an invalid index is used in an MOI call, an InvalidIndex is thrown:

When an invalid result index is used to retrieve an attribute, a ResultIndexBoundsError is thrown:

MathOptInterface.ResultIndexBoundsErrorType
struct ResultIndexBoundsError{AttrType} <: Exception
+    attr::AttrType
+    result_count::Int
+end

An error indicating that the requested attribute attr could not be retrieved, because the solver returned too few results compared to what was requested. For instance, the user tries to retrieve VariablePrimal(2) when only one solution is available, or when the model is infeasible and has no solution.

See also: check_result_index_bounds.

source

As discussed in JuMP mapping, for scalar constraint with a nonzero function constant, a ScalarFunctionConstantNotZero exception may be thrown:

Some VariableIndex constraints cannot be combined on the same variable:

As discussed in AbstractCallback, trying to get attributes inside a callback may throw:

MathOptInterface.OptimizeInProgressType
struct OptimizeInProgress{AttrType<:AnyAttribute} <: Exception
+    attr::AttrType
+end

Error thrown from optimizer when MOI.get(optimizer, attr) is called inside an AbstractCallback while it is only defined once optimize! has completed. This can only happen when is_set_by_optimize(attr) is true.

source

Trying to submit the wrong type of AbstractSubmittable inside an AbstractCallback (for example, a UserCut inside a LazyConstraintCallback) will throw:

The rest of the errors defined in MOI fall in two categories represented by the following two abstract types:

MathOptInterface.NotAllowedErrorType
NotAllowedError <: Exception

Abstract type for error thrown when an operation is supported but cannot be applied in the current state of the model.

source

The different UnsupportedError and NotAllowedError are the following errors:

MathOptInterface.UnsupportedAttributeType
struct UnsupportedAttribute{AttrType} <: UnsupportedError
+    attr::AttrType
+    message::String
+end

An error indicating that the attribute attr is not supported by the model, i.e. that supports returns false.

source
MathOptInterface.SetAttributeNotAllowedType
struct SetAttributeNotAllowed{AttrType} <: NotAllowedError
+    attr::AttrType
+    message::String
+end

An error indicating that the attribute attr is supported (see supports) but cannot be set for some reason (see the error string).

source
MathOptInterface.AddVariableNotAllowedType
struct AddVariableNotAllowed <: NotAllowedError
+    message::String # Human-friendly explanation why the attribute cannot be set
+end

An error indicating that variables cannot be added to the model.

source
MathOptInterface.UnsupportedConstraintType
struct UnsupportedConstraint{F<:AbstractFunction, S<:AbstractSet} <: UnsupportedError
+    message::String # Human-friendly explanation why the attribute cannot be set
+end

An error indicating that constraints of type F-in-S are not supported by the model, i.e. that supports_constraint returns false.

source
MathOptInterface.AddConstraintNotAllowedType
struct AddConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet} <: NotAllowedError
+    message::String # Human-friendly explanation why the attribute cannot be set
+end

An error indicating that constraints of type F-in-S are supported (see supports_constraint) but cannot be added.

source
MathOptInterface.ModifyConstraintNotAllowedType
struct ModifyConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet,
+                                  C<:AbstractFunctionModification} <: NotAllowedError
+    constraint_index::ConstraintIndex{F, S}
+    change::C
+    message::String
+end

An error indicating that the constraint modification change cannot be applied to the constraint of index ci.

source
MathOptInterface.ModifyObjectiveNotAllowedType
struct ModifyObjectiveNotAllowed{C<:AbstractFunctionModification} <: NotAllowedError
+    change::C
+    message::String
+end

An error indicating that the objective modification change cannot be applied to the objective.

source
MathOptInterface.DeleteNotAllowedType
struct DeleteNotAllowed{IndexType <: Index} <: NotAllowedError
+    index::IndexType
+    message::String
+end

An error indicating that the index index cannot be deleted.

source
MathOptInterface.UnsupportedSubmittableType
struct UnsupportedSubmittable{SubmitType} <: UnsupportedError
+    sub::SubmitType
+    message::String
+end

An error indicating that the submittable sub is not supported by the model, i.e. that supports returns false.

source
MathOptInterface.SubmitNotAllowedType
struct SubmitNotAllowed{SubmitTyp<:AbstractSubmittable} <: NotAllowedError
+    sub::SubmitType
+    message::String
+end

An error indicating that the submittable sub is supported (see supports) but cannot be added for some reason (see the error string).

source
MathOptInterface.UnsupportedNonlinearOperatorType
UnsupportedNonlinearOperator(head::Symbol[, message::String]) <: UnsupportedError

An error thrown by optimizers if they do not support the operator head in a ScalarNonlinearFunction.

Example

julia> import MathOptInterface as MOI
+
+julia> throw(MOI.UnsupportedNonlinearOperator(:black_box))
+ERROR: MathOptInterface.UnsupportedNonlinearOperator: The nonlinear operator `:black_box` is not supported by the model.
+Stacktrace:
+[...]
source

Note that setting the ConstraintFunction of a VariableIndex constraint is not allowed:

diff --git a/previews/PR2274/reference/models/index.html b/previews/PR2274/reference/models/index.html new file mode 100644 index 0000000000..1d9ce7fe2a --- /dev/null +++ b/previews/PR2274/reference/models/index.html @@ -0,0 +1,132 @@ + +Models · MathOptInterface

Models

Attribute interface

MathOptInterface.is_set_by_optimizeFunction
is_set_by_optimize(::AnyAttribute)

Return a Bool indicating whether the value of the attribute is modified during an optimize! call, that is, the attribute is used to query the result of the optimization.

Important note when defining new attributes

This function returns false by default so it should be implemented for attributes that are modified by optimize!.

source
MathOptInterface.is_copyableFunction
is_copyable(::AnyAttribute)

Return a Bool indicating whether the value of the attribute may be copied during copy_to using set.

Important note when defining new attributes

By default is_copyable(attr) returns !is_set_by_optimize(attr). A specific method should be defined for attributes which are copied indirectly during copy_to. For instance, both is_copyable and is_set_by_optimize return false for the following attributes:

source
MathOptInterface.getFunction
MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64

Return the number of variables created by the bridge b in the model.

See also MOI.NumberOfConstraints.

Implementation notes

  • There is a default fallback, so you need only implement this if the bridge adds new variables.
source
MOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)

Return the list of variables created by the bridge b.

See also MOI.ListOfVariableIndices.

Implementation notes

  • There is a default fallback, so you need only implement this if the bridge adds new variables.
source
MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}

Return the number of constraints of the type F-in-S created by the bridge b.

See also MOI.NumberOfConstraints.

Implementation notes

  • There is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.
source
MOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}

Return a Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-in-S created by the bride b.

See also MOI.ListOfConstraintIndices.

Implementation notes

  • There is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.
source
function MOI.get(
+    model::MOI.ModelLike,
+    attr::MOI.AbstractConstraintAttribute,
+    bridge::AbstractBridge,
+)

Return the value of the attribute attr of the model model for the constraint bridged by bridge.

source
get(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute)

Return an attribute attr of the optimizer optimizer.

get(model::ModelLike, attr::AbstractModelAttribute)

Return an attribute attr of the model model.

get(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex)

If the attribute attr is set for the variable v in the model model, return its value, return nothing otherwise. If the attribute attr is not supported by model then an error should be thrown instead of returning nothing.

get(model::ModelLike, attr::AbstractVariableAttribute, v::Vector{VariableIndex})

Return a vector of attributes corresponding to each variable in the collection v in the model model.

get(model::ModelLike, attr::AbstractConstraintAttribute, c::ConstraintIndex)

If the attribute attr is set for the constraint c in the model model, return its value, return nothing otherwise. If the attribute attr is not supported by model then an error should be thrown instead of returning nothing.

get(
+    model::ModelLike,
+    attr::AbstractConstraintAttribute,
+    c::Vector{ConstraintIndex{F,S}},
+) where {F,S}

Return a vector of attributes corresponding to each constraint in the collection c in the model model.

get(model::ModelLike, ::Type{VariableIndex}, name::String)

If a variable with name name exists in the model model, return the corresponding index, otherwise return nothing. Errors if two variables have the same name.

get(
+    model::ModelLike,
+    ::Type{ConstraintIndex{F,S}},
+    name::String,
+) where {F,S}

If an F-in-S constraint with name name exists in the model model, return the corresponding index, otherwise return nothing. Errors if two constraints have the same name.

get(model::ModelLike, ::Type{ConstraintIndex}, name::String)

If any constraint with name name exists in the model model, return the corresponding index, otherwise return nothing. This version is available for convenience but may incur a performance penalty because it is not type stable. Errors if two constraints have the same name.

source
MathOptInterface.get!Function
get!(output, model::ModelLike, args...)

An in-place version of get.

The signature matches that of get except that the the result is placed in the vector output.

source
MathOptInterface.setFunction
function MOI.set(
+    model::MOI.ModelLike,
+    attr::MOI.AbstractConstraintAttribute,
+    bridge::AbstractBridge,
+    value,
+)

Set the value of the attribute attr of the model model for the constraint bridged by bridge.

source
set(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute, value)

Assign value to the attribute attr of the optimizer optimizer.

set(model::ModelLike, attr::AbstractModelAttribute, value)

Assign value to the attribute attr of the model model.

set(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex, value)

Assign value to the attribute attr of variable v in model model.

set(
+    model::ModelLike,
+    attr::AbstractVariableAttribute,
+    v::Vector{VariableIndex},
+    vector_of_values,
+)

Assign a value respectively to the attribute attr of each variable in the collection v in model model.

set(
+    model::ModelLike,
+    attr::AbstractConstraintAttribute,
+    c::ConstraintIndex,
+    value,
+)

Assign a value to the attribute attr of constraint c in model model.

set(
+    model::ModelLike,
+    attr::AbstractConstraintAttribute,
+    c::Vector{ConstraintIndex{F,S}},
+    vector_of_values,
+) where {F,S}

Assign a value respectively to the attribute attr of each constraint in the collection c in model model.

An UnsupportedAttribute error is thrown if model does not support the attribute attr (see supports) and a SetAttributeNotAllowed error is thrown if it supports the attribute attr but it cannot be set.

set(
+    model::ModelLike,
+    ::ConstraintSet,
+    c::ConstraintIndex{F,S},
+    set::S,
+) where {F,S}

Change the set of constraint c to the new set set which should be of the same type as the original set.

set(
+    model::ModelLike,
+    ::ConstraintFunction,
+    c::ConstraintIndex{F,S},
+    func::F,
+) where {F,S}

Replace the function in constraint c with func. F must match the original function type used to define the constraint.

Note

Setting the constraint function is not allowed if F is VariableIndex; a SettingVariableIndexNotAllowed error is thrown instead. This is because, it would require changing the index c since the index of VariableIndex constraints must be the same as the index of the variable.

source
MathOptInterface.supportsFunction
MOI.supports(
+    model::MOI.ModelLike,
+    attr::MOI.AbstractConstraintAttribute,
+    BT::Type{<:AbstractBridge},
+)

Return a Bool indicating whether BT supports setting attr to model.

source
supports(model::ModelLike, sub::AbstractSubmittable)::Bool

Return a Bool indicating whether model supports the submittable sub.

supports(model::ModelLike, attr::AbstractOptimizerAttribute)::Bool

Return a Bool indicating whether model supports the optimizer attribute attr. That is, it returns false if copy_to(model, src) shows a warning in case attr is in the ListOfOptimizerAttributesSet of src; see copy_to for more details on how unsupported optimizer attributes are handled in copy.

supports(model::ModelLike, attr::AbstractModelAttribute)::Bool

Return a Bool indicating whether model supports the model attribute attr. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfModelAttributesSet of src.

supports(
+    model::ModelLike,
+    attr::AbstractVariableAttribute,
+    ::Type{VariableIndex},
+)::Bool

Return a Bool indicating whether model supports the variable attribute attr. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfVariableAttributesSet of src.

supports(
+    model::ModelLike,
+    attr::AbstractConstraintAttribute,
+    ::Type{ConstraintIndex{F,S}},
+)::Bool where {F,S}

Return a Bool indicating whether model supports the constraint attribute attr applied to an F-in-S constraint. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfConstraintAttributesSet of src.

For all five methods, if the attribute is only not supported in specific circumstances, it should still return true.

Note that supports is only defined for attributes for which is_copyable returns true as other attributes do not appear in the list of attributes set obtained by ListOf...AttributesSet.

source
MathOptInterface.attribute_value_typeFunction
attribute_value_type(attr::AnyAttribute)

Given an attribute attr, return the type of value expected by get, or returned by set.

Notes

  • Only implement this if it make sense to do so. If un-implemented, the default is Any.
source

Model interface

MathOptInterface.is_emptyFunction
is_empty(model::ModelLike)

Returns false if the model has any model attribute set or has any variables or constraints.

Note that an empty model can have optimizer attributes set.

source
MathOptInterface.empty!Function
empty!(model::ModelLike)

Empty the model, that is, remove all variables, constraints and model attributes but not optimizer attributes.

source
MathOptInterface.write_to_fileFunction
write_to_file(model::ModelLike, filename::String)

Write the current model to the file at filename.

Supported file types depend on the model type.

source
MathOptInterface.read_from_fileFunction
read_from_file(model::ModelLike, filename::String)

Read the file filename into the model model. If model is non-empty, this may throw an error.

Supported file types depend on the model type.

Note

Once the contents of the file are loaded into the model, users can query the variables via get(model, ListOfVariableIndices()). However, some filetypes, such as LP files, do not maintain an explicit ordering of the variables. Therefore, the returned list may be in an arbitrary order.

To avoid depending on the order of the indices, look up each variable index by name using get(model, VariableIndex, "name").

source
MathOptInterface.copy_toFunction
copy_to(dest::ModelLike, src::ModelLike)::IndexMap

Copy the model from src into dest.

The target dest is emptied, and all previous indices to variables and constraints in dest are invalidated.

Returns an IndexMap object that translates variable and constraint indices from the src model to the corresponding indices in the dest model.

Notes

AbstractOptimizerAttributes are not copied to the dest model.

IndexMap

Implementations of copy_to must return an IndexMap. For technical reasons, this type is defined in the Utilities submodule as MOI.Utilities.IndexMap. However, since it is an integral part of the MOI API, we provide MOI.IndexMap as an alias.

Example

# Given empty `ModelLike` objects `src` and `dest`.
+
+x = add_variable(src)
+
+is_valid(src, x)   # true
+is_valid(dest, x)  # false (`dest` has no variables)
+
+index_map = copy_to(dest, src)
+is_valid(dest, x) # false (unless index_map[x] == x)
+is_valid(dest, index_map[x]) # true
source
MathOptInterface.IndexMapType
IndexMap()

The dictionary-like object returned by copy_to.

IndexMap

Implementations of copy_to must return an IndexMap. For technical reasons, the IndexMap type is defined in the Utilities submodule as MOI.Utilities.IndexMap. However, since it is an integral part of the MOI API, we provide this MOI.IndexMap as an alias.

source

Model attributes

MathOptInterface.NameType
Name()

A model attribute for the string identifying the model. It has a default value of "" if not set`.

source
MathOptInterface.ObjectiveFunctionType
ObjectiveFunction{F<:AbstractScalarFunction}()

A model attribute for the objective function which has a type F<:AbstractScalarFunction.

F should be guaranteed to be equivalent but not necessarily identical to the function type provided by the user.

Throws an InexactError if the objective function cannot be converted to F, e.g., the objective function is quadratic and F is ScalarAffineFunction{Float64} or it has non-integer coefficient and F is ScalarAffineFunction{Int}.

source
MathOptInterface.ObjectiveFunctionTypeType
ObjectiveFunctionType()

A model attribute for the type F of the objective function set using the ObjectiveFunction{F} attribute.

Examples

In the following code, attr should be equal to MOI.VariableIndex:

x = MOI.add_variable(model)
+MOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x)
+attr = MOI.get(model, MOI.ObjectiveFunctionType())
source
MathOptInterface.ObjectiveSenseType
ObjectiveSense()

A model attribute for the objective sense of the objective function, which must be an OptimizationSense: MIN_SENSE, MAX_SENSE, or FEASIBILITY_SENSE. The default is FEASIBILITY_SENSE.

Interaction with ObjectiveFunction

Setting the sense to FEASIBILITY_SENSE unsets the ObjectiveFunction attribute. That is, if you first set ObjectiveFunction and then set ObjectiveSense to be FEASIBILITY_SENSE, no objective function will be passed to the solver.

In addition, some reformulations of ObjectiveFunction via bridges rely on the value of ObjectiveSense. Therefore, you should set ObjectiveSense before setting ObjectiveFunction.

source
MathOptInterface.ListOfModelAttributesSetType
ListOfModelAttributesSet()

A model attribute for the Vector{AbstractModelAttribute} of all model attributes attr such that:

  1. is_copyable(attr) returns true, and
  2. the attribute was set to the model
source
MathOptInterface.ListOfVariableAttributesSetType
ListOfVariableAttributesSet()

A model attribute for the Vector{AbstractVariableAttribute} of all variable attributes attr such that 1) is_copyable(attr) returns true and 2) the attribute was set to variables.

source
MathOptInterface.UserDefinedFunctionType
UserDefinedFunction(name::Symbol, arity::Int) <: AbstractModelAttribute

Set this attribute to register a user-defined function by the name of name with arity arguments.

Once registered, name will appear in ListOfSupportedNonlinearOperators.

You cannot register multiple UserDefinedFunctions with the same name but different arity.

Value type

The value to be set is a tuple containing one, two, or three functions to evaluate the function, the first-order derivative, and the second-order derivative respectively. Both derivatives are optional, but if you pass the second-order derivative you must also pass the first-order derivative.

For univariate functions with arity == 1, the functions in the tuple must have the form:

  • f(x::T)::T: returns the value of the function at x
  • ∇f(x::T)::T: returns the first-order derivative of f with respect to x
  • ∇²f(x::T)::T: returns the second-order derivative of f with respect to x.

For multivariate functions with arity > 1, the functions in the tuple must have the form:

  • f(x::T...)::T: returns the value of the function at x
  • ∇f(g::AbstractVector{T}, x::T...)::Nothing: fills the components of g, with g[i] being the first-order partial derivative of f with respect to x[i]
  • ∇²f(H::AbstractMatrix{T}, x::T...)::Nothing: fills the non-zero components of H, with H[i, j] being the second-order partial derivative of f with respect to x[i] and then x[j]. H is initialized to the zero matrix, so you do not need to set any zero elements.

Examples

julia> import MathOptInterface as MOI
+
+julia> f(x, y) = x^2 + y^2
+f (generic function with 1 method)
+
+julia> function ∇f(g, x, y)
+           g .= 2 * x, 2 * y
+           return
+       end
+∇f (generic function with 1 method)
+
+julia> function ∇²f(H, x...)
+           H[1, 1] = H[2, 2] = 2.0
+           return
+       end
+∇²f (generic function with 1 method)
+
+julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
+MOIU.UniversalFallback{MOIU.Model{Float64}}
+fallback for MOIU.Model{Float64}
+
+julia> MOI.set(model, MOI.UserDefinedFunction(:f, 2), (f,))
+
+julia> MOI.set(model, MOI.UserDefinedFunction(:g, 2), (f, ∇f))
+
+julia> MOI.set(model, MOI.UserDefinedFunction(:h, 2), (f, ∇f, ∇²f))
+
+julia> x = MOI.add_variables(model, 2)
+2-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+
+julia> MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
+
+julia> obj_f = MOI.ScalarNonlinearFunction(:f, Any[x[1], x[2]])
+f(MOI.VariableIndex(1), MOI.VariableIndex(2))
+
+julia> MOI.set(model, MOI.ObjectiveFunction{typeof(obj_f)}(), obj_f)
+
+julia> print(model)
+Minimize ScalarNonlinearFunction:
+ f(v[1], v[2])
+
+Subject to:
+
source

Optimizer interface

MathOptInterface.AbstractOptimizerType
AbstractOptimizer <: ModelLike

Abstract supertype for objects representing an instance of an optimization problem tied to a particular solver. This is typically a solver's in-memory representation. In addition to ModelLike, AbstractOptimizer objects let you solve the model and query the solution.

source
MathOptInterface.OptimizerWithAttributesType
struct OptimizerWithAttributes
+    optimizer_constructor
+    params::Vector{Pair{AbstractOptimizerAttribute,<:Any}}
+end

Object grouping an optimizer constructor and a list of optimizer attributes. Instances are created with instantiate.

source
MathOptInterface.optimize!Method
optimize!(dest::AbstractOptimizer, src::ModelLike)::Tuple{IndexMap,Bool}

A "one-shot" call that copies the problem from src into dest and then uses dest to optimize the problem.

Returns a tuple of an IndexMap and a Bool copied.

  • The IndexMap object translates variable and constraint indices from the src model to the corresponding indices in the dest optimizer. See copy_to for details.
  • If copied == true, src was copied to dest and then cached, allowing incremental modification if supported by the solver.
  • If copied == false, a cache of the model was not kept in dest. Therefore, only the solution information (attributes for which is_set_by_optimize is true) is available to query.
Note

The main purpose of optimize! method with two arguments is for use in Utilities.CachingOptimizer.

Relationship to the single-argument optimize!

The default fallback of optimize!(dest::AbstractOptimizer, src::ModelLike) is

function optimize!(dest::AbstractOptimizer, src::ModelLike)
+    index_map = copy_to(dest, src)
+    optimize!(dest)
+    return index_map, true
+end

Therefore, subtypes of AbstractOptimizer should either implement this two-argument method, or implement both copy_to(::Optimizer, ::ModelLike) and optimize!(::Optimizer).

source
MathOptInterface.instantiateFunction
instantiate(
+    optimizer_constructor,
+    with_cache_type::Union{Nothing,Type} = nothing,
+    with_bridge_type::Union{Nothing,Type} = nothing,
+)

Create an instance of an optimizer by either:

  • calling optimizer_constructor.optimizer_constructor() and setting the parameters in optimizer_constructor.params if optimizer_constructor is a OptimizerWithAttributes
  • calling optimizer_constructor() if optimizer_constructor is callable.

withcachetype

If with_cache_type is not nothing, then the optimizer is wrapped in a Utilities.CachingOptimizer to store a cache of the model. This is most useful if the optimizer you are constructing does not support the incremental interface (see supports_incremental_interface).

withbridgetype

If with_bridge_type is not nothing, the optimizer is wrapped in a Bridges.full_bridge_optimizer, enabling all the bridges defined in the MOI.Bridges submodule with coefficient type with_bridge_type.

In addition, if the optimizer created by optimizer_constructor does not support the incremental interface (see supports_incremental_interface), then, irrespective of with_cache_type, the optimizer is wrapped in a Utilities.CachingOptimizer to store a cache of the bridged model.

If with_cache_type and with_bridge_type are both not nothing, then they must be the same type.

source
MathOptInterface.default_cacheFunction
default_cache(optimizer::ModelLike, ::Type{T}) where {T}

Return a new instance of the default model type to be used as cache for optimizer in a Utilities.CachingOptimizer for holding constraints of coefficient type T. By default, this returns Utilities.UniversalFallback(Utilities.Model{T}()). If copying from a instance of a given model type is faster for optimizer then a new method returning an instance of this model type should be defined.

source

Optimizer attributes

MathOptInterface.SolverVersionType
SolverVersion()

An optimizer attribute for the string identifying the version of the solver.

Note

For solvers supporting semantic versioning, the SolverVersion should be a string of the form "vMAJOR.MINOR.PATCH", so that it can be converted to a Julia VersionNumber (e.g., `VersionNumber("v1.2.3")).

We do not require Semantic Versioning because some solvers use alternate versioning systems. For example, CPLEX uses Calendar Versioning, so SolverVersion will return a string like "202001".

source
MathOptInterface.SilentType
Silent()

An optimizer attribute for silencing the output of an optimizer. When set to true, it takes precedence over any other attribute controlling verbosity and requires the solver to produce no output. The default value is false which has no effect. In this case the verbosity is controlled by other attributes.

Note

Every optimizer should have verbosity on by default. For instance, if a solver has a solver-specific log level attribute, the MOI implementation should set it to 1 by default. If the user sets Silent to true, then the log level should be set to 0, even if the user specifically sets a value of log level. If the value of Silent is false then the log level set to the solver is the value given by the user for this solver-specific parameter or 1 if none is given.

source
MathOptInterface.TimeLimitSecType
TimeLimitSec()

An optimizer attribute for setting a time limit (in seconnds) for an optimization. When set to nothing, it deactivates the solver time limit. The default value is nothing.

source
MathOptInterface.ObjectiveLimitType
ObjectiveLimit()

An optimizer attribute for setting a limit on the objective value.

The provided limit must be a Union{Real,Nothing}.

When set to nothing, the limit reverts to the solver's default.

The default value is nothing.

The solver may stop when the ObjectiveValue is better (lower for minimization, higher for maximization) than the ObjectiveLimit. If stopped, the TerminationStatus should be OBJECTIVE_LIMIT.

source
MathOptInterface.NumberOfThreadsType
NumberOfThreads()

An optimizer attribute for setting the number of threads used for an optimization. When set to nothing uses solver default. Values are positive integers. The default value is nothing.

source
MathOptInterface.AbsoluteGapToleranceType
AbsoluteGapTolerance()

An optimizer attribute for setting the absolute gap tolerance for an optimization. This is an optimizer attribute, and should be set before calling optimize!. When set to nothing (if supported), uses solver default.

To set a relative gap tolerance, see RelativeGapTolerance.

Warning

The mathematical definition of "absolute gap", and its treatment during the optimization, are solver-dependent. However, assuming no other limit nor issue is encountered during the optimization, most solvers that implement this attribute will stop once $|f - b| ≤ g_{abs}$, where $b$ is the best bound, $f$ is the best feasible objective value, and $g_{abs}$ is the absolute gap.

source
MathOptInterface.RelativeGapToleranceType
RelativeGapTolerance()

An optimizer attribute for setting the relative gap tolerance for an optimization. This is an optimizer attribute, and should be set before calling optimize!. When set to nothing (if supported), uses solver default.

If you are looking for the relative gap of the current best solution, see RelativeGap. If no limit nor issue is encountered during the optimization, the value of RelativeGap should be at most as large as RelativeGapTolerance.

# Before optimizing: set relative gap tolerance
+# set 0.1% relative gap tolerance
+MOI.set(model, MOI.RelativeGapTolerance(), 1e-3)
+MOI.optimize!(model)
+
+# After optimizing (assuming all went well)
+# The relative gap tolerance has not changed...
+MOI.get(model, MOI.RelativeGapTolerance())  # returns 1e-3
+# ... and the relative gap of the obtained solution is smaller or equal to the
+# tolerance
+MOI.get(model, MOI.RelativeGap())  # should return something ≤ 1e-3
Warning

The mathematical definition of "relative gap", and its allowed range, are solver-dependent. Typically, solvers expect a value between 0.0 and 1.0.

source

List of attributes useful for optimizers

MathOptInterface.TerminationStatusCodeType
TerminationStatusCode

An Enum of possible values for the TerminationStatus attribute. This attribute is meant to explain the reason why the optimizer stopped executing in the most recent call to optimize!.

Values

Possible values are:

  • OPTIMIZE_NOT_CALLED: The algorithm has not started.
  • OPTIMAL: The algorithm found a globally optimal solution.
  • INFEASIBLE: The algorithm concluded that no feasible solution exists.
  • DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.
  • LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.
  • LOCALLY_INFEASIBLE: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.
  • INFEASIBLE_OR_UNBOUNDED: The algorithm stopped because it decided that the problem is infeasible or unbounded; this occasionally happens during MIP presolve.
  • ALMOST_OPTIMAL: The algorithm found a globally optimal solution to relaxed tolerances.
  • ALMOST_INFEASIBLE: The algorithm concluded that no feasible solution exists within relaxed tolerances.
  • ALMOST_DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem within relaxed tolerances.
  • ALMOST_LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, or could not find directions for improvement within relaxed tolerances.
  • ITERATION_LIMIT: An iterative algorithm stopped after conducting the maximum number of iterations.
  • TIME_LIMIT: The algorithm stopped after a user-specified computation time.
  • NODE_LIMIT: A branch-and-bound algorithm stopped because it explored a maximum number of nodes in the branch-and-bound tree.
  • SOLUTION_LIMIT: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.
  • MEMORY_LIMIT: The algorithm stopped because it ran out of memory.
  • OBJECTIVE_LIMIT: The algorithm stopped because it found a solution better than a minimum limit set by the user.
  • NORM_LIMIT: The algorithm stopped because the norm of an iterate became too large.
  • OTHER_LIMIT: The algorithm stopped due to a limit not covered by one of the _LIMIT_ statuses above.
  • SLOW_PROGRESS: The algorithm stopped because it was unable to continue making progress towards the solution.
  • NUMERICAL_ERROR: The algorithm stopped because it encountered unrecoverable numerical error.
  • INVALID_MODEL: The algorithm stopped because the model is invalid.
  • INVALID_OPTION: The algorithm stopped because it was provided an invalid option.
  • INTERRUPTED: The algorithm stopped because of an interrupt signal.
  • OTHER_ERROR: The algorithm stopped because of an error not covered by one of the statuses defined above.
source
MathOptInterface.DUAL_INFEASIBLEConstant
DUAL_INFEASIBLE::TerminationStatusCode

An instance of the TerminationStatusCode enum.

DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.

source
MathOptInterface.LOCALLY_SOLVEDConstant
LOCALLY_SOLVED::TerminationStatusCode

An instance of the TerminationStatusCode enum.

LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.

source
MathOptInterface.LOCALLY_INFEASIBLEConstant
LOCALLY_INFEASIBLE::TerminationStatusCode

An instance of the TerminationStatusCode enum.

LOCALLY_INFEASIBLE: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.

source
MathOptInterface.SOLUTION_LIMITConstant
SOLUTION_LIMIT::TerminationStatusCode

An instance of the TerminationStatusCode enum.

SOLUTION_LIMIT: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.

source
MathOptInterface.DualStatusType
DualStatus(result_index::Int = 1)

A model attribute for the ResultStatusCode of the dual result result_index. If result_index is omitted, it defaults to 1.

See ResultCount for information on how the results are ordered.

If result_index is larger than the value of ResultCount then NO_SOLUTION is returned.

source
MathOptInterface.ResultCountType
ResultCount()

A model attribute for the number of results available.

Order of solutions

A number of attributes contain an index, result_index, which is used to refer to one of the available results. Thus, result_index must be an integer between 1 and the number of available results.

As a general rule, the first result (result_index=1) is the most important result (e.g., an optimal solution or an infeasibility certificate). Other results will typically be alternate solutions that the solver found during the search for the first result.

If a (local) optimal solution is available, i.e., TerminationStatus is OPTIMAL or LOCALLY_SOLVED, the first result must correspond to the (locally) optimal solution. Other results may be alternative optimal solutions, or they may be other suboptimal solutions; use ObjectiveValue to distingiush between them.

If a primal or dual infeasibility certificate is available, i.e., TerminationStatus is INFEASIBLE or DUAL_INFEASIBLE and the corresponding PrimalStatus or DualStatus is INFEASIBILITY_CERTIFICATE, then the first result must be a certificate. Other results may be alternate certificates, or infeasible points.

source
MathOptInterface.ObjectiveValueType
ObjectiveValue(result_index::Int = 1)

A model attribute for the objective value of the primal solution result_index.

If the solver does not have a primal value for the objective because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ObjectiveValue attribute.

See ResultCount for information on how the results are ordered.

source
MathOptInterface.DualObjectiveValueType
DualObjectiveValue(result_index::Int = 1)

A model attribute for the value of the objective function of the dual problem for the result_indexth dual result.

If the solver does not have a dual value for the objective because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check DualStatus before accessing the DualObjectiveValue attribute.

See ResultCount for information on how the results are ordered.

source
MathOptInterface.RelativeGapType
RelativeGap()

A model attribute for the final relative optimality gap.

Warning

The definition of this gap is solver-dependent. However, most solvers implementing this attribute define the relative gap as some variation of $\frac{|b-f|}{|f|}$, where $b$ is the best bound and $f$ is the best feasible objective value.

source
MathOptInterface.SimplexIterationsType
SimplexIterations()

A model attribute for the cumulative number of simplex iterations during the optimization process.

For a mixed-integer program (MIP), the return value is the total simplex iterations for all nodes.

source
MathOptInterface.NodeCountType
NodeCount()

A model attribute for the total number of branch-and-bound nodes explored while solving a mixed-integer program (MIP).

source

ResultStatusCode

MathOptInterface.ResultStatusCodeType
ResultStatusCode

An Enum of possible values for the PrimalStatus and DualStatus attributes.

The values indicate how to interpret the result vector.

Values

Possible values are:

  • NO_SOLUTION: the result vector is empty.
  • FEASIBLE_POINT: the result vector is a feasible point.
  • NEARLY_FEASIBLE_POINT: the result vector is feasible if some constraint tolerances are relaxed.
  • INFEASIBLE_POINT: the result vector is an infeasible point.
  • INFEASIBILITY_CERTIFICATE: the result vector is an infeasibility certificate. If the PrimalStatus is INFEASIBILITY_CERTIFICATE, then the primal result vector is a certificate of dual infeasibility. If the DualStatus is INFEASIBILITY_CERTIFICATE, then the dual result vector is a proof of primal infeasibility.
  • NEARLY_INFEASIBILITY_CERTIFICATE: the result satisfies a relaxed criterion for a certificate of infeasibility.
  • REDUCTION_CERTIFICATE: the result vector is an ill-posed certificate; see this article for details. If the PrimalStatus is REDUCTION_CERTIFICATE, then the primal result vector is a proof that the dual problem is ill-posed. If the DualStatus is REDUCTION_CERTIFICATE, then the dual result vector is a proof that the primal is ill-posed.
  • NEARLY_REDUCTION_CERTIFICATE: the result satisfies a relaxed criterion for an ill-posed certificate.
  • UNKNOWN_RESULT_STATUS: the result vector contains a solution with an unknown interpretation.
  • OTHER_RESULT_STATUS: the result vector contains a solution with an interpretation not covered by one of the statuses defined above
source
MathOptInterface.INFEASIBILITY_CERTIFICATEConstant
INFEASIBILITY_CERTIFICATE::ResultStatusCode

An instance of the ResultStatusCode enum.

INFEASIBILITY_CERTIFICATE: the result vector is an infeasibility certificate. If the PrimalStatus is INFEASIBILITY_CERTIFICATE, then the primal result vector is a certificate of dual infeasibility. If the DualStatus is INFEASIBILITY_CERTIFICATE, then the dual result vector is a proof of primal infeasibility.

source
MathOptInterface.REDUCTION_CERTIFICATEConstant
REDUCTION_CERTIFICATE::ResultStatusCode

An instance of the ResultStatusCode enum.

REDUCTION_CERTIFICATE: the result vector is an ill-posed certificate; see this article for details. If the PrimalStatus is REDUCTION_CERTIFICATE, then the primal result vector is a proof that the dual problem is ill-posed. If the DualStatus is REDUCTION_CERTIFICATE, then the dual result vector is a proof that the primal is ill-posed.

source

Conflict Status

MathOptInterface.compute_conflict!Function
compute_conflict!(optimizer::AbstractOptimizer)

Computes a minimal subset of constraints such that the model with the other constraint removed is still infeasible.

Some solvers call a set of conflicting constraints an Irreducible Inconsistent Subsystem (IIS).

See also ConflictStatus and ConstraintConflictStatus.

Note

If the model is modified after a call to compute_conflict!, the implementor is not obliged to purge the conflict. Any calls to the above attributes may return values for the original conflict without a warning. Similarly, when modifying the model, the conflict can be discarded.

source
MathOptInterface.ConflictStatusCodeType
ConflictStatusCode

An Enum of possible values for the ConflictStatus attribute. This attribute is meant to explain the reason why the conflict finder stopped executing in the most recent call to compute_conflict!.

Possible values are:

  • COMPUTE_CONFLICT_NOT_CALLED: the function compute_conflict! has not yet been called
  • NO_CONFLICT_EXISTS: there is no conflict because the problem is feasible
  • NO_CONFLICT_FOUND: the solver could not find a conflict
  • CONFLICT_FOUND: at least one conflict could be found
source
MathOptInterface.ConflictParticipationStatusCodeType
ConflictParticipationStatusCode

An Enum of possible values for the ConstraintConflictStatus attribute. This attribute is meant to indicate whether a given constraint participates or not in the last computed conflict.

Values

Possible values are:

  • NOT_IN_CONFLICT: the constraint does not participate in the conflict
  • IN_CONFLICT: the constraint participates in the conflict
  • MAYBE_IN_CONFLICT: the constraint may participate in the conflict, the solver was not able to prove that the constraint can be excluded from the conflict
source
diff --git a/previews/PR2274/reference/modification/index.html b/previews/PR2274/reference/modification/index.html new file mode 100644 index 0000000000..bc314c812c --- /dev/null +++ b/previews/PR2274/reference/modification/index.html @@ -0,0 +1,27 @@ + +Modifications · MathOptInterface

Modifications

MathOptInterface.modifyFunction

Constraint Function

modify(model::ModelLike, ci::ConstraintIndex, change::AbstractFunctionModification)

Apply the modification specified by change to the function of constraint ci.

An ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by the model model.

Examples

modify(model, ci, ScalarConstantChange(10.0))

Objective Function

modify(model::ModelLike, ::ObjectiveFunction, change::AbstractFunctionModification)

Apply the modification specified by change to the objective function of model. To change the function completely, call set instead.

An ModifyObjectiveNotAllowed error is thrown if modifying objectives is not supported by the model model.

Examples

modify(model, ObjectiveFunction{ScalarAffineFunction{Float64}}(), ScalarConstantChange(10.0))

Multiple modifications in Constraint Functions

modify(
+    model::ModelLike,
+    cis::AbstractVector{<:ConstraintIndex},
+    changes::AbstractVector{<:AbstractFunctionModification},
+)

Apply multiple modifications specified by changes to the functions of constraints cis.

A ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by model.

Examples

modify(
+    model,
+    [ci, ci],
+    [
+        ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),
+        ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),
+    ],
+)

Multiple modifications in the Objective Function

modify(
+    model::ModelLike,
+    attr::ObjectiveFunction,
+    changes::AbstractVector{<:AbstractFunctionModification},
+)

Apply multiple modifications specified by changes to the functions of constraints cis.

A ModifyObjectiveNotAllowed error is thrown if modifying objective coefficients is not supported by model.

Examples

modify(
+    model,
+    ObjectiveFunction{ScalarAffineFunction{Float64}}(),
+    [
+        ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),
+        ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),
+    ],
+)
source
MathOptInterface.AbstractFunctionModificationType
AbstractFunctionModification

An abstract supertype for structs which specify partial modifications to functions, to be used for making small modifications instead of replacing the functions entirely.

source
diff --git a/previews/PR2274/reference/nonlinear/index.html b/previews/PR2274/reference/nonlinear/index.html new file mode 100644 index 0000000000..7e17252da7 --- /dev/null +++ b/previews/PR2274/reference/nonlinear/index.html @@ -0,0 +1,78 @@ + +Nonlinear programming · MathOptInterface

Nonlinear programming

Types

MathOptInterface.NLPBoundsPairType
NLPBoundsPair(lower::Float64, upper::Float64)

A struct holding a pair of lower and upper bounds.

-Inf and Inf can be used to indicate no lower or upper bound, respectively.

source
MathOptInterface.NLPBlockDataType
struct NLPBlockData
+    constraint_bounds::Vector{NLPBoundsPair}
+    evaluator::AbstractNLPEvaluator
+    has_objective::Bool
+end

A struct encoding a set of nonlinear constraints of the form $lb \le g(x) \le ub$ and, if has_objective == true, a nonlinear objective function $f(x)$.

Nonlinear objectives override any objective set by using the ObjectiveFunction attribute.

The evaluator is a callback object that is used to query function values, derivatives, and expression graphs. If has_objective == false, then it is an error to query properties of the objective function, and in Hessian-of-the-Lagrangian queries, σ must be set to zero.

Note

Throughout the evaluator, all variables are ordered according to ListOfVariableIndices. Hence, MOI copies of nonlinear problems must not re-order variables.

source

Attributes

Functions

MathOptInterface.initializeFunction
initialize(
+    d::AbstractNLPEvaluator,
+    requested_features::Vector{Symbol},
+)::Nothing

Initialize d with the set of features in requested_features. Check features_available before calling initialize to see what features are supported by d.

Warning

This method must be called before any other methods.

Features

The following features are defined:

In all cases, including when requested_features is empty, eval_objective and eval_constraint are supported.

Examples

MOI.initialize(d, Symbol[])
+MOI.initialize(d, [:ExprGraph])
+MOI.initialize(d, MOI.features_available(d))
source
MathOptInterface.eval_constraintFunction
eval_constraint(d::AbstractNLPEvaluator,
+    g::AbstractVector{T},
+    x::AbstractVector{T},
+)::Nothing where {T}

Given a set of vector-valued constraints $l \le g(x) \le u$, evaluate the constraint function $g(x)$, storing the result in the vector g.

Implementation notes

When implementing this method, you must not assume that g is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_objective_gradientFunction
eval_objective_gradient(
+    d::AbstractNLPEvaluator,
+    grad::AbstractVector{T},
+    x::AbstractVector{T},
+)::Nothing where {T}

Evaluate the gradient of the objective function $grad = \nabla f(x)$ as a dense vector, storing the result in the vector grad.

Implementation notes

When implementing this method, you must not assume that grad is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.jacobian_structureFunction
jacobian_structure(d::AbstractNLPEvaluator)::Vector{Tuple{Int64,Int64}}

Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Jacobian matrix: $J_g(x) = \left[ \begin{array}{c} \nabla g_1(x) \\ \nabla g_2(x) \\ \vdots \\ \nabla g_m(x) \end{array}\right],$ where $g_i$ is the $i\text{th}$ component of the nonlinear constraints $g(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.eval_constraint_gradientFunction
eval_constraint_gradient(
+    d::AbstractNLPEvaluator,
+    ∇g::AbstractVector{T},
+    x::AbstractVector{T},
+    i::Int,
+)::Nothing where {T}

Evaluate the gradient of constraint i, $\nabla g_i(x)$, and store the non-zero values in ∇g, corresponding to the structure returned by constraint_gradient_structure.

Implementation notes

When implementing this method, you must not assume that ∇g is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.constraint_gradient_structureFunction
constraint_gradient_structure(d::AbstractNLPEvaluator, i::Int)::Vector{Int64}

Returns a vector of indices, where each element indicates the position of a structurally nonzero element in the gradient of constraint $\nabla g_i(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.eval_constraint_jacobianFunction
eval_constraint_jacobian(d::AbstractNLPEvaluator,
+    J::AbstractVector{T},
+    x::AbstractVector{T},
+)::Nothing where {T}

Evaluates the sparse Jacobian matrix $J_g(x) = \left[ \begin{array}{c} \nabla g_1(x) \\ \nabla g_2(x) \\ \vdots \\ \nabla g_m(x) \end{array}\right]$.

The result is stored in the vector J in the same order as the indices returned by jacobian_structure.

Implementation notes

When implementing this method, you must not assume that J is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_constraint_jacobian_productFunction
eval_constraint_jacobian_product(
+    d::AbstractNLPEvaluator,
+    y::AbstractVector{T},
+    x::AbstractVector{T},
+    w::AbstractVector{T},
+)::Nothing where {T}

Computes the Jacobian-vector product $y = J_g(x)w$, storing the result in the vector y.

The vectors have dimensions such that length(w) == length(x), and length(y) is the number of nonlinear constraints.

Implementation notes

When implementing this method, you must not assume that y is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_constraint_jacobian_transpose_productFunction
eval_constraint_jacobian_transpose_product(
+    d::AbstractNLPEvaluator,
+    y::AbstractVector{T},
+    x::AbstractVector{T},
+    w::AbstractVector{T},
+)::Nothing where {T}

Computes the Jacobian-transpose-vector product $y = J_g(x)^Tw$, storing the result in the vector y.

The vectors have dimensions such that length(y) == length(x), and length(w) is the number of nonlinear constraints.

Implementation notes

When implementing this method, you must not assume that y is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.hessian_lagrangian_structureFunction
hessian_lagrangian_structure(
+    d::AbstractNLPEvaluator,
+)::Vector{Tuple{Int64,Int64}}

Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian-of-the-Lagrangian matrix: $\nabla^2 f(x) + \sum_{i=1}^m \nabla^2 g_i(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

Any mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.hessian_objective_structureFunction
hessian_objective_structure(
+    d::AbstractNLPEvaluator,
+)::Vector{Tuple{Int64,Int64}}

Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian matrix: $\nabla^2 f(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

Any mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.hessian_constraint_structureFunction
hessian_constraint_structure(
+    d::AbstractNLPEvaluator,
+    i::Int64,
+)::Vector{Tuple{Int64,Int64}}

Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian matrix: $\nabla^2 g_i(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

Any mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.eval_hessian_objectiveFunction
eval_hessian_objective(
+    d::AbstractNLPEvaluator,
+    H::AbstractVector{T},
+    x::AbstractVector{T},
+)::Nothing where {T}

This function computes the sparse Hessian matrix: $\nabla^2 f(x)$, storing the result in the vector H in the same order as the indices returned by hessian_objective_structure.

Implementation notes

When implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_hessian_constraintFunction
eval_hessian_constraint(
+    d::AbstractNLPEvaluator,
+    H::AbstractVector{T},
+    x::AbstractVector{T},
+    i::Int64,
+)::Nothing where {T}

This function computes the sparse Hessian matrix: $\nabla^2 g_i(x)$, storing the result in the vector H in the same order as the indices returned by hessian_constraint_structure.

Implementation notes

When implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_hessian_lagrangianFunction
eval_hessian_lagrangian(
+    d::AbstractNLPEvaluator,
+    H::AbstractVector{T},
+    x::AbstractVector{T},
+    σ::T,
+    μ::AbstractVector{T},
+)::Nothing where {T}

Given scalar weight σ and vector of constraint weights μ, this function computes the sparse Hessian-of-the-Lagrangian matrix: $\sigma\nabla^2 f(x) + \sum_{i=1}^m \mu_i \nabla^2 g_i(x)$, storing the result in the vector H in the same order as the indices returned by hessian_lagrangian_structure.

Implementation notes

When implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_hessian_lagrangian_productFunction
eval_hessian_lagrangian_product(
+    d::AbstractNLPEvaluator,
+    h::AbstractVector{T},
+    x::AbstractVector{T},
+    v::AbstractVector{T},
+    σ::T,
+    μ::AbstractVector{T},
+)::Nothing where {T}

Given scalar weight σ and vector of constraint weights μ, computes the Hessian-of-the-Lagrangian-vector product $h = \left(\sigma\nabla^2 f(x) + \sum_{i=1}^m \mu_i \nabla^2 g_i(x)\right)v$, storing the result in the vector h.

The vectors have dimensions such that length(h) == length(x) == length(v).

Implementation notes

When implementing this method, you must not assume that h is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.objective_exprFunction
objective_expr(d::AbstractNLPEvaluator)::Expr

Returns a Julia Expr object representing the expression graph of the objective function.

Format

The expression has a number of limitations, compared with arbitrary Julia expressions:

  • All sums and products are flattened out as simple Expr(:+, ...) and Expr(:*, ...) objects.
  • All decision variables must be of the form Expr(:ref, :x, MOI.VariableIndex(i)), where i is the $i$th variable in ListOfVariableIndices.
  • There are currently no restrictions on recognized functions; typically these will be built-in Julia functions like ^, exp, log, cos, tan, sqrt, etc., but modeling interfaces may choose to extend these basic functions, or error if they encounter unsupported functions.

Examples

The expression $x_1+\sin(x_2/\exp(x_3))$ is represented as

:(x[MOI.VariableIndex(1)] + sin(x[MOI.VariableIndex(2)] / exp(x[MOI.VariableIndex[3]])))

or equivalently

Expr(
+    :call,
+    :+,
+    Expr(:ref, :x, MOI.VariableIndex(1)),
+    Expr(
+        :call,
+        :/,
+        Expr(:call, :sin, Expr(:ref, :x, MOI.VariableIndex(2))),
+        Expr(:call, :exp, Expr(:ref, :x, MOI.VariableIndex(3))),
+    ),
+)
source
MathOptInterface.constraint_exprFunction
constraint_expr(d::AbstractNLPEvaluator, i::Integer)::Expr

Returns a Julia Expr object representing the expression graph for the $i\text{th}$ nonlinear constraint.

Format

The format is the same as objective_expr, with an additional comparison operator indicating the sense of and bounds on the constraint.

For single-sided comparisons, the body of the constraint must be on the left-hand side, and the right-hand side must be a constant.

For double-sided comparisons (that is, $l \le f(x) \le u$), the body of the constraint must be in the middle, and the left- and right-hand sides must be constants.

The bounds on the constraints must match the NLPBoundsPairs passed to NLPBlockData.

Examples

:(x[MOI.VariableIndex(1)]^2 <= 1.0)
+:(x[MOI.VariableIndex(1)]^2 >= 2.0)
+:(x[MOI.VariableIndex(1)]^2 == 3.0)
+:(4.0 <= x[MOI.VariableIndex(1)]^2 <= 5.0)
source
diff --git a/previews/PR2274/reference/standard_form/index.html b/previews/PR2274/reference/standard_form/index.html new file mode 100644 index 0000000000..91728301b5 --- /dev/null +++ b/previews/PR2274/reference/standard_form/index.html @@ -0,0 +1,989 @@ + +Standard form · MathOptInterface

Standard form

Functions

MathOptInterface.AbstractFunctionType
AbstractFunction

Abstract supertype for function objects.

Required methods

All functions must implement:

Abstract subtypes of AbstractFunction may require additional methods to be implemented.

source
MathOptInterface.constantFunction
constant(f::AbstractFunction[, ::Type{T}]) where {T}

Returns the constant term of a scalar-valued function, or the constant vector of a vector-valued function.

If f is untyped and T is provided, returns zero(T).

source
constant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})

Returns the constant term of the set set.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.constant(MOI.GreaterThan(1.0))
+1.0
+
+julia> MOI.constant(MOI.LessThan(2.5))
+2.5
+
+julia> MOI.constant(MOI.EqualTo(3))
+3
+
+julia> MOI.constant(MOI.Parameter(4.5))
+4.5
source

Scalar functions

MathOptInterface.VariableIndexType
VariableIndex

A type-safe wrapper for Int64 for use in referencing variables in a model. To allow for deletion, indices need not be consecutive.

source
MathOptInterface.ScalarAffineTermType
ScalarAffineTerm{T}(coefficient::T, variable::VariableIndex) where {T}

Represents the scalar-valued term coefficient * variable.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> MOI.ScalarAffineTerm(2.0, x)
+MathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))
source
MathOptInterface.ScalarAffineFunctionType
ScalarAffineFunction{T}(terms::ScalarAffineTerm{T}, constant::T) where {T}

Represents the scalar-valued affine function $a^\top x + b$, where:

  • $a^\top x$ is represented by the vector of ScalarAffineTerms
  • $b$ is a scalar constant::T

Duplicates

Duplicate variable indices in terms are accepted, and the corresponding coefficients are summed together.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> terms = [MOI.ScalarAffineTerm(2.0, x), MOI.ScalarAffineTerm(3.0, x)]
+2-element Vector{MathOptInterface.ScalarAffineTerm{Float64}}:
+ MathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))
+ MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1))
+
+julia> f = MOI.ScalarAffineFunction(terms, 4.0)
+4.0 + 2.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)
source
MathOptInterface.ScalarQuadraticTermType
ScalarQuadraticTerm{T}(
+    coefficient::T,
+    variable_1::VariableIndex,
+    variable_2::VariableIndex,
+) where {T}

Represents the scalar-valued term $c x_i x_j$ where $c$ is coefficient, $x_i$ is variable_1 and $x_j$ is variable_2.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> MOI.ScalarQuadraticTerm(2.0, x, x)
+MathOptInterface.ScalarQuadraticTerm{Float64}(2.0, MOI.VariableIndex(1), MOI.VariableIndex(1))
source
MathOptInterface.ScalarQuadraticFunctionType
ScalarQuadraticFunction{T}(
+    quadratic_terms::Vector{ScalarQuadraticTerm{T}},
+    affine_terms::Vector{ScalarAffineTerm{T}},
+    constant::T,
+) wher {T}

The scalar-valued quadratic function $\frac{1}{2}x^\top Q x + a^\top x + b$, where:

Duplicates

Duplicate indices in quadratic_terms or affine_terms are accepted, and the corresponding coefficients are summed together.

In quadratic_terms, "mirrored" indices, (q, r) and (r, q) where r and q are VariableIndexes, are considered duplicates; only one needs to be specified.

The 0.5 factor

Coupled with the interpretation of mirrored indices, the 0.5 factor in front of the $Q$ matrix is a common source of bugs.

As a rule, to represent $a * x^2 + b * x * y$:

  • The coefficient $a$ in front of squared variables (diagonal elements in $Q$) must be doubled when creating a ScalarQuadraticTerm
  • The coefficient $b$ in front of off-diagonal elements in $Q$ should be left as $b$, be cause the mirrored index $b * y * x$ will be implicitly added.

Example

To represent the function $f(x, y) = 2 * x^2 + 3 * x * y + 4 * x + 5$, do:

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> y = MOI.VariableIndex(2);
+
+julia> constant = 5.0;
+
+julia> affine_terms = [MOI.ScalarAffineTerm(4.0, x)];
+
+julia> quadratic_terms = [
+           MOI.ScalarQuadraticTerm(4.0, x, x),  # Note the changed coefficient
+           MOI.ScalarQuadraticTerm(3.0, x, y),
+       ]
+2-element Vector{MathOptInterface.ScalarQuadraticTerm{Float64}}:
+ MathOptInterface.ScalarQuadraticTerm{Float64}(4.0, MOI.VariableIndex(1), MOI.VariableIndex(1))
+ MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(2))
+
+julia> f = MOI.ScalarQuadraticFunction(quadratic_terms, affine_terms, constant)
+5.0 + 4.0 MOI.VariableIndex(1) + 2.0 MOI.VariableIndex(1)² + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)
source
MathOptInterface.ScalarNonlinearFunctionType
ScalarNonlinearFunction(head::Symbol, args::Vector{Any})

The scalar-valued nonlinear function head(args...), represented as a symbolic expression tree, with the call operator head and ordered arguments in args.

head

The head::Symbol must be an operator supported by the model.

The default list of supported univariate operators is given by:

and the default list of supported multivariate operators is given by:

Additional operators can be registered by setting a UserDefinedFunction attribute.

See the full list of operators supported by a ModelLike by querying ListOfSupportedNonlinearOperators.

args

The vector args contains the arguments to the nonlinear function. If the operator is univariate, it must contain one element. Otherwise, it may contain multiple elements.

Each element must be one of the following:

Unsupported operators

If the optimizer does not support head, an UnsupportedNonlinearOperator error will be thrown.

There is no guarantee about when this error will be thrown; it may be thrown when the function is first added to the model, or it may be thrown when optimize! is called.

Example

To represent the function $f(x) = sin(x)^2$, do:

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> MOI.ScalarNonlinearFunction(
+           :^,
+           Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2],
+       )
+^(sin(MOI.VariableIndex(1)), (2))
source

Vector functions

MathOptInterface.VectorOfVariablesType
VectorOfVariables(variables::Vector{VariableIndex}) <: AbstractVectorFunction

The vector-valued function f(x) = variables, where variables is a subset of VariableIndexes in the model.

The list of variables may contain duplicates.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex.(1:2)
+2-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+
+julia> f = MOI.VectorOfVariables([x[1], x[2], x[1]])
+┌                    ┐
+│MOI.VariableIndex(1)│
+│MOI.VariableIndex(2)│
+│MOI.VariableIndex(1)│
+└                    ┘
+
+julia> MOI.output_dimension(f)
+3
source
MathOptInterface.VectorAffineTermType
VectorAffineTerm{T}(
+    output_index::Int64,
+    scalar_term::ScalarAffineTerm{T},
+) where {T}

A VectorAffineTerm is a scalar_term that appears in the output_index row of the vector-valued VectorAffineFunction or VectorQuadraticFunction.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x))
+MathOptInterface.VectorAffineTerm{Float64}(2, MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1)))
source
MathOptInterface.VectorAffineFunctionType
VectorAffineFunction{T}(
+    terms::Vector{VectorAffineTerm{T}},
+    constants::Vector{T},
+) where {T}

The vector-valued affine function $A x + b$, where:

  • $A x$ is the sparse matrix given by the vector of VectorAffineTerms
  • $b$ is the vector constants

Duplicates

Duplicate indices in the $A$ are accepted, and the corresponding coefficients are summed together.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> terms = [
+           MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),
+           MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),
+       ];
+
+julia> f = MOI.VectorAffineFunction(terms, [4.0, 5.0])
+┌                              ┐
+│4.0 + 2.0 MOI.VariableIndex(1)│
+│5.0 + 3.0 MOI.VariableIndex(1)│
+└                              ┘
+
+julia> MOI.output_dimension(f)
+2
source
MathOptInterface.VectorQuadraticTermType
VectorQuadraticTerm{T}(
+    output_index::Int64,
+    scalar_term::ScalarQuadraticTerm{T},
+) where {T}

A VectorQuadraticTerm is a ScalarQuadraticTerm scalar_term that appears in the output_index row of the vector-valued VectorQuadraticFunction.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, x))
+MathOptInterface.VectorQuadraticTerm{Float64}(2, MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(1)))
source
MathOptInterface.VectorQuadraticFunctionType
VectorQuadraticFunction{T}(
+    quadratic_terms::Vector{VectorQuadraticTerm{T}},
+    affine_terms::Vector{VectorAffineTerm{T}},
+    constants::Vector{T},
+) where {T}

The vector-valued quadratic function with ith component ("output index") defined as $\frac{1}{2}x^\top Q_i x + a_i^\top x + b_i$, where:

  • $\frac{1}{2}x^\top Q_i x$ is the symmetric matrix given by the VectorQuadraticTerm elements in quadratic_terms with output_index == i
  • $a_i^\top x$ is the sparse vector given by the VectorAffineTerm elements in affine_terms with output_index == i
  • $b_i$ is a scalar given by constants[i]

Duplicates

Duplicate indices in quadratic_terms and affine_terms with the same output_index are handled in the same manner as duplicates in ScalarQuadraticFunction.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> y = MOI.VariableIndex(2);
+
+julia> constants = [4.0, 5.0];
+
+julia> affine_terms = [
+           MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),
+           MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),
+       ];
+
+julia> quad_terms = [
+        MOI.VectorQuadraticTerm(Int64(1), MOI.ScalarQuadraticTerm(2.0, x, x)),
+        MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, y)),
+           ];
+
+julia> f = MOI.VectorQuadraticFunction(quad_terms, affine_terms, constants)
+┌                                                                              ┐
+│4.0 + 2.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²                    │
+│5.0 + 3.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)│
+└                                                                              ┘
+
+julia> MOI.output_dimension(f)
+2
source
MathOptInterface.VectorNonlinearFunctionType
VectorNonlinearFunction(args::Vector{ScalarNonlinearFunction})

The vector-valued nonlinear function composed of a vector of ScalarNonlinearFunction.

args

The vector args contains the scalar elements of the nonlinear function. Each element must be a ScalarNonlinearFunction, but if you pass a Vector{Any}, the elements can be automatically converted from one of the following:

Example

To represent the function $f(x) = [sin(x)^2, x]$, do:

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> g = MOI.ScalarNonlinearFunction(
+           :^,
+           Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2.0],
+       )
+^(sin(MOI.VariableIndex(1)), 2.0)
+
+julia> MOI.VectorNonlinearFunction([g, x])
+┌                                 ┐
+│^(sin(MOI.VariableIndex(1)), 2.0)│
+│+(MOI.VariableIndex(1))          │
+└                                 ┘

Note the automatic conversion from x to +(x).

source

Sets

MathOptInterface.AbstractSetType
AbstractSet

Abstract supertype for set objects used to encode constraints.

Required methods

For sets of type S with isbitstype(S) == false, you must implement:

  • Base.copy(set::S)
  • Base.:(==)(x::S, y::S)

Subtypes of AbstractSet such as AbstractScalarSet and AbstractVectorSet may prescribe additional required methods.

Optional methods

You may optionally implement:

Note for developers

When creating a new set, the set struct must not contain any VariableIndex or ConstraintIndex objects.

source
MathOptInterface.AbstractVectorSetType
AbstractVectorSet

Abstract supertype for subsets of $\mathbb{R}^n$ for some $n$.

Required methods

All AbstractVectorSets of type S must implement:

  • dimension, unless the dimension is stored in the set.dimension field
  • Utilities.set_dot, unless the dot product between two vectors in the set is equivalent to LinearAlgebra.dot.
source

Utilities

MathOptInterface.dimensionFunction
dimension(set::AbstractSet)

Return the output_dimension that an AbstractFunction should have to be used with the set set.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.dimension(MOI.Reals(4))
+4
+
+julia> MOI.dimension(MOI.LessThan(3.0))
+1
+
+julia> MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(2))
+3
source
MathOptInterface.dual_setFunction
dual_set(set::AbstractSet)

Return the dual set of set, that is the dual cone of the set. This follows the definition of duality discussed in Duality.

See Dual cone for more information.

If the dual cone is not defined it returns an error.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.dual_set(MOI.Reals(4))
+MathOptInterface.Zeros(4)
+
+julia> MOI.dual_set(MOI.SecondOrderCone(5))
+MathOptInterface.SecondOrderCone(5)
+
+julia> MOI.dual_set(MOI.ExponentialCone())
+MathOptInterface.DualExponentialCone()
source
MathOptInterface.dual_set_typeFunction
dual_set_type(S::Type{<:AbstractSet})

Return the type of dual set of sets of type S, as returned by dual_set. If the dual cone is not defined it returns an error.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.dual_set_type(MOI.Reals)
+MathOptInterface.Zeros
+
+julia> MOI.dual_set_type(MOI.SecondOrderCone)
+MathOptInterface.SecondOrderCone
+
+julia> MOI.dual_set_type(MOI.ExponentialCone)
+MathOptInterface.DualExponentialCone
source
MathOptInterface.constantMethod
constant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})

Returns the constant term of the set set.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.constant(MOI.GreaterThan(1.0))
+1.0
+
+julia> MOI.constant(MOI.LessThan(2.5))
+2.5
+
+julia> MOI.constant(MOI.EqualTo(3))
+3
+
+julia> MOI.constant(MOI.Parameter(4.5))
+4.5
source
MathOptInterface.supports_dimension_updateFunction
supports_dimension_update(S::Type{<:MOI.AbstractVectorSet})

Return a Bool indicating whether the elimination of any dimension of n-dimensional sets of type S give an n-1-dimensional set S. By default, this function returns false so it should only be implemented for sets that supports dimension update.

For instance, supports_dimension_update(MOI.Nonnegatives) is true because the elimination of any dimension of the n-dimensional nonnegative orthant gives the n-1-dimensional nonnegative orthant. However supports_dimension_update(MOI.ExponentialCone) is false.

source

Scalar sets

List of recognized scalar sets.

MathOptInterface.GreaterThanType
GreaterThan{T<:Real}(lower::T)

The set $[lower, \infty) \subseteq \mathbb{R}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.GreaterThan(0.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)
source
MathOptInterface.LessThanType
LessThan{T<:Real}(upper::T)

The set $(-\infty, upper] \subseteq \mathbb{R}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.LessThan(2.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64}}(1)
source
MathOptInterface.EqualToType
EqualTo{T<:Number}(value::T)

The set containing the single point $\{value\} \subseteq \mathbb{R}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.EqualTo(2.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}}(1)
source
MathOptInterface.IntervalType
Interval{T<:Real}(lower::T, upper::T)

The interval $[lower, upper] \subseteq \mathbb{R} \cup \{-\infty, +\infty\}$.

If lower or upper is -Inf or Inf, respectively, the set is interpreted as a one-sided interval.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.Interval(1.0, 2.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
source
MathOptInterface.IntegerType
Integer()

The set of integers, $\mathbb{Z}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.Integer())
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)
source
MathOptInterface.ZeroOneType
ZeroOne()

The set $\{0, 1\}$.

Variables belonging to the ZeroOne set are also known as "binary" variables.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.ZeroOne())
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)
source
MathOptInterface.SemicontinuousType
Semicontinuous{T<:Real}(lower::T, upper::T)

The set $\{0\} \cup [lower, upper]$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.Semicontinuous(2.0, 3.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semicontinuous{Float64}}(1)
source
MathOptInterface.SemiintegerType
Semiinteger{T<:Real}(lower::T, upper::T)

The set $\{0\} \cup \{lower, lower+1, \ldots, upper-1, upper\}$.

Note that if lower and upper are not equivalent to an integer, then the solver may throw an error, or it may round up lower and round down upper to the nearest integers.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.Semiinteger(2.0, 3.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semiinteger{Float64}}(1)
source
MathOptInterface.ParameterType
Parameter{T<:Number}(value::T)

The set containing the single point $\{value\} \subseteq \mathbb{R}$.

The Parameter set is conceptually similar to the EqualTo set, except that a variable constrained to the Parameter set cannot have other constraints added to it, and the Parameter set can never be deleted. Thus, solvers are free to treat the variable as a constant, and they need not add it as a decision variable to the model.

Because of this behavior, you must add parameters using add_constrained_variable, and solvers should declare supports_add_constrained_variable and not supports_constraint for the Parameter set.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> p, ci = MOI.add_constrained_variable(model, MOI.Parameter(2.5))
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Parameter{Float64}}(1))
+
+julia> MOI.set(model, MOI.ConstraintSet(), ci, MOI.Parameter(3.0))
+
+julia> MOI.get(model, MOI.ConstraintSet(), ci)
+MathOptInterface.Parameter{Float64}(3.0)
source

Vector sets

List of recognized vector sets.

MathOptInterface.RealsType
Reals(dimension::Int)

The set $\mathbb{R}^{dimension}$ (containing all points) of non-negative dimension dimension.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Reals(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Reals}(1)
source
MathOptInterface.ZerosType
Zeros(dimension::Int)

The set $\{ 0 \}^{dimension}$ (containing only the origin) of non-negative dimension dimension.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Zeros(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Zeros}(1)
source
MathOptInterface.NonnegativesType
Nonnegatives(dimension::Int)

The nonnegative orthant $\{ x \in \mathbb{R}^{dimension} : x \ge 0 \}$ of non-negative dimension dimension.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)
source
MathOptInterface.NonpositivesType
Nonpositives(dimension::Int)

The nonpositive orthant $\{ x \in \mathbb{R}^{dimension} : x \le 0 \}$ of non-negative dimension dimension.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonpositives(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonpositives}(1)
source
MathOptInterface.NormInfinityConeType
NormInfinityCone(dimension::Int)

The $\ell_\infty$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_\infty = \max_i \lvert x_i \rvert \}$ of dimension dimension.

The dimension must be at least 1.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormInfinityCone(4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormInfinityCone}(1)
source
MathOptInterface.NormOneConeType
NormOneCone(dimension::Int)

The $\ell_1$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_1 = \sum_i \lvert x_i \rvert \}$ of dimension dimension.

The dimension must be at least 1.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormOneCone(4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormOneCone}(1)
source
MathOptInterface.NormConeType
NormCone(p::Float64, dimension::Int)

The $\ell_p$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \left(\sum\limits_i |x_i|^p\right)^{\frac{1}{p}} \}$ of dimension dimension.

The dimension must be at least 1.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormCone(3, 4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormCone}(1)
source
MathOptInterface.SecondOrderConeType
SecondOrderCone(dimension::Int)

The second-order cone (or Lorenz cone or $\ell_2$-norm cone) $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_2 \}$ of dimension dimension.

The dimension must be at least 1.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.SecondOrderCone(4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SecondOrderCone}(1)
source
MathOptInterface.RotatedSecondOrderConeType
RotatedSecondOrderCone(dimension::Int)

The rotated second-order cone $\{ (t,u,x) \in \mathbb{R}^{dimension} : 2tu \ge \lVert x \rVert_2^2, t,u \ge 0 \}$ of dimension dimension.

The dimension must be at least 2.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> u = MOI.add_variable(model)
+MOI.VariableIndex(2)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; u; x]),
+           MOI.RotatedSecondOrderCone(5),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RotatedSecondOrderCone}(1)
source
MathOptInterface.GeometricMeanConeType
GeometricMeanCone(dimension::Int)

The geometric mean cone $\{ (t,x) \in \mathbb{R}^{n+1} : x \ge 0, t \le \sqrt[n]{x_1 x_2 \cdots x_n} \}$, where dimension = n + 1 >= 2.

Duality note

The dual of the geometric mean cone is $\{ (u, v) \in \mathbb{R}^{n+1} : u \le 0, v \ge 0, -u \le n \sqrt[n]{\prod_i v_i} \}$, where dimension = n + 1 >= 2.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; x]),
+           MOI.GeometricMeanCone(4),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.GeometricMeanCone}(1)
source
MathOptInterface.ExponentialConeType
ExponentialCone()

The 3-dimensional exponential cone $\{ (x,y,z) \in \mathbb{R}^3 : y \exp (x/y) \le z, y > 0 \}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.ExponentialCone())
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.ExponentialCone}(1)
source
MathOptInterface.DualExponentialConeType
DualExponentialCone()

The 3-dimensional dual exponential cone $\{ (u,v,w) \in \mathbb{R}^3 : -u \exp (v/u) \le \exp(1) w, u < 0 \}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualExponentialCone())
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualExponentialCone}(1)
source
MathOptInterface.PowerConeType
PowerCone{T<:Real}(exponent::T)

The 3-dimensional power cone $\{ (x,y,z) \in \mathbb{R}^3 : x^{exponent} y^{1-exponent} \ge |z|, x \ge 0, y \ge 0 \}$ with parameter exponent.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.PowerCone(0.5))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.PowerCone{Float64}}(1)
source
MathOptInterface.DualPowerConeType
DualPowerCone{T<:Real}(exponent::T)

The 3-dimensional power cone $\{ (u,v,w) \in \mathbb{R}^3 : (\frac{u}{exponent})^{exponent} (\frac{v}{1-exponent})^{1-exponent} \ge |w|, u \ge 0, v \ge 0 \}$ with parameter exponent.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualPowerCone(0.5))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualPowerCone{Float64}}(1)
source
MathOptInterface.RelativeEntropyConeType
RelativeEntropyCone(dimension::Int)

The relative entropy cone $\{ (u, v, w) \in \mathbb{R}^{1+2n} : u \ge \sum_{i=1}^n w_i \log(\frac{w_i}{v_i}), v_i \ge 0, w_i \ge 0 \}$, where dimension = 2n + 1 >= 1.

Duality note

The dual of the relative entropy cone is $\{ (u, v, w) \in \mathbb{R}^{1+2n} : \forall i, w_i \ge u (\log (\frac{u}{v_i}) - 1), v_i \ge 0, u > 0 \}$ of dimension dimension${}=2n+1$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> u = MOI.add_variable(model);
+
+julia> v = MOI.add_variables(model, 3);
+
+julia> w = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([u; v; w]),
+           MOI.RelativeEntropyCone(7),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RelativeEntropyCone}(1)
source
MathOptInterface.NormSpectralConeType
NormSpectralCone(row_dim::Int, column_dim::Int)

The epigraph of the matrix spectral norm (maximum singular value function) $\{ (t, X) \in \mathbb{R}^{1 + row_dim \times column_dim} : t \ge \sigma_1(X) \}$, where $\sigma_i$ is the $i$th singular value of the matrix $X$ of non-negative row dimension row_dim and column dimension column_dim.

The matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = reshape(MOI.add_variables(model, 6), 2, 3)
+2×3 Matrix{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)  MOI.VariableIndex(4)  MOI.VariableIndex(6)
+ MOI.VariableIndex(3)  MOI.VariableIndex(5)  MOI.VariableIndex(7)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; vec(X)]),
+           MOI.NormSpectralCone(2, 3),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormSpectralCone}(1)
source
MathOptInterface.NormNuclearConeType
NormNuclearCone(row_dim::Int, column_dim::Int)

The epigraph of the matrix nuclear norm (sum of singular values function) $\{ (t, X) \in \mathbb{R}^{1 + row_dim \times column_dim} : t \ge \sum_i \sigma_i(X) \}$, where $\sigma_i$ is the $i$th singular value of the matrix $X$ of non-negative row dimension row_dim and column dimension column_dim.

The matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = reshape(MOI.add_variables(model, 6), 2, 3)
+2×3 Matrix{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)  MOI.VariableIndex(4)  MOI.VariableIndex(6)
+ MOI.VariableIndex(3)  MOI.VariableIndex(5)  MOI.VariableIndex(7)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; vec(X)]),
+           MOI.NormNuclearCone(2, 3),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormNuclearCone}(1)
source
MathOptInterface.SOS1Type
SOS1{T<:Real}(weights::Vector{T})

The set corresponding to the Special Ordered Set (SOS) constraint of Type I.

Of the variables in the set, at most one can be nonzero.

The weights induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights. Solvers may use these weights to improve the efficiency of the solution process, but the ordering does not change the set of feasible solutions.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables(x),
+           MOI.SOS1([1.0, 3.0, 2.5]),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS1{Float64}}(1)
source
MathOptInterface.SOS2Type
SOS2{T<:Real}(weights::Vector{T})

The set corresponding to the Special Ordered Set (SOS) constraint of Type II.

The weights induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights. Therefore, the weights must be unique.

Of the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables(x),
+           MOI.SOS2([1.0, 3.0, 2.5]),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS2{Float64}}(1)
source
MathOptInterface.IndicatorType
Indicator{A<:ActivationCondition,S<:AbstractScalarSet}(set::S)

The set corresponding to an indicator constraint.

When A is ACTIVATE_ON_ZERO, this means: $\{(y, x) \in \{0, 1\} \times \mathbb{R}^n : y = 0 \implies x \in set\}$

When A is ACTIVATE_ON_ONE, this means: $\{(y, x) \in \{0, 1\} \times \mathbb{R}^n : y = 1 \implies x \in set\}$

Notes

Most solvers expect that the first row of the function is interpretable as a variable index x_i (e.g., 1.0 * x + 0.0). An error will be thrown if this is not the case.

Example

The constraint $\{(y, x) \in \{0, 1\} \times \mathbb{R}^2 : y = 1 \implies x_1 + x_2 \leq 9 \}$ is defined as

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 2)
+2-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+
+julia> y, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
+(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3))
+
+julia> f = MOI.VectorAffineFunction(
+           [
+               MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, y)),
+               MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[1])),
+               MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[2])),
+           ],
+           [0.0, 0.0],
+       )
+┌                                                         ┐
+│0.0 + 1.0 MOI.VariableIndex(3)                           │
+│0.0 + 1.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(2)│
+└                                                         ┘
+
+julia> s = MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(9.0))
+MathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}(MathOptInterface.LessThan{Float64}(9.0))
+
+julia> MOI.add_constraint(model, f, s)
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}}(1)
source
MathOptInterface.ComplementsType
Complements(dimension::Base.Integer)

The set corresponding to a mixed complementarity constraint.

Complementarity constraints should be specified with an AbstractVectorFunction-in-Complements(dimension) constraint.

The dimension of the vector-valued function F must be dimension. This defines a complementarity constraint between the scalar function F[i] and the variable in F[i + dimension/2]. Thus, F[i + dimension/2] must be interpretable as a single variable x_i (e.g., 1.0 * x + 0.0), and dimension must be even.

The mixed complementarity problem consists of finding x_i in the interval [lb, ub] (i.e., in the set Interval(lb, ub)), such that the following holds:

  1. F_i(x) == 0 if lb_i < x_i < ub_i
  2. F_i(x) >= 0 if lb_i == x_i
  3. F_i(x) <= 0 if x_i == ub_i

Classically, the bounding set for x_i is Interval(0, Inf), which recovers: 0 <= F_i(x) ⟂ x_i >= 0, where the operator implies F_i(x) * x_i = 0.

Example

The problem:

x -in- Interval(-1, 1)
+[-4 * x - 3, x] -in- Complements(2)

defines the mixed complementarity problem where the following holds:

  1. -4 * x - 3 == 0 if -1 < x < 1
  2. -4 * x - 3 >= 0 if x == -1
  3. -4 * x - 3 <= 0 if x == 1

There are three solutions:

  1. x = -3/4 with F(x) = 0
  2. x = -1 with F(x) = 1
  3. x = 1 with F(x) = -7
julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x, _ = MOI.add_constrained_variable(model, MOI.Interval(-1.0, 1.0));
+
+julia> MOI.add_constraint(
+            model,
+            MOI.Utilities.vectorize([-4.0 * x - 3.0, x]),
+            MOI.Complements(2),
+        )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Complements}(1)

The function F can also be defined in terms of single variables. For example, the problem:

[x_3, x_4] -in- Nonnegatives(2)
+[x_1, x_2, x_3, x_4] -in- Complements(4)

defines the complementarity problem where 0 <= x_1 ⟂ x_3 >= 0 and 0 <= x_2 ⟂ x_4 >= 0.

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 4);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x[3:4]), MOI.Nonnegatives(2))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)
+
+julia> MOI.add_constraint(
+            model,
+            MOI.VectorOfVariables(x),
+            MOI.Complements(4),
+        )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Complements}(1)
source
MathOptInterface.HyperRectangleType
HyperRectangle(lower::Vector{T}, upper::Vector{T}) where {T}

The set $\{x \in \bar{\mathbb{R}}^d: x_i \in [lower_i, upper_i] \forall i=1,\ldots,d\}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3)
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables(x),
+           MOI.HyperRectangle(zeros(3), ones(3)),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.HyperRectangle{Float64}}(1)
source
MathOptInterface.ScaledType
struct Scaled{S<:AbstractVectorSet} <: AbstractVectorSet
+    set::S
+end

Given a vector $a \in \mathbb{R}^d$ and a set representing the set $\mathcal{S} \in \mathbb{R}^d$ such that Utilities.set_dot for $x \in \mathcal{S}$ and $y \in \mathcal{S}^*$ is

\[\sum_{i=1}^d a_i x_i y_i\]

the set Scaled(set) is defined as

\[\{ (\sqrt{a_1} x_1, \sqrt{a_2} x_2, \ldots, \sqrt{a_d} x_d) : x \in S \}\]

Example

This can be used to scale a vector of numbers

julia> import MathOptInterface as MOI
+
+julia> set = MOI.PositiveSemidefiniteConeTriangle(2)
+MathOptInterface.PositiveSemidefiniteConeTriangle(2)
+
+julia> a = MOI.Utilities.SetDotScalingVector{Float64}(set)
+3-element MathOptInterface.Utilities.SetDotScalingVector{Float64, MathOptInterface.PositiveSemidefiniteConeTriangle}:
+ 1.0
+ 1.4142135623730951
+ 1.0
+
+julia> using LinearAlgebra
+
+julia> MOI.Utilities.operate(*, Float64, Diagonal(a), ones(3))
+3-element Vector{Float64}:
+ 1.0
+ 1.4142135623730951
+ 1.0

It can be also used to scale a vector of function

julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> func = MOI.VectorOfVariables(x)
+┌                    ┐
+│MOI.VariableIndex(1)│
+│MOI.VariableIndex(2)│
+│MOI.VariableIndex(3)│
+└                    ┘
+
+julia> set = MOI.PositiveSemidefiniteConeTriangle(2)
+MathOptInterface.PositiveSemidefiniteConeTriangle(2)
+
+julia> MOI.Utilities.operate(*, Float64, Diagonal(a), func)
+┌                                             ┐
+│0.0 + 1.0 MOI.VariableIndex(1)               │
+│0.0 + 1.4142135623730951 MOI.VariableIndex(2)│
+│0.0 + 1.0 MOI.VariableIndex(3)               │
+└                                             ┘
source

Constraint programming sets

MathOptInterface.AllDifferentType
AllDifferent(dimension::Int)

The set $\{x \in \mathbb{Z}^{d}\}$ such that no two elements in $x$ take the same value and dimension = d.

Also known as

This constraint is called all_different in MiniZinc, and is sometimes also called distinct.

Example

To enforce x[1] != x[2] AND x[1] != x[3] AND x[2] != x[3]:

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.AllDifferent(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.AllDifferent}(1)
source
MathOptInterface.BinPackingType
BinPacking(c::T, w::Vector{T}) where {T}

The set $\{x \in \mathbb{Z}^d\}$ where d = length(w), such that each item i in 1:d of weight w[i] is put into bin x[i], and the total weight of each bin does not exceed c.

There are additional assumptions that the capacity, c, and the weights, w, must all be non-negative.

The bin numbers depend on the bounds of x, so they may be something other than the integers 1:d.

Also known as

This constraint is called bin_packing in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> bins = MOI.add_variables(model, 5)
+5-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+ MOI.VariableIndex(5)
+
+julia> weights = Float64[1, 1, 2, 2, 3]
+5-element Vector{Float64}:
+ 1.0
+ 1.0
+ 2.0
+ 2.0
+ 3.0
+
+julia> MOI.add_constraint.(model, bins, MOI.Integer())
+5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(4)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(5)
+
+julia> MOI.add_constraint.(model, bins, MOI.Interval(4.0, 6.0))
+5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(2)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(3)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(4)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(5)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(bins), MOI.BinPacking(3.0, weights))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.BinPacking{Float64}}(1)
source
MathOptInterface.CircuitType
Circuit(dimension::Int)

The set $\{x \in \{1..d\}^d\}$ that constraints $x$ to be a circuit, such that $x_i = j$ means that $j$ is the successor of $i$, and dimension = d.

Graphs with multiple independent circuits, such as [2, 1, 3] and [2, 1, 4, 3], are not valid.

Also known as

This constraint is called circuit in MiniZinc, and it is equivalent to forming a (potentially sub-optimal) tour in the travelling salesperson problem.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Circuit(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Circuit}(1)
source
MathOptInterface.CountAtLeastType
CountAtLeast(n::Int, d::Vector{Int}, set::Set{Int})

The set $\{x \in \mathbb{Z}^{d_1 + d_2 + \ldots d_N}\}$, where x is partitioned into N subsets ($\{x_1, \ldots, x_{d_1}\}$, $\{x_{d_1 + 1}, \ldots, x_{d_1 + d_2}\}$ and so on), and at least $n$ elements of each subset take one of the values in set.

Also known as

This constraint is called at_least in MiniZinc.

Example

To ensure that 3 appears at least once in each of the subsets {a, b} and {b, c}:

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> a, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
+
+julia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3))
+
+julia> x, d, set = [a, b, b, c], [2, 2], [3]
+(MathOptInterface.VariableIndex[MOI.VariableIndex(1), MOI.VariableIndex(2), MOI.VariableIndex(2), MOI.VariableIndex(3)], [2, 2], [3])
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.CountAtLeast(1, d, Set(set)))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountAtLeast}(1)
source
MathOptInterface.CountBelongsType
CountBelongs(dimenson::Int, set::Set{Int})

The set $\{(n, x) \in \mathbb{Z}^{1+d}\}$, such that n elements of the vector x take on of the values in set and dimension = 1 + d.

Also known as

This constraint is called among by MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+
+julia> set = Set([3, 4, 5])
+Set{Int64} with 3 elements:
+  5
+  4
+  3
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([n; x]), MOI.CountBelongs(4, set))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountBelongs}(1)
source
MathOptInterface.CountDistinctType
CountDistinct(dimension::Int)

The set $\{(n, x) \in \mathbb{Z}^{1+d}\}$, such that the number of distinct values in x is n and dimension = 1 + d.

Also known as

This constraint is called nvalues in MiniZinc.

Example

To model:

  • if n == 1`, thenx[1] == x[2] == x[3]`
  • if n == 2, then
    • x[1] == x[2] != x[3] or
    • x[1] != x[2] == x[3] or
    • x[1] == x[3] != x[2]
  • if n == 3, then x[1] != x[2], x[2] != x[3] and x[3] != x[1]
julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(vcat(n, x)), MOI.CountDistinct(4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountDistinct}(1)

Relationship to AllDifferent

When the first element is d, CountDistinct is equivalent to an AllDifferent constraint.

source
MathOptInterface.CountGreaterThanType
CountGreaterThan(dimension::Int)

The set $\{(c, y, x) \in \mathbb{Z}^{1+1+d}\}$, such that c is strictly greater than the number of occurances of y in x and dimension = 1 + 1 + d.

Also known as

This constraint is called count_gt in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> y, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+ MOI.VariableIndex(5)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([c; y; x]), MOI.CountGreaterThan(5))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountGreaterThan}(1)
source
MathOptInterface.CumulativeType
Cumulative(dimension::Int)

The set $\{(s, d, r, b) \in \mathbb{Z}^{3n+1}\}$, representing the cumulative global constraint, where n == length(s) == length(r) == length(b) and dimension = 3n + 1.

Cumulative requires that a set of tasks given by start times $s$, durations $d$, and resource requirements $r$, never requires more than the global resource bound $b$ at any one time.

Also known as

This constraint is called cumulative in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> s = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> d = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(4)
+ MOI.VariableIndex(5)
+ MOI.VariableIndex(6)
+
+julia> r = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(7)
+ MOI.VariableIndex(8)
+ MOI.VariableIndex(9)
+
+julia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(10), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(10))
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([s; d; r; b]), MOI.Cumulative(10))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Cumulative}(1)
source
MathOptInterface.PathType
Path(from::Vector{Int}, to::Vector{Int})

Given a graph comprised of a set of nodes 1..N and a set of arcs 1..E represented by an edge from node from[i] to node to[i], Path constrains the set $(s, t, ns, es) \in (1..N)\times(1..E)\times\{0,1\}^N\times\{0,1\}^E$, to form subgraph that is a path from node s to node t, where node n is in the path if ns[n] is 1, and edge e is in the path if es[e] is 1.

The path must be acyclic, and it must traverse all nodes n for which ns[n] is 1, and all edges e for which es[e] is 1.

Also known as

This constraint is called path in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> N, E = 4, 5
+(4, 5)
+
+julia> from = [1, 1, 2, 2, 3]
+5-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 2
+ 3
+
+julia> to = [2, 3, 3, 4, 4]
+5-element Vector{Int64}:
+ 2
+ 3
+ 3
+ 4
+ 4
+
+julia> s, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> t, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
+
+julia> ns = MOI.add_variables(model, N)
+4-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+ MOI.VariableIndex(5)
+ MOI.VariableIndex(6)
+
+julia> MOI.add_constraint.(model, ns, MOI.ZeroOne())
+4-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(4)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(5)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(6)
+
+julia> es = MOI.add_variables(model, E)
+5-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(7)
+ MOI.VariableIndex(8)
+ MOI.VariableIndex(9)
+ MOI.VariableIndex(10)
+ MOI.VariableIndex(11)
+
+julia> MOI.add_constraint.(model, es, MOI.ZeroOne())
+5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(7)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(8)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(9)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(10)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(11)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([s; t; ns; es]), MOI.Path(from, to))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Path}(1)
source
MathOptInterface.ReifiedType
Reified(set::AbstractSet)

The constraint $[z; f(x)] \in Reified(S)$ ensures that $f(x) \in S$ if and only if $z == 1$, where $z \in \{0, 1\}$.

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
+MOIU.UniversalFallback{MOIU.Model{Float64}}
+fallback for MOIU.Model{Float64}
+
+julia> z, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1))
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(2)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.Utilities.vectorize([z, 2.0 * x]),
+           MOI.Reified(MOI.GreaterThan(1.0)),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Reified{MathOptInterface.GreaterThan{Float64}}}(1)
source
MathOptInterface.TableType
Table(table::Matrix{T}) where {T}

The set $\{x \in \mathbb{R}^d\}$ where d = size(table, 2), such that x belongs to one row of table. That is, there exists some j in 1:size(table, 1), such that x[i] = table[j, i] for all i=1:size(table, 2).

Also known as

This constraint is called table in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3)
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> table = Float64[1 1 0; 0 1 1; 1 0 1; 1 1 1]
+4×3 Matrix{Float64}:
+ 1.0  1.0  0.0
+ 0.0  1.0  1.0
+ 1.0  0.0  1.0
+ 1.0  1.0  1.0
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Table(table))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Table{Float64}}(1)
source

Matrix sets

Matrix sets are vectorized to be subtypes of AbstractVectorSet.

For sets of symmetric matrices, storing both the (i, j) and (j, i) elements is redundant. Use the AbstractSymmetricMatrixSetTriangle set to represent only the vectorization of the upper triangular part of the matrix.

When the matrix of expressions constrained to be in the set is not symmetric, and hence additional constraints are needed to force the equality of the (i, j) and (j, i) elements, use the AbstractSymmetricMatrixSetSquare set.

The Bridges.Constraint.SquareBridge can transform a set from the square form to the triangular_form by adding appropriate constraints if the (i, j) and (j, i) expressions are different.

MathOptInterface.AbstractSymmetricMatrixSetTriangleType
abstract type AbstractSymmetricMatrixSetTriangle <: AbstractVectorSet end

Abstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row). A vectorized cone of dimension $n$ corresponds to a square matrix with side dimension $\sqrt{1/4 + 2 n} - 1/2$. (Because a $d \times d$ matrix has $d(d + 1) / 2$ elements in the upper or lower triangle.)

Example

The matrix

\[\begin{bmatrix} + 1 & 2 & 4\\ + 2 & 3 & 5\\ + 4 & 5 & 6 +\end{bmatrix}\]

has side_dimension 3 and vectorization $(1, 2, 3, 4, 5, 6)$.

Note

Two packed storage formats exist for symmetric matrices, the respective orders of the entries are:

  • upper triangular column by column (or lower triangular row by row);
  • lower triangular column by column (or upper triangular row by row).

The advantage of the first format is the mapping between the (i, j) matrix indices and the k index of the vectorized form. It is simpler and does not depend on the side dimension of the matrix. Indeed,

  • the entry of matrix indices (i, j) has vectorized index k = div((j - 1) * j, 2) + i if $i \leq j$ and k = div((i - 1) * i, 2) + j if $j \leq i$;
  • and the entry with vectorized index k has matrix indices i = div(1 + isqrt(8k - 7), 2) and j = k - div((i - 1) * i, 2) or j = div(1 + isqrt(8k - 7), 2) and i = k - div((j - 1) * j, 2).

Duality note

The scalar product for the symmetric matrix in its vectorized form is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries; see [p. 634, 1]. This has important consequence for duality.

Consider for example the following problem (PositiveSemidefiniteConeTriangle is a subtype of AbstractSymmetricMatrixSetTriangle)

\[\begin{align*} + & \max_{x \in \mathbb{R}} & x + \\ + & \;\;\text{s.t.} & + (1, -x, 1) & \in \text{PositiveSemidefiniteConeTriangle}(2). +\end{align*}\]

The dual is the following problem

\[\begin{align*} + & \min_{x \in \mathbb{R}^3} & y_1 + y_3 + \\ + & \;\;\text{s.t.} & 2y_2 & = 1\\ + & & y & \in \text{PositiveSemidefiniteConeTriangle}(2). +\end{align*}\]

Why do we use $2y_2$ in the dual constraint instead of $y_2$ ? The reason is that $2y_2$ is the scalar product between $y$ and the symmetric matrix whose vectorized form is $(0, 1, 0)$. Indeed, with our modified scalar products we have

\[\langle +(0, 1, 0), +(y_1, y_2, y_3) +\rangle += +\mathrm{trace} +\begin{pmatrix} + 0 & 1\\ + 1 & 0 +\end{pmatrix} +\begin{pmatrix} + y_1 & y_2\\ + y_2 & y_3 +\end{pmatrix} += 2y_2.\]

References

[1] Boyd, S. and Vandenberghe, L.. Convex optimization. Cambridge university press, 2004.

source
MathOptInterface.AbstractSymmetricMatrixSetSquareType
abstract type AbstractSymmetricMatrixSetSquare <: AbstractVectorSet end

Abstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the matrix are given column by column (or equivalently, row by row). The matrix is both constrained to be symmetric and to have its triangular_form belong to the corresponding set. That is, if the functions in entries $(i, j)$ and $(j, i)$ are different, then a constraint will be added to make sure that the entries are equal.

Example

PositiveSemidefiniteConeSquare is a subtype of AbstractSymmetricMatrixSetSquare and constraining the matrix

\[\begin{bmatrix} + 1 & -y\\ + -z & 0\\ +\end{bmatrix}\]

to be symmetric positive semidefinite can be achieved by constraining the vector $(1, -z, -y, 0)$ (or $(1, -y, -z, 0)$) to belong to the PositiveSemidefiniteConeSquare(2). It both constrains $y = z$ and $(1, -y, 0)$ (or $(1, -z, 0)$) to be in PositiveSemidefiniteConeTriangle(2), since triangular_form(PositiveSemidefiniteConeSquare) is PositiveSemidefiniteConeTriangle.

source

List of recognized matrix sets.

MathOptInterface.PositiveSemidefiniteConeSquareType
PositiveSemidefiniteConeSquare(side_dimension::Int) <: AbstractSymmetricMatrixSetSquare

The cone of symmetric positive semidefinite matrices, with non-negative side length side_dimension.

See AbstractSymmetricMatrixSetSquare for more details on the vectorized form.

The entries of the matrix are given column by column (or equivalently, row by row).

The matrix is both constrained to be symmetric and to be positive semidefinite. That is, if the functions in entries $(i, j)$ and $(j, i)$ are different, then a constraint will be added to make sure that the entries are equal.

Example

Constraining the matrix

\[\begin{bmatrix} + 1 & -y\\ + -z & 0\\ +\end{bmatrix}\]

to be symmetric positive semidefinite can be achieved by constraining the vector $(1, -z, -y, 0)$ (or $(1, -y, -z, 0)$) to belong to the PositiveSemidefiniteConeSquare(2).

It both constrains $y = z$ and $(1, -y, 0)$ (or $(1, -z, 0)$) to be in PositiveSemidefiniteConeTriangle(2).

source
MathOptInterface.HermitianPositiveSemidefiniteConeTriangleType
HermitianPositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractVectorSet

The (vectorized) cone of Hermitian positive semidefinite matrices, with non-negative side_dimension rows and columns.

Becaue the matrix is Hermitian, the diagonal elements are real, and the complex-valued lower triangular entries are obtained as the conjugate of corresponding upper triangular entries.

Vectorization format

The vectorized form starts with real part of the entries of the upper triangular part of the matrix, given column by column as explained in AbstractSymmetricMatrixSetSquare.

It is then followed by the imaginary part of the off-diagonal entries of the upper triangular part, also given column by column.

For example, the matrix

\[\begin{bmatrix} + 1 & 2 + 7im & 4 + 8im\\ + 2 - 7im & 3 & 5 + 9im\\ + 4 - 8im & 5 - 9im & 6 +\end{bmatrix}\]

has side_dimension 3 and is represented as the vector $[1, 2, 3, 4, 5, 6, 7, 8, 9]$.

source
MathOptInterface.LogDetConeTriangleType
LogDetConeTriangle(side_dimension::Int)

The log-determinant cone $\{ (t, u, X) \in \mathbb{R}^{2 + d(d+1)/2} : t \le u \log(\det(X/u)), u > 0 \}$, where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle.

The non-negative argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; X]),
+           MOI.LogDetConeTriangle(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeTriangle}(1)
source
MathOptInterface.LogDetConeSquareType
LogDetConeSquare(side_dimension::Int)

The log-determinant cone $\{ (t, u, X) \in \mathbb{R}^{2 + d^2} : t \le u \log(\det(X/u)), X \text{ symmetric}, u > 0 \}$, where the matrix X is represented in the same format as in the PositiveSemidefiniteConeSquare.

Similarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric.

The non-negative argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = reshape(MOI.add_variables(model, 4), 2, 2)
+2×2 Matrix{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)  MOI.VariableIndex(4)
+ MOI.VariableIndex(3)  MOI.VariableIndex(5)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; vec(X)]),
+           MOI.LogDetConeSquare(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeSquare}(1)
source
MathOptInterface.RootDetConeTriangleType
RootDetConeTriangle(side_dimension::Int)

The root-determinant cone $\{ (t, X) \in \mathbb{R}^{1 + d(d+1)/2} : t \le \det(X)^{1/d} \}$, where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle.

The non-negative argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; X]),
+           MOI.RootDetConeTriangle(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeTriangle}(1)
source
MathOptInterface.RootDetConeSquareType
RootDetConeSquare(side_dimension::Int)

The root-determinant cone $\{ (t, X) \in \mathbb{R}^{1 + d^2} : t \le \det(X)^{1/d}, X \text{ symmetric} \}$, where the matrix X is represented in the same format as PositiveSemidefiniteConeSquare.

Similarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric.

The non-negative argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = reshape(MOI.add_variables(model, 4), 2, 2)
+2×2 Matrix{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)  MOI.VariableIndex(4)
+ MOI.VariableIndex(3)  MOI.VariableIndex(5)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; vec(X)]),
+           MOI.RootDetConeSquare(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeSquare}(1)
source
diff --git a/previews/PR2274/reference/variables/index.html b/previews/PR2274/reference/variables/index.html new file mode 100644 index 0000000000..79b2acded5 --- /dev/null +++ b/previews/PR2274/reference/variables/index.html @@ -0,0 +1,24 @@ + +Variables · MathOptInterface

Variables

Functions

MathOptInterface.add_variablesFunction
add_variables(model::ModelLike, n::Int)::Vector{VariableIndex}

Add n scalar variables to the model, returning a vector of variable indices.

A AddVariableNotAllowed error is thrown if adding variables cannot be done in the current state of the model model.

source
MathOptInterface.add_constrained_variableFunction
add_constrained_variable(
+    model::ModelLike,
+    set::AbstractScalarSet
+)::Tuple{MOI.VariableIndex,
+         MOI.ConstraintIndex{MOI.VariableIndex, typeof(set)}}

Add to model a scalar variable constrained to belong to set, returning the index of the variable created and the index of the constraint constraining the variable to belong to set.

By default, this function falls back to creating a free variable with add_variable and then constraining it to belong to set with add_constraint.

source
MathOptInterface.add_constrained_variablesFunction
add_constrained_variables(
+    model::ModelLike,
+    sets::AbstractVector{<:AbstractScalarSet}
+)::Tuple{
+    Vector{MOI.VariableIndex},
+    Vector{MOI.ConstraintIndex{MOI.VariableIndex,eltype(sets)}},
+}

Add to model scalar variables constrained to belong to sets, returning the indices of the variables created and the indices of the constraints constraining the variables to belong to each set in sets. That is, if it returns variables and constraints, constraints[i] is the index of the constraint constraining variable[i] to belong to sets[i].

By default, this function falls back to calling add_constrained_variable on each set.

source
add_constrained_variables(
+    model::ModelLike,
+    set::AbstractVectorSet,
+)::Tuple{
+    Vector{MOI.VariableIndex},
+    MOI.ConstraintIndex{MOI.VectorOfVariables,typeof(set)},
+}

Add to model a vector of variables constrained to belong to set, returning the indices of the variables created and the index of the constraint constraining the vector of variables to belong to set.

By default, this function falls back to creating free variables with add_variables and then constraining it to belong to set with add_constraint.

source
MathOptInterface.supports_add_constrained_variableFunction
supports_add_constrained_variable(
+    model::ModelLike,
+    S::Type{<:AbstractScalarSet}
+)::Bool

Return a Bool indicating whether model supports constraining a variable to belong to a set of type S either on creation of the variable with add_constrained_variable or after the variable is created with add_constraint.

By default, this function falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VariableIndex, S) which is the correct definition for most models.

Example

Suppose that a solver supports only two kind of variables: binary variables and continuous variables with a lower bound. If the solver decides not to support VariableIndex-in-Binary and VariableIndex-in-GreaterThan constraints, it only has to implement add_constrained_variable for these two sets which prevents the user to add both a binary constraint and a lower bound on the same variable. Moreover, if the user adds a VariableIndex-in-GreaterThan constraint, implementing this interface (i.e., supports_add_constrained_variables) enables the constraint to be transparently bridged into a supported constraint.

source
MathOptInterface.supports_add_constrained_variablesFunction
supports_add_constrained_variables(
+    model::ModelLike,
+    S::Type{<:AbstractVectorSet}
+)::Bool

Return a Bool indicating whether model supports constraining a vector of variables to belong to a set of type S either on creation of the vector of variables with add_constrained_variables or after the variable is created with add_constraint.

By default, if S is Reals then this function returns true and otherwise, it falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VectorOfVariables, S) which is the correct definition for most models.

Example

In the standard conic form (see Duality), the variables are grouped into several cones and the constraints are affine equality constraints. If Reals is not one of the cones supported by the solvers then it needs to implement supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false as free variables are not supported. The solvers should then implement supports_add_constrained_variables(::Optimizer, ::Type{<:SupportedCones}) = true where SupportedCones is the union of all cone types that are supported; it does not have to implement the method supports_constraint(::Type{VectorOfVariables}, Type{<:SupportedCones}) as it should return false and it's the default. This prevents the user to constrain the same variable in two different cones. When a VectorOfVariables-in-S is added, the variables of the vector have already been created so they already belong to given cones. If bridges are enabled, the constraint will therefore be bridged by adding slack variables in S and equality constraints ensuring that the slack variables are equal to the corresponding variables of the given constraint function.

Note that there may also be sets for which !supports_add_constrained_variables(model, S) and supports_constraint(model, MOI.VectorOfVariables, S). For instance, suppose a solver supports positive semidefinite variable constraints and two types of variables: binary variables and nonnegative variables. Then the solver should support adding VectorOfVariables-in-PositiveSemidefiniteConeTriangle constraints, but it should not support creating variables constrained to belong to the PositiveSemidefiniteConeTriangle because the variables in PositiveSemidefiniteConeTriangle should first be created as either binary or non-negative.

source
MathOptInterface.is_validMethod
is_valid(model::ModelLike, index::Index)::Bool

Return a Bool indicating whether this index refers to a valid object in the model model.

source
MathOptInterface.deleteMethod
delete(model::ModelLike, index::Index)

Delete the referenced object from the model. Throw DeleteNotAllowed if if index cannot be deleted.

The following modifications also take effect if Index is VariableIndex:

  • If index used in the objective function, it is removed from the function, i.e., it is substituted for zero.
  • For each func-in-set constraint of the model:
    • If func isa VariableIndex and func == index then the constraint is deleted.
    • If func isa VectorOfVariables and index in func.variables then
      • if length(func.variables) == 1 is one, the constraint is deleted;
      • if length(func.variables) > 1 and supports_dimension_update(set) then then the variable is removed from func and set is replaced by update_dimension(set, MOI.dimension(set) - 1).
      • Otherwise, a DeleteNotAllowed error is thrown.
    • Otherwise, the variable is removed from func, i.e., it is substituted for zero.
source
MathOptInterface.deleteMethod
delete(model::ModelLike, indices::Vector{R<:Index}) where {R}

Delete the referenced objects in the vector indices from the model. It may be assumed that R is a concrete type. The default fallback sequentially deletes the individual items in indices, although specialized implementations may be more efficient.

source

Attributes

MathOptInterface.VariableNameType
VariableName()

A variable attribute for a string identifying the variable. It is valid for two variables to have the same name; however, variables with duplicate names cannot be looked up using get. It has a default value of "" if not set`.

source
MathOptInterface.VariablePrimalStartType
VariablePrimalStart()

A variable attribute for the initial assignment to some primal variable's value that the optimizer may use to warm-start the solve. May be a number or nothing (unset).

source
MathOptInterface.VariablePrimalType
VariablePrimal(result_index::Int = 1)

A variable attribute for the assignment to some primal variable's value in result result_index. If result_index is omitted, it is 1 by default.

If the solver does not have a primal value for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the VariablePrimal attribute.

See ResultCount for information on how the results are ordered.

source
MathOptInterface.VariableBasisStatusType
VariableBasisStatus(result_index::Int = 1)

A variable attribute for the BasisStatusCode of a variable in result result_index, with respect to an available optimal solution basis.

If the solver does not have a basis statue for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the VariableBasisStatus attribute.

See ResultCount for information on how the results are ordered.

source
diff --git a/previews/PR2274/release_notes/index.html b/previews/PR2274/release_notes/index.html new file mode 100644 index 0000000000..c8e29cd440 --- /dev/null +++ b/previews/PR2274/release_notes/index.html @@ -0,0 +1,30 @@ + +Release notes · MathOptInterface

Release notes

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

v1.20.0 (September 7, 2023)

Added

Other

v1.19.0 (August 15, 2023)

Added

Fixed

Other

  • Added extensions to solver-tests.yml (#2229)
  • Refactored test/Benchmarks (#2234)
  • Fixed warnings in tests (#2241) (#2243)
  • Small refactoring of bridges for upcoming VectorNonlinearFunction (#2244) (#2245)
  • Fixed various typos (#2251) (#2255)
  • Partitioned how we run the tests on GitHub actions (#2252) (#2253)

v1.18.0 (June 23, 2023)

Added

Fixed

  • Fixed a missing @require in MOI.Test (#2195) (#2196)
  • Fixed incorrect usage of Utilities.operate! in bridges (#2207) (#2216)
  • Fixed splatting nonlinear expression with univariate operator (#2221)

Other

  • Removed unused argument names (#2199)
  • Reduced memory requirement for tests (#2204)
  • Refactored Utilities.promote_operation (#2206)
  • Improved code style in Utilities/mutable_arithmetics.jl (#2209)
  • Refactored various methods in Utilities/functions.jl (#2208) (#2212) (#2213) (#2214) (#2215)

v1.17.1 (June 6, 2023)

Fixed

Other

  • Added documentation for enum instances (#2186)
  • Updated chatroom links in documentation (#2188)
  • Changed the documentation to build on Julia v1.9 (#2191)

v1.17.0 (June 1, 2023)

Added

Fixed

  • Fixed support for external sets in Utilities.loadfromstring! (#2177)
  • Fixed promote_operation for ScalarNonlinearFunction (#2179)
  • Fixed two issues in FileFormats.LP when reading files with quadratic functions (#2182) (#2184)

v1.16.0 (May 16, 2023)

Added

Fixed

Other

  • Fixed solver-tests.yml (#2157)
  • Updated documentation links to developer chatroom (#2160)
  • Added various tests for bridges (#2156)
  • Added checklists to the developer documentation (#2167) (#2168)

v1.15.1 (April 25, 2023)

Fixed

  • Fixed deleting a variable in a bridged objective (#2150)

v1.15.0 (April 19, 2023)

Added

Fixed

Other

  • Add a test for variables in one-sided open Interval sets (#2133)
  • Minor style fixes in the source code (#2148)

v1.14.1 (April 6, 2023)

Fixed

Other

v1.14.0 (April 4, 2023)

Added

Fixed

v1.13.2 (March 21, 2023)

Fixed

Other

  • Fixed typos in the documentation (#2114)
  • Functions now print to the REPL in algebraic form. This is potentially breaking if you have tests which rely on a specific String form of MOI functions. (#2112) (#2126)

v1.13.1 (March 3, 2023)

Other

  • Added the Google style guide to the documentation linter Vale, and fixed the resulting warnings (#2110)
  • Improved the docstrings in src/functions.jl (#2108)

v1.13.0 (February 28, 2023)

Added

Fixed

Other

  • Added tests for vector-valued objective functions in FileFormats.MOF (#2093)
  • Used and documented preference for import MathOptInterface as MOI (#2096)
  • Fix and test links in the documentation with linkcheck = true (#2098)
  • Improved docstrings of sets in src/sets.jl (#2099)
  • Skip checking flakey links in documentation with linkcheck_ignore (#2103)

v1.12.0 (February 10, 2023)

Added

Fixed

  • Fixed a number of constraint bridges so that Bridges.final_touch can be called multiple times without forcing a rebuild of the reformulation (#2089)

Other

v1.11.5 (January 24, 2023)

Fixed

  • Fixed a bug writing .lp files with an off-diagonal quadratic objective (#2082)

Other

  • Added SnoopPrecompile directives for reduced time-to-first-X in Julia v1.9 (#2080)

v1.11.4 (January 12, 2023)

Fixed

  • Fixed a bug reading .lp files with an Integer section (#2078)

v1.11.3 (January 12, 2023)

Fixed

  • Fixed a performance bug when deleting a vector of constraints (#2072)
  • Fixed a bug reading .lp files with terms like x -1 y (#2076)

Other

v1.11.2 (January 2, 2023)

Fixed

  • Fixed a bug reading .mof.json files with ConstraintName set for VariableIndex constraints (#2066)
  • Fixed a bug reading .mof.json files with nonlinear objectives and no constraints (#2068)

v1.11.1 (December 22, 2022)

Fixed

  • Fixed a bug reading .mof.json files with integer coefficients for affine and quadratic functions (#2063)

v1.11.0 (December 2, 2022)

Added

Other

  • Tidied these release notes (#2055)

v1.10.0 (November 22, 2022)

Added

Fixed

  • Fixed Bridges.Objective.SlackBridge when the objective function is complex-valued (#2036) (#2038)
  • Fixed docstring of Test.runtests to clarify the warn_unsupported argument (#2037)
  • Fixed reading of free variables in FileFormats.LP (#2044)
  • Fixed numerous edge cases reading files from QPLIB using FileFormats.LP (#2042) (#2044)
  • Fixed situations in which x^y returns a complex value in Nonlinear (#2050)

Other

  • Improved the error message thrown when a user-defined nonlinear function does not accept splatted input (#2032)
  • Removed specialized iterators for keys and values in Utilities.CleverDicts (#2051)

v1.9.0 (October 29, 2022)

Added

Fixed

  • Fixed Constraint.ZeroOneBridge by adding new bounds as affine constraints instead of variable bounds (#1879)
  • Fixed reading free rows in FileFormats.MPS files (#2009)
  • Fixed parsing of OBJSENSE blocks in FileFormats.MPS files (#2016) (#2019)
  • Fixed the parsing of deeply nested nonlinear expressions by removing the use of recursion (#2020)
  • Fixed the requirements check in Test.test_constrainnt_get_ConstraintIndex (#2024)

v1.8.2 (September 20, 2022)

Documentation

  • Added vale as a documentation linter (#2002)
  • Improved styling of code blocks in the PDF (#1999) (#2000)
  • Fixed a number of typos in the documentation (#2001) (#2003)

v1.8.1 (September 12, 2022)

Fixed

  • Fixed a bug in supports(::AbstractBridgeOptimizer for constraint attributes (#1991) (#1992)

v1.8.0 (September 1, 2022)

Added

Fixed

  • Lazily construct expressions in Nonlinear so that expressions are updated when Nonlinear.Parameter values are updated (#1984)
  • Allow NORM_LIMIT as a TerminationStatus for unbounded problems in Test (#1990)

v1.7.0 (August 16, 2022)

Added

Fixed

  • Fixed some missing promotion rules

Other

  • Improved the performance of Jacobian products in Nonlinear
  • Removed an un-needed copy in Utilities.modify_function
  • Various clean-ups in Bridges/bridge_optimizer.jl

v1.6.1 (July 23, 2022)

Fixed

  • Added support for ExponentialCone in MatrixOfConstraints
  • Fix PSDSquare_3 test to reflect a previously fixed bug getting the ConstraintDual of a PositiveSemidefiniteConeSquare constraint

v1.6.0 (July 2, 2022)

Added

  • Added Bridges.needs_final_touch and Bridges.final_touch
  • Added new bridges from constraint programming sets to mixed-integer linear programs:
    • AllDifferentToCountDistinctBridge
    • CountAtLeastToCountBelongsBridge
    • CountBelongsToMILPBridge
    • CountDistinctToMILPBridge
    • CountGreaterThanToMILPBridge
    • CircuitToMILPBridge

Fixed

  • Relax an instance of ::Vector to ::AbstractVector in MOI.Nonlinear
  • Fix BinPackingToMILPBridge to respect variable bounds
  • Fix SemiToBinaryBridge to throw error if other bounds are set

v1.5.0 (June 27, 2022)

Added

  • Added GetAttributeNotAllowed for solvers to indicate when getting an attribute encounters an error
  • Added Utilities.get_fallback support for ObjectiveValue and DualObjectiveValue
  • Added new bridges:
    • RootDetConeSquare to RootDetConeTriangle
    • LogDetConeSquare to LogDetConeTriangle
    • BinPacking to a mixed-integer linear program
    • Table to a mixed-integer linear program
  • Added Bridges.print_active_bridges to display the current optimal hyper-path in a Bridges.LazyBridgeOptimizer

Fixed

  • Fixed ZeroOne tests with lower and upper bounds
  • Fixed error in FileFormats.LP when reading a malformed file
  • Fixed reading of nonlinear programs in FileFormats.MOF
  • Fixed bug in ConstraintDual when using SquareBridge

Other

  • Improved documentation of nonlinear API
  • Documented duality convention for PositiveSemidefiniteConeSquare sets
  • Fixed typo in Bridges.Constraint.QuadToSOCBridge docstring

v1.4.0 (June 9, 2022)

Added

  • Added a number of sets for constraint programming:
    • AllDifferent
    • BinPacking
    • Circuit
    • CountAtLeast
    • CountBelongs
    • CountDistinct
    • CountGreaterThan
    • Cumulative
    • Path
    • Table
  • Added support for user-defined hessians in Nonlinear
  • Added Bridges.runtests to simplify the testing of bridge implementations

Fixed

  • Fixed a bug in FileFormats.NL when writing univariate *

Other

  • Began a large refactoring of the Bridges submodule, with greatly improved documentation.

v1.3.0 (May 27, 2022)

Added

  • Add MOI.Nonlinear submodule. This is a large new submodule that has been refactored from code that was in JuMP. For now, it should be considered experimental.
  • Add FileFormats.NL.SolFileResults(::IO, ::Model)
  • Add FileFormats.NL.read!(::IO, ::Model)
  • Add MOI.modify that accepts a vector of modifications

Fixed

  • Fixed a bug in Test which attempted to include non-.jl files
  • Fixed a bug in FileFormats for models with open interval constraints

Other

  • Fixed a performance issue in Utilities.DoubleDict
  • Various minor improvements to the documentation

v1.2.0 (April 25, 2022)

Added

  • Add support for the FORMAT_REW/.rew file format in FileFormats.

Fixed

  • Fix bug handling of default variable bounds in FileFormats.LP
  • Fix FileFormats.MPS to not write OBJSENSE by default since this is only supported by some readers.

v1.1.2 (March 31, 2022)

Fixed

  • Fix a range of bugs in FileFormats.LP
  • Fix reading of problem dimensions in FileFormats.SDPA

v1.1.1 (March 23, 2022)

Fixed

  • Fix bug in test_model_UpperBoundAlreadySet
  • Fix bug in test_infeasible_ tests
  • Fix bug in test_objective_ObjectiveFunction_blank
  • Relax restriction of MOI.AbstractOptimizer to MOI.ModelLike in Utilities.CachingOptimizer and instantiate.

New tests

  • Add test_conic_empty_matrix that checks conic solvers support problems with no variables.

v1.1.0 (March 2, 2022)

Added

  • Added MOI.Utilities.throw_unsupported(::UniversalFallback) for simplifying solver wrappers which copy from a UniversalFallback.

v1.0.2 (March 1, 2022)

Fixed

  • Fixed a bug in the test_model_ScalarFunctionConstantNotZero test
  • Fixed the error type when an AbstractFunctionConversionBridge cannot get or set an attribute
  • Identified a correctness bug in RSOCtoPSDBridge. We now thrown an error instead of returning an incorrect result.

v1.0.1 (February 25, 2022)

Fixed

  • Fixed a bug in which OptimizerAttributes were not copied in CachingOptimizer
  • Fixed a bug in which shift_constant did not promote mixed types of coefficients
  • Fixed a bug in which deleting a constraint of a bridged variable threw ErrorException instead of MOI.DeleteNotAllowed
  • Fixed a bug in which add_constraint in MatrixOfConstraints did not canonicalize the function
  • Fixed a bug when modifying scalar constants of a function containing a bridged variable
  • Fixed a bug in which final_touch was not always called with a CachingOptimizer

v1.0.0 (February 17, 2022)

Although tagged as a breaking release, v1.0.0 is v0.10.9 with deprecations removed, similar to how Julia 1.0 was Julia 0.7 with deprecations removed.

Breaking

  • Julia 1.6 is now the minimum supported version
  • All deprecations have been removed

Troubleshooting problems when updating

If you experience problems when updating, you are likely using previously deprecated features. (By default, Julia does not warn when you use deprecated features.)

To find the deprecated features you are using, start Julia with --depwarn=yes:

$ julia --depwarn=yes

Then install MathOptInterface v0.10.9:

julia> using Pkg
+julia> pkg"add MathOptInterface@0.10"

And then run your code. Apply any suggestions, or search the release notes below for advice on updating a specific deprecated feature.

v0.10.9 (February 16, 2022)

Added

  • Added MOI.Utilities.FreeVariables as a new VariablesConstrainer for conic solvers
  • Added MOI.default_cache for specifying the model used in CachingOptimizer

Fixed

  • Fixed LaTeX printing of MOI.Interval sets

Other

  • Added Aqua.jl as a CI check, and fixed suggested issues
  • The constructors of GeoMeanBridge, StructOfConstraints, and CachingOptimizer were changed from outer to inner constructors. This change is technically breaking, but does not impact users who followed the documented API.

v0.10.8 (February 3, 2022)

Added

  • Added a Base.read! for FileFormats.LP.

Fixed

  • Fixed a bug in MutableSparseMatrix
  • Fixed a bug when calling operate!(vcat, ...) with Number arguments
  • Removed unintended export of deprecated symbols
  • Fixed a bug with PowerCone and DualPowerCone in MatrixOfConstraints.

v0.10.7 (January 5, 2022)

Added

  • Added test for modifying the constant vector in a VectorAffineFunction-in-Zeros constraint.

Fixed

  • Fixed the order in which sets are added to a LazyBridgeOptimizer. Compared to v0.10.6, this may result in bridged models being created with a different number (and order) of variables and constraints. However, it was necessary to fix cases which were previously rejected as unsupported, even though there was a valid bridge transformation.
  • Fixed an error message in FileFormats.CBF
  • Fixed comparison in test_linear_integration_Interval
  • Fixed errors for ConstraintPrimal in a CachingOptimizer
  • Fixed printing of models with non-Float64 coefficients.

Other

  • Various improvements to reduce time-to-first-solve latency
  • Improved error message when an optimizer does not support compute_conflict!

v0.10.6 (November 30, 2021)

Added

  • Added new documentation and tests for infeasibility certificates
  • Added a version control system for the tests in MOI.Test.runtests. Pass exclude_tests_after = v"0.10.5" to run tests added in v0.10.5 and earlier.
  • MOI.Test.runtests now supports generic number types. To specify the number type T, pass MOI.Test.Config(T).
  • Added infeasible_status to MOI.Test.Config for solvers which return LOCALLY_INFEASIBLE
  • CachingOptimizers now use a fallback for ConstraintPrimal. This should enable solvers using a CachingOptimizer to pass tests requiring ConstraintPrimal.

Fixed

  • Fixed a StackOverflow bug in copy_to
  • Fixed error thrown when nonconvex quadratic constraints cannot be bridged
  • Fixed a bug in copy_to for FileFormats.NL.Model
  • Fixed a bug in FileFormats.NL when printing large integers
  • Remove a common test failure for LowerBoundAlreadySet tests
  • Utilities.num_rows is now exported
  • Remove parts of failing test_model_copy_to_xxx tests due to bridges

v0.10.5 (November 7, 2021)

Fixed

  • Fixed getter in UniversalFallback
  • Fixed test_solve_conflict_zeroone_ii

Other

  • Make normalize_and_add_constraint more flexible
  • Update paper BibTeX

v0.10.4 (October 26, 2021)

Added

  • Add SolverVersion attribute
  • Add new tests:
    • test_solve_conflict_zeroone_ii
    • test_nonlinear_objective
  • Utilities.VariablesContainer now supports ConstraintFunction and ConstraintSet
  • The documentation is now available as a PDF

Other

  • Update to MutableArithmetics 0.3
  • Various improvements to the documentation

v0.10.3 (September 18, 2021)

Fixed

  • Fixed bug which prevented callbacks from working through a CachingOptimizer
  • Fixed bug in Test submodule

v0.10.2 (September 16, 2021)

  • Updated MathOptFormat to v1.0
  • Updated JSONSchema to v1.0
  • Added Utilities.set_with_dimension
  • Added two-argument optimize!(::AbstractOptimizer, ::ModelLike)
  • The experimental feature copy_to_and_optimize! has been removed
  • Det bridges now support getting ConstraintFunction and ConstraintSet
  • Various minor bug fixes identified by improved testing

v0.10.1 (September 8, 2021)

  • Various fixes to MOI.Test

v0.10.0 (September 6, 2021)

MOI v0.10 is a significant breaking release. There are a large number of user-visible breaking changes and code refactors, as well as a substantial number of new features.

Breaking in MOI

  • SingleVariable has been removed; use VariableIndex instead
  • SingleVariableConstraintNameError has been renamed to VariableIndexConstraintNameError
  • SettingSingleVariableFunctionNotAllowed has been renamed to SettingVariableIndexFunctionNotAllowed
  • VariableIndex constraints should not support ConstraintName
  • VariableIndex constraints should not support ConstraintBasisStatus; implement VariableBasisStatus instead
  • ListOfConstraints has been renamed to ListOfConstraintTypesPresent
  • ListOfConstraintTypesPresent should now return Tuple{Type,Type} instead of Tuple{DataType,DataType}
  • SolveTime has been renamed to SolveTimeSec
  • IndicatorSet has been renamed to Indicator
  • RawParameter has been renamed to RawOptimizerAttribute and now takes String instead of Any as the only argument
  • The .N field in result attributes has been renamed to .result_index
  • The .variable_index field in ScalarAffineTerm has been renamed to .variable
  • The .variable_index_1 field in ScalarQuadraticTerm has been renamed to .variable_1
  • The .variable_index_2 field in ScalarQuadraticTerm has been renamed to .variable_2
  • The order of affine_terms and quadratic_terms in ScalarQuadraticFunction and VectorQuadraticFunction have been reversed. Both functions now accept quadratic, affine, and constant terms in that order.
  • The index_value function has been removed. Use .value instead.
  • isapprox has been removed for SOS1 and SOS2.
  • The dimension argument to Complements(dimension::Int) should now be the length of the corresponding function, instead of half the length. An ArgumentError is thrown if dimension is not even.
  • copy_to no longer takes keyword arguments:
    • copy_names: now copy names if they are supported by the destination solver
    • filter_constraints: use Utilities.ModelFilter instead
    • warn_attributes: never warn about optimizer attributes

Breaking in Bridges

  • Constraint.RSOCBridge has been renamed to Constraint.RSOCtoSOCBridge
  • Constraint.SOCRBridge has been renamed to Constraint.SOCtoRSOCBridge
  • Bridges now return vectors that can be modified by the user. Previously, some bridges returned views instead of copies.
  • Bridges.IndexInVector has been unified into a single type. Previously, there was a different type for each submodule within Bridges
  • The signature of indicator bridges has been fixed. Use MOI.Bridges.Constraint.IndicatortoSOS1{Float64}(model).

Breaking in FileFormats

  • FileFormats.MOF.Model no longer accepts validate argument. Use the JSONSchema package to validate the MOF file. See the documentation for more information.

Breaking in Utilities

  • The datastructure of Utilities.Model (and models created with Utilities.@model) has been significantly refactored in a breaking way. This includes the way that objective functions and variable-related information is stored.
  • Utilities.supports_default_copy has been renamed to supports_incremental_interface
  • Utilities.automatic_copy_to has been renamed to Utilities.default_copy_to
  • The allocate-load API has been removed
  • CachingOptimizers are now initialized as EMPTY_OPTIMIZER instead of ATTACHED_OPTIMIZER. If your code relies on the optimizer being attached, call MOIU.attach_optimizer(model) after creation.
  • The field names of Utilities.IndexMap have been renamed to var_map and con_map. Accessing these fields directly is considered a private detail that may change. Use the public getindex and setindex! API instead.
  • The size argument to Utilities.CleverDicts.CleverDict(::Integer) has been removed.
  • The size argument to Utilities.IndexMap(::Integer) has been removed.
  • Utilities.DoubleDicts have been significantly refactored. Consult the source code for details.
  • Utilities.test_models_equal has been moved to MOI.Test

Breaking in Test

  • MOI.Test has been renamed to MOI.DeprecatedTest
  • An entirely new MOI.Test submodule has been written. See the documentation for details. The new MOI.Test submodule may find many bugs in the implementations of existing solvers that were previously untested.

Other changes:

  • attribute_value_type has been added
  • copy_to_and_optimize! has been added
  • VariableBasisStatus has been added
  • print(model) now prints a human-readable description of the model
  • Various improvements to the FileFormats submodule
    • FileFormats.CBF was refactored and received bugfixes
    • Support for MathOptFormat v0.6 was added in FileFormats.MOF
    • FileFormats.MPS has had bugfixes and support for more features such as OBJSENSE and objective constants.
    • FileFormats.NL has been added to support nonlinear files
  • Improved type inference throughout to reduce latency

Updating

A helpful script when updating is:

for (root, dirs, files) in walkdir(".")
+    for file in files
+        if !endswith(file, ".jl")
+            continue
+        end
+        path = joinpath(root, file)
+        s = read(path, String)
+        for pair in [
+            ".variable_index" => ".variable",
+            "RawParameter" => "RawOptimizerAttribute",
+            "ListOfConstraints" => "ListOfConstraintTypesPresent",
+            "TestConfig" => "Config",
+            "attr.N" => "attr.result_index",
+            "SolveTime" => "SolveTimeSec",
+            "DataType" => "Type",
+            "Utilities.supports_default_copy_to" =>
+                "supports_incremental_interface",
+            "SingleVariableConstraintNameError" =>
+                "VariableIndexConstraintNameError",
+            "SettingSingleVariableFunctionNotAllowed" =>
+                "SettingVariableIndexFunctionNotAllowed",
+            "automatic_copy_to" => "default_copy_to",
+        ]
+            s = replace(s, pair)
+        end
+        write(path, s)
+    end
+end

v0.9.22 (May 22, 2021)

This release contains backports from the ongoing development of the v0.10 release.

  • Improved type inference in Utilities, Bridges and FileFormats submodules to reduce latency.
  • Improved performance of Utilities.is_canonical.
  • Fixed Utilities.pass_nonvariable_constraints with bridged variables.
  • Fixed performance regression of Utilities.Model.
  • Fixed ordering of objective setting in parser.

v0.9.21 (April 23, 2021)

  • Added supports_shift_constant.
  • Improve performance of bridging quadratic constraints.
  • Add precompilation statements.
  • Large improvements to the documentation.
  • Fix a variety of inference issues, benefiting precompilation and reducing initial latency.
  • RawParameters are now ignored when resetting a CachingOptimizer. Previously, changing the underlying optimizer after RawParameters were set would throw an error.
  • Utilities.AbstractModel is being refactored. This may break users interacting with private fields of a model generated using @model.

v0.9.20 (February 20, 2021)

  • Improved performance of Utilities.ScalarFunctionIterator
  • Added support for compute_conflict to MOI layers
  • Added test with zero off-diagonal quadratic term in objective
  • Fixed double deletion of nested bridged SingleVariable/VectorOfVariables constraints
  • Fixed modification of un-set objective
  • Fixed function modification with duplicate terms
  • Made unit tests abort without failing if the problem class is not supported
  • Formatted code with JuliaFormatter
  • Clarified BasisStatusCode's docstring

v0.9.19 (December 1, 2020)

  • Added CallbackNodeStatus attribute
  • Added bridge from GreaterThan or LessThan to Interval
  • Added tests for infeasibility certificates and double optimize
  • Fixed support for Julia v1.6
  • Re-organized MOI docs and added documentation for adding a test

v0.9.18 (November 3, 2020)

  • Various improvements for working with complex numbers
  • Added GeoMeantoRelEntrBridge to bridge a GeometricMeanCone constraint to a relative entropy constraint

v0.9.17 (September 21, 2020)

  • Fixed CleverDict with variable of negative index value
  • Implement supports_add_constrained_variable for MockOptimizer

v0.9.16 (September 17, 2020)

  • Various fixes:
    • 32-bit support
    • CleverDict with abstract value type
    • Checks in test suite

v0.9.15 (September 14, 2020)

  • Bridges improvements:
    • (R)SOCtoNonConvexQuad bridge
    • ZeroOne bridge
    • Use supports_add_constrained_variable in LazyBridgeOptimizer
    • Exposed VariableBridgeCost and ConstraintBridgeCost attributes
    • Prioritize constraining variables on creation according to these costs
    • Refactor bridge debugging
  • Large performance improvements across all submodules
  • Lots of documentation improvements
  • FileFormats improvements:
    • Update MathOptFormat to v0.5
    • Fix supported objectives in FileFormats
  • Testing improvements:
    • Add name option for basic_constraint_test
  • Bug fixes and missing methods
    • Add length for iterators
    • Fix bug with duplicate terms
    • Fix order of LinearOfConstraintIndices

v0.9.14 (May 30, 2020)

  • Add a solver-independent interface for accessing the set of conflicting constraints an Irreducible Inconsistent Subsystem (#1056).
  • Bump JSONSchema dependency from v0.2 to v0.3 (#1090).
  • Documentation improvements:
    • Fix typos (#1054, #1060, #1061, #1064, #1069, #1070).
    • Remove the outdated recommendation for a package implementing MOI for a solver XXX to be called MathOptInterfaceXXX (#1087).
  • Utilities improvements:
    • Fix is_canonical for quadratic functions (#1081, #1089).
    • Implement add_constrained_variable[s] for CachingOptimizer so that it is added as constrained variables to the underlying optimizer (#1084).
    • Add support for custom objective functions for UniversalFallback (#1086).
    • Deterministic ordering of constraints in UniversalFallback (#1088).
  • Testing improvements:
    • Add NormOneCone/NormInfinityCone tests (#1045).
  • Bridges improvements:
    • Add bridges from Semiinteger and Semicontinuous (#1059).
    • Implement getting ConstraintSet for Variable.FlipSignBridge (#1066).
    • Fix setting ConstraintFunction for Constraint.ScalarizeBridge (#1093).
    • Fix NormOne/NormInf bridges with nonzero constants (#1045).
    • Fix StackOverflow in debug (#1063).
  • FileFormats improvements:
    • [SDPA] Implement the extension for integer variables (#1079).
    • [SDPA] Ignore comments after m and nblocks and detect dat-s extension (#1077).
    • [SDPA] No scaling of off-diagonal coefficient (#1076).
    • [SDPA] Add missing negation of constant (#1075).

v0.9.13 (March 24, 2020)

  • Added tests for Semicontinuous and Semiinteger variables (#1033).
  • Added tests for using ExprGraphs from NLP evaluators (#1043).
  • Update version compatibilities of dependencies (#1034, #1051, #1052).
  • Fixed typos in documentation (#1044).

v0.9.12 (February 28, 2020)

  • Fixed writing NLPBlock in MathOptFormat (#1037).
  • Fixed MockOptimizer for result attributes with non-one result index (#1039).
  • Updated test template with instantiate (#1032).

v0.9.11 (February 21, 2020)

  • Add an option for the model created by Utilities.@model to be a subtype of AbstractOptimizer (#1031).
  • Described dual cone in docstrings of GeoMeanCone and RelativeEntropyCone (#1018, #1028).
  • Fixed typos in documentation (#1022, #1024).
  • Fixed warning of unsupported attribute (#1027).
  • Added more rootdet/logdet conic tests (#1026).
  • Implemented ConstraintDual for Constraint.GeoMeanBridge, Constraint.RootDetBridge and Constraint.LogDetBridge and test duals in tests with GeoMeanCone and RootDetConeTriangle and LogDetConeTriangle cones (#1025, #1026).

v0.9.10 (January 31, 2020)

  • Added OptimizerWithAttributes grouping an optimizer constructor and a list of optimizer attributes (#1008).
  • Added RelativeEntropyCone with corresponding bridge into exponential cone constraints (#993).
  • Added NormSpectralCone and NormNuclearCone with corresponding bridges into positive semidefinite constraints (#976).
  • Added supports_constrained_variable(s) (#1004).
  • Added dual_set_type (#1002).
  • Added tests for vector specialized version of delete (#989, #1011).
  • Added PSD3 test (#1007).
  • Clarified dual solution of Tests.pow1v and Tests.pow1f (#1013).
  • Added support for EqualTo and Zero in Bridges.Constraint.SplitIntervalBridge (#1005).
  • Fixed Utilities.vectorize for empty vector (#1003).
  • Fixed free variables in LP writer (#1006).

v0.9.9 (December 29, 2019)

  • Incorporated MathOptFormat.jl as the FileFormats submodule. FileFormats provides readers and writers for a number of standard file formats and MOF, a file format specialized for MOI (#969).
  • Improved performance of deletion of vector of variables in MOI.Utilities.Model (#983).
  • Updated to MutableArithmetics v0.2 (#981).
  • Added MutableArithmetics.promote_operation allocation tests (#975).
  • Fixed inference issue on Julia v1.1 (#982).

v0.9.8 (December 19, 2019)

  • Implemented MutableArithmetics API (#924).
  • Fixed callbacks with CachingOptimizer (#959).
  • Fixed MOI.dimension for MOI.Complements (#948).
  • Added fallback for add_variables (#972).
  • Added is_diagonal_vectorized_index utility (#965).
  • Improved linear constraints display in manual (#963, #964).
  • Bridges improvements:
    • Added IndicatorSet to SOS1 bridge (#877).
    • Added support for starting values for Variable.VectorizeBridge (#944).
    • Fixed MOI.add_constraints with non-bridged variable constraint on bridged variable (#951).
    • Fixed corner cases and docstring of GeoMeanBridge (#961, #962, #966).
    • Fixed choice between variable or constraint bridges for constrained variables (#973).
    • Improve performance of bridge shortest path (#945, #946, #956).
    • Added docstring for test_delete_bridge (#954).
    • Added Variable bridge tests (#952).

v0.9.7 (October 30, 2019)

  • Implemented _result_index_field for NLPBlockDual (#934).
  • Fixed copy of model with starting values for vector constraints (#941).
  • Bridges improvements:
    • Improved performance of add_bridge and added has_bridge (#935).
    • Added AbstractSetMapBridge for bridges between sets S1, S2 such that there is a linear map A such that A*S1 = S2 (#933).
    • Added support for starting values for FlipSignBridge, VectorizeBridge, ScalarizeBridge, SlackBridge, SplitIntervalBridge, RSOCBridge, SOCRBridge NormInfinityBridge, SOCtoPSDBridge and RSOCtoPSDBridge (#933, #936, #937, #938, #939).

v0.9.6 (October 25, 2019)

  • Added complementarity constraints (#913).
  • Allowed ModelLike objects as value of attributes (#928).
  • Testing improvements:
    • Added dual_objective_value option to MOI.Test.TestConfig (#922).
    • Added InvalidIndex tests in basic_constraint_tests (#921).
    • Added tests for the constant term in indicator constraint (#929).
  • Bridges improvements:
    • Added support for starting values for Functionize bridges (#923).
    • Added variable indices context to variable bridges (#920).
    • Fixed a typo in printing o debug_supports (#927).

v0.9.5 (October 9, 2019)

  • Clarified PrimalStatus/DualStatus to be NO_SOLUTION if result_index is out of bounds (#912).
  • Added tolerance for checks and use ResultCount + 1 for the result_index in MOI.Test.solve_result_status (#910, #917).
  • Use 0.5 instead of 2.0 for power in PowerCone in basic_constraint_test (#916).
  • Bridges improvements:
    • Added debug utilities for unsupported variable/constraint/objective (#861).
    • Fixed deletion of variables in bridged VectorOfVariables constraints (#909).
    • Fixed result_index with objective bridges (#911).

v0.9.4 (October 2, 2019)

  • Added solver-independent MIP callbacks (#782).
  • Implements submit for Utilities.CachingOptimizer and Bridges.AbstractBridgeOptimizer (#906).
  • Added tests for result count of solution attributes (#901, #904).
  • Added NumberOfThreads attribute (#892).
  • Added Utilities.get_bounds to get the bounds on a variable (#890).
  • Added a note on duplicate coefficients in documentation (#581).
  • Added result index in ConstraintBasisStatus (#898).
  • Added extension dictionary to Utilities.Model (#884, #895).
  • Fixed deletion of constrained variables for CachingOptimizer (#905).
  • Implemented Utilities.shift_constraint for Test.UnknownScalarSet (#896).
  • Bridges improvements:
    • Added Variable.RSOCtoSOCBridge (#907).
    • Implemented MOI.get for ConstraintFunction/ConstraintSet for Bridges.Constraint.SquareBridge (#899).

v0.9.3 (September 20, 2019)

  • Fixed ambiguity detected in Julia v1.3 (#891, #893).
  • Fixed missing sets from ListOfSupportedConstraints (#880).
  • Fixed copy of VectorOfVariables constraints with duplicate indices (#886).
  • Added extension dictionary to MOIU.Model (#884).
  • Implemented MOI.get for function and set for GeoMeanBridge (#888).
  • Updated documentation for SingleVariable indices and bridges (#885).
  • Testing improvements:
    • Added more comprehensive tests for names (#882).
    • Added tests for SingleVariable duals (#883).
    • Added tests for DualExponentialCone and DualPowerCone (#873).
  • Improvements for arbitrary coefficient type:
    • Fixed == for sets with mutable fields (#887).
    • Removed some Float64 assumptions in bridges (#878).
    • Automatic selection of Constraint.[Scalar|Vector]FunctionizeBridge (#889).

v0.9.2 (September 5, 2019)

  • Implemented model printing for MOI.ModelLike and specialized it for models defined in MOI (864).
  • Generalized contlinear tests for arbitrary coefficient type (#855).
  • Fixed supports_constraint for Semiinteger and Semicontinuous and supports for ObjectiveFunction (#859).
  • Fixed Allocate-Load copy for single variable constraints (#856).
  • Bridges improvements:
    • Add objective bridges (#789).
    • Fixed Variable.RSOCtoPSDBridge for dimension 2 (#869).
    • Added Variable.SOCtoRSOCBridge (#865).
    • Added Constraint.SOCRBridge and disable MOI.Bridges.Constraint.SOCtoPSDBridge (#751).
    • Fixed added_constraint_types for Contraint.LogDetBridge and Constraint.RootDetBridge (#870).

v0.9.1 (August 22, 2019)

  • Fix support for Julia v1.2 (#834).
  • L1 and L∞ norm epigraph cones and corresponding bridges to LP were added (#818).
  • Added tests to MOI.Test.nametest (#833).
  • Fix MOI.Test.soc3test for solvers not supporting infeasibility certificates (#839).
  • Implements operate for operators * and / between vector function and constant (#837).
  • Implements show for MOI.Utilities.IndexMap (#847).
  • Fix corner cases for mapping of variables in MOI.Utilities.CachingOptimizer and substitution of variables in MOI.Bridges.AbstractBridgeOptimizer (#848).
  • Fix transformation of constant terms for MOI.Bridges.Constraint.SOCtoPSDBridge and MOI.Bridges.Constraint.RSOCtoPSDBridge (#840).

v0.9.0 (August 13, 2019)

  • Support for Julia v0.6 and v0.7 was dropped (#714, #717).
  • A MOI.Utilities.Model implementation of ModelLike, this should replace most use cases of MOI.Utilities.@model (#781).
  • add_constrained_variable and add_constrained_variables were added (#759).
  • Support for indicator constraints was added (#709, #712).
  • DualObjectiveValue attribute was added (#473).
  • RawParameter attribute was added (#733).
  • A dual_set function was added (#804).
  • A Benchmarks submodule was added to facilitate solver benchmarking (#769).
  • A submit function was added, this may for instance allow the user to submit solutions or cuts to the solver from a callback (#775).
  • The field of ObjectiveValue was renamed to result_index (#729).
  • The _constant and Utilities.getconstant function were renamed to constant
  • REDUCTION_CERTIFICATE result status was added (#734).
  • Abstract matrix sets were added (#731).
  • Testing improvements:
    • The testing guideline was updated (#728).
    • Quadratic tests were added (#697).
    • Unit tests for RawStatusString, SolveTime, Silent and SolverName were added (#726, #741).
    • A rotated second-order cone test was added (#759).
    • A power cone test was added (#768).
    • Tests for ZeroOne variables with variable bounds were added (#772).
    • An unbounded test was added (#773).
    • Existing tests had a few updates (#702, #703, #763).
  • Documentation improvements:
    • Added a section on CachingOptimizer (#777).
    • Added a section on UniversalFallback, Model and @model (#762).
    • Transition the knapsack example to a doctest with MockOptimizer (#786).
  • Utilities improvements:
    • A CleverDict utility was added for a vector that automatically transform into a dictionary once a first index is removed (#767).
    • The Utilities.constant function was renamed to Utilities.constant_vector (#740).
    • Implement optimizer attributes for CachingOptimizer (#745).
    • Rename Utilities.add_scalar_constraint to Utilities.normalize_and_add_constraint (#801).
    • operate with vcat, SingleVariable and VectorOfVariables now returns a VectorOfVariables (#616).
    • Fix a type piracy of operate (#784).
    • The load_constraint fallback signature was fixed (#760).
    • The set_dot function was extended to work with sparse arrays (#805).
  • Bridges improvements:
    • The bridges no longer store the constraint function and set before it is bridged, the bridges now have to implement ConstraintFunction and ConstraintSet if the user wants to recover them. As a consequence, the @bridge macro was removed (#722).
    • Bridge are now instantiated with a bridge_constraint function instead of using a constructor (#730).
    • Fix constraint attributes for bridges (#699).
    • Constraint bridges were moved to the Bridges/Constraint submodule so they should now inherit from MOI.Bridges.Constraint.Abstract and should implement MOI.Bridges.Constraint.concrete_bridge_type instead of MOI.Bridges.concrete_bridge_type (#756).
    • Variable bridges were added in (#759).
    • Various improvements (#746, #747).

v0.8.4 (March 13, 2019)

  • Performance improvement in default_copy_to and bridge optimizer (#696).
  • Add Silent and implement setting optimizer attributes in caching and mock optimizers (#695).
  • Add Functionize bridges (SingleVariable and VectorOfVariables) (#659).
  • Minor typo fixes (#694).

v0.8.3 (March 6, 2019)

  • Use zero constant in scalar constraint function of MOI.Test.copytest (#691).
  • Fix variable deletion with SingleVariable objective function (#690).
  • Fix LazyBridgeOptimizer with bridges that add no constraints (#689).
  • Error message improvements (#673, #685, #686, #688).
  • Documentation improvements (#682, #683, #687).
  • Basis status:
    • Remove VariableBasisStatus (#679).
    • Test ConstraintBasisStatus and implement it in bridges (#678).
  • Fix inference of NumberOfVariables and NumberOfConstraints (#677).
  • Implement division between a quadratic function and a number (#675).

v0.8.2 (February 7, 2019)

  • Add RawStatusString attribute (#629).
  • Do not set names to the optimizer but only to the cache in CachingOptimizer (#638).
  • Make scalar MOI functions act as scalars in broadcast (#646).
  • Add function utilities:
    • Implement Base.zero (#634), Base.iszero (#643), add missing arithmetic operations (#644, #645) and fix division (#648).
    • Add a vectorize function that turns a vector of ScalarAffineFunction into a VectorAffineFunction (#642).
  • Improve support for starting values:
    • Show a warning in copy when starting values are not supported instead of throwing an error (#630).
    • Fix UniversalFallback for getting an variable or constraint attribute set to no indices (#623).
    • Add a test in contlineartest with partially set VariablePrimalStart.
  • Bridges improvements:
    • Fix StackOverFlow in LazyBridgeOptimizer when there is a cycle in the graph of bridges.
    • Add Slack bridges (#610, #650).
    • Add FlipSign bridges (#658).
  • Add tests with duplicate coefficients in ScalarAffineFunction and VectorAffineFunction (#639).
  • Use tolerance to compare VariablePrimal in rotatedsoc1 test (#632).
  • Use a zero constant in ScalarAffineFunction of constraints in psdt2 (#622).

v0.8.1 (January 7, 2019)

  • Adding an NLP objective now overrides any objective set using the ObjectiveFunction attribute (#619).
  • Rename fullbridgeoptimizer into full_bridge_optimizer (#621).
  • Allow custom constraint types with full_bridge_optimizer (#617).
  • Add Vectorize bridge which transforms scalar linear constraints into vector linear constraints (#615).

v0.8.0 (December 18, 2018)

  • Rename all enum values to follow the JuMP naming guidelines for constants, for example, Optimal becomes OPTIMAL, and DualInfeasible becomes DUAL_INFEASIBLE.
  • Rename CachingOptimizer methods for style compliance.
  • Add an MOI.TerminationStatusCode called ALMOST_DUAL_INFEASIBLE.

v0.7.0 (December 13, 2018)

  • Test that MOI.TerminationStatus is MOI.OptimizeNotCalled before MOI.optimize! is called.
  • Check supports_default_copy_to in tests (#594).
  • Key pieces of information like optimality, infeasibility, etc., are now reported through TerminationStatusCode. It is typically no longer necessary to check the result statuses in addition to the termination status.
  • Add perspective dimension to log-det cone (#593).

v0.6.4 (November 27, 2018)

  • Add OptimizeNotCalled termination status (#577) and improve documentation of other statuses (#575).
  • Add a solver naming guideline (#578).
  • Make FeasibilitySense the default ObjectiveSense (#579).
  • Fix Utilities.@model and Bridges.@bridge macros for functions and sets defined outside MOI (#582).
  • Document solver-specific attributes (#580) and implement them in Utilities.CachingOptimizer (#565).

v0.6.3 (November 16, 2018)

  • Variables and constraints are now allowed to have duplicate names. An error is thrown only on lookup. This change breaks some existing tests. (#549)
  • Attributes may now be partially set (some values could be nothing). (#563)
  • Performance improvements in Utilities.Model (#549, #567, #568)
  • Fix bug in QuadtoSOC (#558).
  • New supports_default_copy_to method that optimizers should implement to control caching behavior.
  • Documentation improvements.

v0.6.2 (October 26, 2018)

  • Improve hygiene of @model macro (#544).
  • Fix bug in copy tests (#543).
  • Fix bug in UniversalFallback attribute getter (#540).
  • Allow all correct solutions for solve_blank_obj unit test (#537).
  • Add errors for Allocate-Load and bad constraints (#534).
  • [performance] Add specialized implementation of hash for VariableIndex (#533).
  • [performance] Construct the name to object dictionaries lazily in model (#535).
  • Add the QuadtoSOC bridge which transforms ScalarQuadraticFunction constraints into RotatedSecondOrderCone (#483).

v0.6.1 (September 22, 2018)

  • Enable PositiveSemidefiniteConeSquare set and quadratic functions in MOIB.fullbridgeoptimizer (#524).
  • Add warning in the bridge between PositiveSemidefiniteConeSquare and PositiveSemidefiniteConeTriangle when the matrix is almost symmetric (#522).
  • Modify MOIT.copytest to not add multiples constraints on the same variable (#521).
  • Add missing keyword argument in one of MOIU.add_scalar_constraint methods (#520).

v0.6.0 (August 30, 2018)

  • The MOIU.@model and MOIB.@bridge macros now support functions and sets defined in external modules. As a consequence, function and set names in the macro arguments need to be prefixed by module name.
  • Rename functions according to the JuMP style guide:
    • copy! with keyword arguments copynames and warnattributes -> copy_to with keyword arguments copy_names and warn_attributes;
    • set! -> set;
    • addvariable[s]! -> add_variable[s];
    • supportsconstraint -> supports_constraint;
    • addconstraint[s]! -> add_constraint[s];
    • isvalid -> is_valid;
    • isempty -> is_empty;
    • Base.delete! -> delete;
    • modify! -> modify;
    • transform! -> transform;
    • initialize! -> initialize;
    • write -> write_to_file; and
    • read! -> read_from_file.
  • Remove free! (use Base.finalize instead).
  • Add the SquarePSD bridge which transforms PositiveSemidefiniteConeTriangle constraints into PositiveSemidefiniteConeTriangle.
  • Add result fallback for ConstraintDual of variable-wise constraint, ConstraintPrimal and ObjectiveValue.
  • Add tests for ObjectiveBound.
  • Add test for empty rows in vector linear constraint.
  • Rework errors: CannotError has been renamed NotAllowedError and the distinction between UnsupportedError and NotAllowedError is now about whether the element is not supported (for example, it cannot be copied a model containing this element) or the operation is not allowed (either because it is not implemented, because it cannot be performed in the current state of the model, or because it cannot be performed for a specific index)
  • canget is removed. NoSolution is added as a result status to indicate that the solver does not have either a primal or dual solution available (See #479).

v0.5.0 (August 5, 2018)

  • Fix names with CachingOptimizer.
  • Cleanup thanks to @mohamed82008.
  • Added a universal fallback for constraints.
  • Fast utilities for function canonicalization thanks to @rdeits.
  • Renamed dimension field to side_dimension in the context of matrix-like sets.
  • New and improved tests for cases like duplicate terms and ObjectiveBound.
  • Removed cantransform, canaddconstraint, canaddvariable, canset, canmodify, and candelete functions from the API. They are replaced by a new set of errors that are thrown: Subtypes of UnsupportedError indicate unsupported operations, while subtypes of CannotError indicate operations that cannot be performed in the current state.
  • The API for copy! is updated to remove the CopyResult type.
  • Updates for the new JuMP style guide.

v0.4.1 (June 28, 2018)

  • Fixes vector function modification on 32 bits.
  • Fixes Bellman-Ford algorithm for bridges.
  • Added an NLP test with FeasibilitySense.
  • Update modification documentation.

v0.4.0 (June 23, 2018)

  • Helper constructors for VectorAffineTerm and VectorQuadraticTerm.
  • Added modify_lhs to TestConfig.
  • Additional unit tests for optimizers.
  • Added a type parameter to CachingOptimizer for the optimizer field.
  • New API for problem modification (#388)
  • Tests pass without deprecation warnings on Julia 0.7.
  • Small fixes and documentation updates.

v0.3.0 (May 25, 2018)

  • Functions have been redefined to use arrays-of-structs instead of structs-of-arrays.
  • Improvements to MockOptimizer.
  • Significant changes to Bridges.
  • New and improved unit tests.
  • Fixes for Julia 0.7.

v0.2.0 (April 24, 2018)

  • Improvements to and better coverage of Tests.
  • Documentation fixes.
  • SolverName attribute.
  • Changes to the NLP interface (new definition of variable order and arrays of structs for bound pairs and sparsity patterns).
  • Addition of NLP tests.
  • Introduction of UniversalFallback.
  • copynames keyword argument to MOI.copy!.
  • Add Bridges submodule.

v0.1.0 (February 28, 2018)

  • Initial public release.
  • The framework for MOI was developed at the JuMP-dev workshop at MIT in June 2017 as a sorely needed replacement for MathProgBase.
diff --git a/previews/PR2274/search_index.js b/previews/PR2274/search_index.js new file mode 100644 index 0000000000..e22cf1e017 --- /dev/null +++ b/previews/PR2274/search_index.js @@ -0,0 +1,3 @@ +var documenterSearchIndex = {"docs": +[{"location":"background/motivation/#Motivation","page":"Motivation","title":"Motivation","text":"","category":"section"},{"location":"background/motivation/","page":"Motivation","title":"Motivation","text":"MathOptInterface (MOI) is a replacement for MathProgBase, the first-generation abstraction layer for mathematical optimization previously used by JuMP and Convex.jl.","category":"page"},{"location":"background/motivation/","page":"Motivation","title":"Motivation","text":"To address a number of limitations of MathProgBase, MOI is designed to:","category":"page"},{"location":"background/motivation/","page":"Motivation","title":"Motivation","text":"Be simple and extensible\nunifying linear, quadratic, and conic optimization,\nseamlessly facilitating extensions to essentially arbitrary constraints and functions (for example, indicator constraints, complementarity constraints, and piecewise-linear functions)\nBe fast\nby allowing access to a solver's in-memory representation of a problem without writing intermediate files (when possible)\nby using multiple dispatch and avoiding requiring containers of non-concrete types\nAllow a solver to return multiple results (for example, a pool of solutions)\nAllow a solver to return extra arbitrary information via attributes (for example, variable- and constraint-wise membership in an irreducible inconsistent subset for infeasibility analysis)\nProvide a greatly expanded set of status codes explaining what happened during the optimization procedure\nEnable a solver to more precisely specify which problem classes it supports\nEnable both primal and dual warm starts\nEnable adding and removing both variables and constraints by indices that are not required to be consecutive\nEnable any modification that the solver supports to an existing model\nAvoid requiring the solver wrapper to store an additional copy of the problem data","category":"page"},{"location":"reference/constraints/","page":"Constraints","title":"Constraints","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/constraints/#constraints_ref","page":"Constraints","title":"Constraints","text":"","category":"section"},{"location":"reference/constraints/#Types","page":"Constraints","title":"Types","text":"","category":"section"},{"location":"reference/constraints/","page":"Constraints","title":"Constraints","text":"ConstraintIndex","category":"page"},{"location":"reference/constraints/#MathOptInterface.ConstraintIndex","page":"Constraints","title":"MathOptInterface.ConstraintIndex","text":"ConstraintIndex{F, S}\n\nA type-safe wrapper for Int64 for use in referencing F-in-S constraints in a model. The parameter F is the type of the function in the constraint, and the parameter S is the type of set in the constraint. To allow for deletion, indices need not be consecutive. Indices within a constraint type (i.e. F-in-S) must be unique, but non-unique indices across different constraint types are allowed. If F is VariableIndex then the index is equal to the index of the variable. That is for an index::ConstraintIndex{VariableIndex}, we always have\n\nindex.value == MOI.get(model, MOI.ConstraintFunction(), index).value\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#Functions","page":"Constraints","title":"Functions","text":"","category":"section"},{"location":"reference/constraints/","page":"Constraints","title":"Constraints","text":"is_valid(::ModelLike,::ConstraintIndex)\nadd_constraint\nadd_constraints\ntransform\nsupports_constraint","category":"page"},{"location":"reference/constraints/#MathOptInterface.is_valid-Tuple{MathOptInterface.ModelLike, MathOptInterface.ConstraintIndex}","page":"Constraints","title":"MathOptInterface.is_valid","text":"is_valid(model::ModelLike, index::Index)::Bool\n\nReturn a Bool indicating whether this index refers to a valid object in the model model.\n\n\n\n\n\n","category":"method"},{"location":"reference/constraints/#MathOptInterface.add_constraint","page":"Constraints","title":"MathOptInterface.add_constraint","text":"add_constraint(model::ModelLike, func::F, set::S)::ConstraintIndex{F,S} where {F,S}\n\nAdd the constraint f(x) in mathcalS where f is defined by func, and mathcalS is defined by set.\n\nadd_constraint(model::ModelLike, v::VariableIndex, set::S)::ConstraintIndex{VariableIndex,S} where {S}\nadd_constraint(model::ModelLike, vec::Vector{VariableIndex}, set::S)::ConstraintIndex{VectorOfVariables,S} where {S}\n\nAdd the constraint v in mathcalS where v is the variable (or vector of variables) referenced by v and mathcalS is defined by set.\n\nAn UnsupportedConstraint error is thrown if model does not support F-in-S constraints,\na AddConstraintNotAllowed error is thrown if it supports F-in-S constraints but it cannot add the constraint(s) in its current state and\na ScalarFunctionConstantNotZero error may be thrown if func is an AbstractScalarFunction with nonzero constant and set is EqualTo, GreaterThan, LessThan or Interval.\na LowerBoundAlreadySet error is thrown if F is a VariableIndex and a constraint was already added to this variable that sets a lower bound.\na UpperBoundAlreadySet error is thrown if F is a VariableIndex and a constraint was already added to this variable that sets an upper bound.\n\n\n\n\n\n","category":"function"},{"location":"reference/constraints/#MathOptInterface.add_constraints","page":"Constraints","title":"MathOptInterface.add_constraints","text":"add_constraints(model::ModelLike, funcs::Vector{F}, sets::Vector{S})::Vector{ConstraintIndex{F,S}} where {F,S}\n\nAdd the set of constraints specified by each function-set pair in funcs and sets. F and S should be concrete types. This call is equivalent to add_constraint.(model, funcs, sets) but may be more efficient.\n\n\n\n\n\n","category":"function"},{"location":"reference/constraints/#MathOptInterface.transform","page":"Constraints","title":"MathOptInterface.transform","text":"Transform Constraint Set\n\ntransform(model::ModelLike, c::ConstraintIndex{F,S1}, newset::S2)::ConstraintIndex{F,S2}\n\nReplace the set in constraint c with newset. The constraint index c will no longer be valid, and the function returns a new constraint index with the correct type.\n\nSolvers may only support a subset of constraint transforms that they perform efficiently (for example, changing from a LessThan to GreaterThan set). In addition, set modification (where S1 = S2) should be performed via the modify function.\n\nTypically, the user should delete the constraint and add a new one.\n\nExamples\n\nIf c is a ConstraintIndex{ScalarAffineFunction{Float64},LessThan{Float64}},\n\nc2 = transform(model, c, GreaterThan(0.0))\ntransform(model, c, LessThan(0.0)) # errors\n\n\n\n\n\n","category":"function"},{"location":"reference/constraints/#MathOptInterface.supports_constraint","page":"Constraints","title":"MathOptInterface.supports_constraint","text":"supports_constraint(\n model::ModelLike,\n ::Type{F},\n ::Type{S},\n)::Bool where {F<:AbstractFunction,S<:AbstractSet}\n\nReturn a Bool indicating whether model supports F-in-S constraints, that is, copy_to(model, src) does not throw UnsupportedConstraint when src contains F-in-S constraints. If F-in-S constraints are only not supported in specific circumstances, e.g. F-in-S constraints cannot be combined with another type of constraint, it should still return true.\n\n\n\n\n\nMOI.supports_constraint(\n BT::Type{<:AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet},\n)::Bool\n\nReturn a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.\n\nImplementation notes\n\nThis method depends only on the type of the inputs, not the runtime values.\nThere is a default fallback, so you need only implement this method for constraint types that the bridge implements.\n\n\n\n\n\n","category":"function"},{"location":"reference/constraints/#Attributes","page":"Constraints","title":"Attributes","text":"","category":"section"},{"location":"reference/constraints/","page":"Constraints","title":"Constraints","text":"AbstractConstraintAttribute\nConstraintName\nConstraintPrimalStart\nConstraintDualStart\nConstraintPrimal\nConstraintDual\nConstraintBasisStatus\nConstraintFunction\nCanonicalConstraintFunction\nConstraintSet\nBasisStatusCode\nBASIC\nNONBASIC\nNONBASIC_AT_LOWER\nNONBASIC_AT_UPPER\nSUPER_BASIC","category":"page"},{"location":"reference/constraints/#MathOptInterface.AbstractConstraintAttribute","page":"Constraints","title":"MathOptInterface.AbstractConstraintAttribute","text":"AbstractConstraintAttribute\n\nAbstract supertype for attribute objects that can be used to set or get attributes (properties) of constraints in the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintName","page":"Constraints","title":"MathOptInterface.ConstraintName","text":"ConstraintName()\n\nA constraint attribute for a string identifying the constraint.\n\nIt is valid for constraints variables to have the same name; however, constraints with duplicate names cannot be looked up using get, regardless of whether they have the same F-in-S type.\n\nConstraintName has a default value of \"\" if not set.\n\nNotes\n\nYou should not implement ConstraintName for VariableIndex constraints.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintPrimalStart","page":"Constraints","title":"MathOptInterface.ConstraintPrimalStart","text":"ConstraintPrimalStart()\n\nA constraint attribute for the initial assignment to some constraint's ConstraintPrimal that the optimizer may use to warm-start the solve.\n\nMay be nothing (unset), a number for AbstractScalarFunction, or a vector for AbstractVectorFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintDualStart","page":"Constraints","title":"MathOptInterface.ConstraintDualStart","text":"ConstraintDualStart()\n\nA constraint attribute for the initial assignment to some constraint's ConstraintDual that the optimizer may use to warm-start the solve.\n\nMay be nothing (unset), a number for AbstractScalarFunction, or a vector for AbstractVectorFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintPrimal","page":"Constraints","title":"MathOptInterface.ConstraintPrimal","text":"ConstraintPrimal(result_index::Int = 1)\n\nA constraint attribute for the assignment to some constraint's primal value(s) in result result_index.\n\nIf the constraint is f(x) in S, then in most cases the ConstraintPrimal is the value of f, evaluated at the correspondng VariablePrimal solution.\n\nHowever, some conic solvers reformulate b - Ax in S to s = b - Ax, s in S. These solvers may return the value of s for ConstraintPrimal, rather than b - Ax. (Although these are constrained by an equality constraint, due to numerical tolerances they may not be identical.)\n\nIf the solver does not have a primal value for the constraint because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ConstraintPrimal attribute.\n\nIf result_index is omitted, it is 1 by default. See ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintDual","page":"Constraints","title":"MathOptInterface.ConstraintDual","text":"ConstraintDual(result_index::Int = 1)\n\nA constraint attribute for the assignment to some constraint's dual value(s) in result result_index. If result_index is omitted, it is 1 by default.\n\nIf the solver does not have a dual value for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check DualStatus before accessing the ConstraintDual attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintBasisStatus","page":"Constraints","title":"MathOptInterface.ConstraintBasisStatus","text":"ConstraintBasisStatus(result_index::Int = 1)\n\nA constraint attribute for the BasisStatusCode of some constraint in result result_index, with respect to an available optimal solution basis. If result_index is omitted, it is 1 by default.\n\nIf the solver does not have a basis statue for the constraint because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ConstraintBasisStatus attribute.\n\nSee ResultCount for information on how the results are ordered.\n\nNotes\n\nFor the basis status of a variable, query VariableBasisStatus.\n\nConstraintBasisStatus does not apply to VariableIndex constraints. You can infer the basis status of a VariableIndex constraint by looking at the result of VariableBasisStatus.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintFunction","page":"Constraints","title":"MathOptInterface.ConstraintFunction","text":"ConstraintFunction()\n\nA constraint attribute for the AbstractFunction object used to define the constraint.\n\nIt is guaranteed to be equivalent but not necessarily identical to the function provided by the user.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.CanonicalConstraintFunction","page":"Constraints","title":"MathOptInterface.CanonicalConstraintFunction","text":"CanonicalConstraintFunction()\n\nA constraint attribute for a canonical representation of the AbstractFunction object used to define the constraint.\n\nGetting this attribute is guaranteed to return a function that is equivalent but not necessarily identical to the function provided by the user.\n\nBy default, MOI.get(model, MOI.CanonicalConstraintFunction(), ci) fallbacks to MOI.Utilities.canonical(MOI.get(model, MOI.ConstraintFunction(), ci)). However, if model knows that the constraint function is canonical then it can implement a specialized method that directly return the function without calling Utilities.canonical. Therefore, the value returned cannot be assumed to be a copy of the function stored in model. Moreover, Utilities.Model checks with Utilities.is_canonical whether the function stored internally is already canonical and if it's the case, then it returns the function stored internally instead of a copy.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintSet","page":"Constraints","title":"MathOptInterface.ConstraintSet","text":"ConstraintSet()\n\nA constraint attribute for the AbstractSet object used to define the constraint.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.BasisStatusCode","page":"Constraints","title":"MathOptInterface.BasisStatusCode","text":"BasisStatusCode\n\nAn Enum of possible values for the ConstraintBasisStatus and VariableBasisStatus attributes, explaining the status of a given element with respect to an optimal solution basis.\n\nNotes\n\nNONBASIC_AT_LOWER and NONBASIC_AT_UPPER should be used only for\n\nconstraints with the Interval set. In this case, they are necessary to distinguish which side of the constraint is active. One-sided constraints (e.g., LessThan and GreaterThan) should use NONBASIC instead of the NONBASIC_AT_* values. This restriction does not apply to VariableBasisStatus, which should return NONBASIC_AT_* regardless of whether the alternative bound exists.\n\nIn linear programs, SUPER_BASIC occurs when a variable with no bounds is not\n\nin the basis.\n\nValues\n\nPossible values are:\n\nBASIC: element is in the basis\nNONBASIC: element is not in the basis\nNONBASIC_AT_LOWER: element is not in the basis and is at its lower bound\nNONBASIC_AT_UPPER: element is not in the basis and is at its upper bound\nSUPER_BASIC: element is not in the basis but is also not at one of its bounds\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.BASIC","page":"Constraints","title":"MathOptInterface.BASIC","text":"BASIC::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nBASIC: element is in the basis\n\n\n\n\n\n","category":"constant"},{"location":"reference/constraints/#MathOptInterface.NONBASIC","page":"Constraints","title":"MathOptInterface.NONBASIC","text":"NONBASIC::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nNONBASIC: element is not in the basis\n\n\n\n\n\n","category":"constant"},{"location":"reference/constraints/#MathOptInterface.NONBASIC_AT_LOWER","page":"Constraints","title":"MathOptInterface.NONBASIC_AT_LOWER","text":"NONBASIC_AT_LOWER::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nNONBASIC_AT_LOWER: element is not in the basis and is at its lower bound\n\n\n\n\n\n","category":"constant"},{"location":"reference/constraints/#MathOptInterface.NONBASIC_AT_UPPER","page":"Constraints","title":"MathOptInterface.NONBASIC_AT_UPPER","text":"NONBASIC_AT_UPPER::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nNONBASIC_AT_UPPER: element is not in the basis and is at its upper bound\n\n\n\n\n\n","category":"constant"},{"location":"reference/constraints/#MathOptInterface.SUPER_BASIC","page":"Constraints","title":"MathOptInterface.SUPER_BASIC","text":"SUPER_BASIC::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nSUPER_BASIC: element is not in the basis but is also not at one of its bounds\n\n\n\n\n\n","category":"constant"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/implementing/#Implementing-a-solver-interface","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"This guide outlines the basic steps to implement an interface to MathOptInterface for a new solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"danger: Danger\nImplementing an interface to MathOptInterface for a new solver is a lot of work. Before starting, we recommend that you join the Developer chatroom and explain a little bit about the solver you are wrapping. If you have questions that are not answered by this guide, please ask them in the Developer chatroom so we can improve this guide.","category":"page"},{"location":"tutorials/implementing/#A-note-on-the-API","page":"Implementing a solver interface","title":"A note on the API","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The API of MathOptInterface is large and varied. In order to support the diversity of solvers and use-cases, we make heavy use of duck-typing. That is, solvers are not expected to implement the full API, nor is there a well-defined minimal subset of what must be implemented. Instead, you should implement the API as necessary to make the solver function as you require.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The main reason for using duck-typing is that solvers work in different ways and target different use-cases.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Some solvers support incremental problem construction, support modification after a solve, and have native support for things like variable names.\nOther solvers are \"one-shot\" solvers that require all of the problem data to construct and solve the problem in a single function call. They do not support modification or things like variable names.\nOther \"solvers\" are not solvers at all, but things like file readers. These may only support functions like read_from_file, and may not even support the ability to add variables or constraints directly.\nFinally, some \"solvers\" are layers which take a problem as input, transform it according to some rules, and pass the transformed problem to an inner solver.","category":"page"},{"location":"tutorials/implementing/#Preliminaries","page":"Implementing a solver interface","title":"Preliminaries","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Before starting on your wrapper, you should do some background research and make the solver accessible via Julia.","category":"page"},{"location":"tutorials/implementing/#Decide-if-MathOptInterface-is-right-for-you","page":"Implementing a solver interface","title":"Decide if MathOptInterface is right for you","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The first step in writing a wrapper is to decide whether implementing an interface is the right thing to do.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MathOptInterface is an abstraction layer for unifying constrained mathematical optimization solvers. If your solver doesn't fit in the category, for example, it implements a derivative-free algorithm for unconstrained objective functions, MathOptInterface may not be the right tool for the job.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nIf you're not sure whether you should write an interface, ask in the Developer chatroom.","category":"page"},{"location":"tutorials/implementing/#Find-a-similar-solver-already-wrapped","page":"Implementing a solver interface","title":"Find a similar solver already wrapped","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The next step is to find (if possible) a similar solver that is already wrapped. Although not strictly necessary, this will be a good place to look for inspiration when implementing your wrapper.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The JuMP documentation has a good list of solvers, along with the problem classes they support.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nIf you're not sure which solver is most similar, ask in the Developer chatroom.","category":"page"},{"location":"tutorials/implementing/#Create-a-low-level-interface","page":"Implementing a solver interface","title":"Create a low-level interface","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Before writing a MathOptInterface wrapper, you first need to be able to call the solver from Julia.","category":"page"},{"location":"tutorials/implementing/#Wrapping-solvers-written-in-Julia","page":"Implementing a solver interface","title":"Wrapping solvers written in Julia","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver is written in Julia, there's nothing to do here. Go to the next section.","category":"page"},{"location":"tutorials/implementing/#Wrapping-solvers-written-in-C","page":"Implementing a solver interface","title":"Wrapping solvers written in C","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Julia is well suited to wrapping solvers written in C.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"info: Info\nThis is not true for C++. If you have a solver written in C++, first write a C interface, then wrap the C interface.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Before writing a MathOptInterface wrapper, there are a few extra steps.","category":"page"},{"location":"tutorials/implementing/#Create-a-JLL","page":"Implementing a solver interface","title":"Create a JLL","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If the C code is publicly available under an open source license, create a JLL package via Yggdrasil. The easiest way to do this is to copy an existing solver. Good examples to follow are the COIN-OR solvers.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"warning: Warning\nBuilding the solver via Yggdrasil is non-trivial. Please ask the Developer chatroom for help.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If the code is commercial or not publicly available, the user will need to manually install the solver. See Gurobi.jl or CPLEX.jl for examples of how to structure this.","category":"page"},{"location":"tutorials/implementing/#implement_clang","page":"Implementing a solver interface","title":"Use Clang.jl to wrap the C API","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The next step is to use Clang.jl to automatically wrap the C API. The easiest way to do this is to follow an example. Good examples to follow are Cbc.jl and HiGHS.jl.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Sometimes, you will need to make manual modifications to the resulting files.","category":"page"},{"location":"tutorials/implementing/#Solvers-written-in-other-languages","page":"Implementing a solver interface","title":"Solvers written in other languages","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Ask the Developer chatroom for advice. You may be able to use one of the JuliaInterop packages to call out to the solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example, SeDuMi.jl uses MATLAB.jl to call the SeDuMi solver written in MATLAB.","category":"page"},{"location":"tutorials/implementing/#Structuring-the-package","page":"Implementing a solver interface","title":"Structuring the package","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Structure your wrapper as a Julia package. Consult the Julia documentation if you haven't done this before.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MOI solver interfaces may be in the same package as the solver itself (either the C wrapper if the solver is accessible through C, or the Julia code if the solver is written in Julia, for example), or in a separate package which depends on the solver package.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"note: Note\nThe JuMP core contributors request that you do not use \"JuMP\" in the name of your package without prior consent.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Your package should have the following structure:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"/.github\n /workflows\n ci.yml\n format_check.yml\n TagBot.yml\n/gen\n gen.jl # Code to wrap the C API\n/src\n NewSolver.jl\n /gen\n libnewsolver_api.jl\n libnewsolver_common.jl\n /MOI_wrapper\n MOI_wrapper.jl\n other_files.jl\n/test\n runtests.jl\n /MOI_wrapper\n MOI_wrapper.jl\n.gitignore\n.JuliaFormatter.toml\nREADME.md\nLICENSE.md\nProject.toml","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The /.github folder contains the scripts for GitHub actions. The easiest way to write these is to copy the ones from an existing solver.\nThe /gen and /src/gen folders are only needed if you are wrapping a solver written in C.\nThe /src/MOI_wrapper folder contains the Julia code for the MOI wrapper.\nThe /test folder contains code for testing your package. See Setup tests for more information.\nThe .JuliaFormatter.toml and .github/workflows/format_check.yml enforce code formatting using JuliaFormatter.jl. Check existing solvers or JuMP.jl for details.","category":"page"},{"location":"tutorials/implementing/#Documentation","page":"Implementing a solver interface","title":"Documentation","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Your package must include documentation explaining how to use the package. The easiest approach is to include documentation in your README.md. A more involved option is to use Documenter.jl.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Examples of packages with README-based documentation include:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Cbc.jl\nHiGHS.jl\nSCS.jl","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Examples of packages with Documenter-based documentation include:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Alpine.jl\nCOSMO.jl\nJuniper.jl","category":"page"},{"location":"tutorials/implementing/#Setup-tests","page":"Implementing a solver interface","title":"Setup tests","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The best way to implement an interface to MathOptInterface is via test-driven development.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The MOI.Test submodule contains a large test suite to help check that you have implemented things correctly.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Follow the guide How to test a solver to set up the tests for your package.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nRun the tests frequently when developing. However, at the start there is going to be a lot of errors. Start by excluding large classes of tests (for example, exclude = [\"test_basic_\", \"test_model_\"], implement any missing methods until the tests pass, then remove an exclusion and repeat.","category":"page"},{"location":"tutorials/implementing/#Initial-code","page":"Implementing a solver interface","title":"Initial code","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"By this point, you should have a package setup with tests, formatting, and access to the underlying solver. Now it's time to start writing the wrapper.","category":"page"},{"location":"tutorials/implementing/#The-Optimizer-object","page":"Implementing a solver interface","title":"The Optimizer object","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The first object to create is a subtype of AbstractOptimizer. This type is going to store everything related to the problem.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"By convention, these optimizers should not be exported and should be named PackageName.Optimizer.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"import MathOptInterface as MOI\n\nstruct Optimizer <: MOI.AbstractOptimizer\n # Fields go here\nend","category":"page"},{"location":"tutorials/implementing/#Optimizer-objects-for-C-solvers","page":"Implementing a solver interface","title":"Optimizer objects for C solvers","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"warning: Warning\nThis section is important if you wrap a solver written in C.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Wrapping a solver written in C will require the use of pointers, and for you to manually free the solver's memory when the Optimizer is garbage collected by Julia.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Never pass a pointer directly to a Julia ccall function.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Instead, store the pointer as a field in your Optimizer, and implement Base.cconvert and Base.unsafe_convert. Then you can pass Optimizer to any ccall function that expects the pointer.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In addition, make sure you implement a finalizer for each model you create.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If newsolver_createProblem() is the low-level function that creates the problem pointer in C, and newsolver_freeProblem(::Ptr{Cvoid}) is the low-level function that frees memory associated with the pointer, your Optimizer() function should look like this:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"struct Optimizer <: MOI.AbstractOptimizer\n ptr::Ptr{Cvoid}\n\n function Optimizer()\n ptr = newsolver_createProblem()\n model = Optimizer(ptr)\n finalizer(model) do m\n newsolver_freeProblem(m)\n return\n end\n return model\n end\nend\n\nBase.cconvert(::Type{Ptr{Cvoid}}, model::Optimizer) = model\nBase.unsafe_convert(::Type{Ptr{Cvoid}}, model::Optimizer) = model.ptr","category":"page"},{"location":"tutorials/implementing/#Implement-methods-for-Optimizer","page":"Implementing a solver interface","title":"Implement methods for Optimizer","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"All Optimizers must implement the following methods:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"empty!\nis_empty","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Other methods, detailed below, are optional or depend on how you implement the interface.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nFor this and all future methods, read the docstrings to understand what each method does, what it expects as input, and what it produces as output. If it isn't clear, let us know and we will improve the docstrings. It is also very helpful to look at an existing wrapper for a similar solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"You should also implement Base.show(::IO, ::Optimizer) to print a nice string when someone prints your model. For example","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function Base.show(io::IO, model::Optimizer)\n return print(io, \"NewSolver with the pointer $(model.ptr)\")\nend","category":"page"},{"location":"tutorials/implementing/#Implement-attributes","page":"Implementing a solver interface","title":"Implement attributes","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MathOptInterface uses attributes to manage different aspects of the problem.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For each attribute","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"get gets the current value of the attribute\nset sets a new value of the attribute. Not all attributes can be set. For example, the user can't modify the SolverName.\nsupports returns a Bool indicating whether the solver supports the attribute.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"info: Info\nUse attribute_value_type to check the value expected by a given attribute. You should make sure that your get function correctly infers to this type (or a subtype of it).","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Each column in the table indicates whether you need to implement the particular method for each attribute.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nSolverName Yes No No\nSolverVersion Yes No No\nRawSolver Yes No No\nName Yes Yes Yes\nSilent Yes Yes Yes\nTimeLimitSec Yes Yes Yes\nObjectiveLimit Yes Yes Yes\nRawOptimizerAttribute Yes Yes Yes\nNumberOfThreads Yes Yes Yes\nAbsoluteGapTolerance Yes Yes Yes\nRelativeGapTolerance Yes Yes Yes","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function MOI.get(model::Optimizer, ::MOI.Silent)\n return # true if MOI.Silent is set\nend\n\nfunction MOI.set(model::Optimizer, ::MOI.Silent, v::Bool)\n if v\n # Set a parameter to turn off printing\n else\n # Restore the default printing\n end\n return\nend\n\nMOI.supports(::Optimizer, ::MOI.Silent) = true","category":"page"},{"location":"tutorials/implementing/#Define-supports_constraint","page":"Implementing a solver interface","title":"Define supports_constraint","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The next step is to define which constraints and objective functions you plan to support.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For each function-set constraint pair, define supports_constraint:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function MOI.supports_constraint(\n ::Optimizer,\n ::Type{MOI.VariableIndex},\n ::Type{MOI.ZeroOne},\n)\n return true\nend","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"To make this easier, you may want to use Unions:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function MOI.supports_constraint(\n ::Optimizer,\n ::Type{MOI.VariableIndex},\n ::Type{<:Union{MOI.LessThan,MOI.GreaterThan,MOI.EqualTo}},\n)\n return true\nend","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nOnly support a constraint if your solver has native support for it.","category":"page"},{"location":"tutorials/implementing/#The-big-decision:-incremental-modification?","page":"Implementing a solver interface","title":"The big decision: incremental modification?","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Now you need to decide whether to support incremental modification or not.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Incremental modification means that the user can add variables and constraints one-by-one without needing to rebuild the entire problem, and they can modify the problem data after an optimize! call. Supporting incremental modification means implementing functions like add_variable and add_constraint.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The alternative is to accept the problem data in a single optimize! or copy_to function call. Because these functions see all of the data at once, it can typically call a more efficient function to load data into the underlying solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Good examples of solvers supporting incremental modification are MILP solvers like GLPK.jl and Gurobi.jl. Examples of non-incremental solvers are AmplNLWriter.jl and SCS.jl","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"It is possible for a solver to implement both approaches, but you should probably start with one for simplicity.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nOnly support incremental modification if your solver has native support for it.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In general, supporting incremental modification is more work, and it usually requires some extra book-keeping. However, it provides a more efficient interface to the solver if the problem is going to be resolved multiple times with small modifications. Moreover, once you've implemented incremental modification, it's usually not much extra work to add a copy_to interface. The converse is not true.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nIf this is your first time writing an interface, start with the one-shot optimize!.","category":"page"},{"location":"tutorials/implementing/#The-non-incremental-interface","page":"Implementing a solver interface","title":"The non-incremental interface","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"There are two ways to implement the non-incremental interface. The first uses a two-argument version of optimize!, the second implements copy_to followed by the one-argument version of optimize!.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver does not support modification, and requires all data to solve the problem in a single function call, you should implement the \"one-shot\" optimize!.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"optimize!(::ModelLike, ::ModelLike)","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver separates data loading and the actual optimization into separate steps, implement the copy_to interface.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"copy_to(::ModelLike, ::ModelLike)\noptimize!(::ModelLike)","category":"page"},{"location":"tutorials/implementing/#The-incremental-interface","page":"Implementing a solver interface","title":"The incremental interface","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"warning: Warning\nWriting this interface is a lot of work. The easiest way is to consult the source code of a similar solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"To implement the incremental interface, implement the following functions:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"add_variable\nadd_variables\nadd_constraint\nadd_constraints\nis_valid\ndelete\noptimize!(::ModelLike)","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"info: Info\nSolvers do not have to support AbstractScalarFunction in GreaterThan, LessThan, EqualTo, or Interval with a nonzero constant in the function. Throw ScalarFunctionConstantNotZero if the function constant is not zero.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In addition, you should implement the following model attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nListOfModelAttributesSet Yes No No\nObjectiveFunctionType Yes No No\nObjectiveFunction Yes Yes Yes\nObjectiveSense Yes Yes Yes\nName Yes Yes Yes","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Variable-related attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nListOfVariableAttributesSet Yes No No\nNumberOfVariables Yes No No\nListOfVariableIndices Yes No No","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Constraint-related attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nListOfConstraintAttributesSet Yes No No\nNumberOfConstraints Yes No No\nListOfConstraintTypesPresent Yes No No\nConstraintFunction Yes Yes No\nConstraintSet Yes Yes No","category":"page"},{"location":"tutorials/implementing/#Modifications","page":"Implementing a solver interface","title":"Modifications","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver supports modifying data in-place, implement modify for the following AbstractModifications:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ScalarConstantChange\nScalarCoefficientChange\nVectorConstantChange\nMultirowChange","category":"page"},{"location":"tutorials/implementing/#Variables-constrained-on-creation","page":"Implementing a solver interface","title":"Variables constrained on creation","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Some solvers require variables be associated with a set when they are created. This conflicts with the incremental modification approach, since you cannot first add a free variable and then constrain it to the set.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If this is the case, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"add_constrained_variable\nadd_constrained_variables\nsupports_add_constrained_variables","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"By default, MathOptInterface assumes solvers support free variables. If your solver does not support free variables, define:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MOI.supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false","category":"page"},{"location":"tutorials/implementing/#Incremental-and-copy_to","page":"Implementing a solver interface","title":"Incremental and copy_to","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If you implement the incremental interface, you have the option of also implementing copy_to.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If you don't want to implement copy_to, for example, because the solver has no API for building the problem in a single function call, define the following fallback:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MOI.supports_incremental_interface(::Optimizer) = true\n\nfunction MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)\n return MOI.Utilities.default_copy_to(dest, src)\nend","category":"page"},{"location":"tutorials/implementing/#implement_names","page":"Implementing a solver interface","title":"Names","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Regardless of which interface you implement, you have the option of implementing the Name attribute for variables and constraints:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nVariableName Yes Yes Yes\nConstraintName Yes Yes Yes","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If you implement names, you must also implement the following three methods:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function MOI.get(model::Optimizer, ::Type{MOI.VariableIndex}, name::String)\n return # The variable named `name`.\nend\n\nfunction MOI.get(model::Optimizer, ::Type{MOI.ConstraintIndex}, name::String)\n return # The constraint any type named `name`.\nend\n\nfunction MOI.get(\n model::Optimizer,\n ::Type{MOI.ConstraintIndex{F,S}},\n name::String,\n) where {F,S}\n return # The constraint of type F-in-S named `name`.\nend","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"These methods have the following rules:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If there is no variable or constraint with the name, return nothing\nIf there is a single variable or constraint with that name, return the variable or constraint\nIf there are multiple variables or constraints with the name, throw an error.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"warning: Warning\nYou should not implement ConstraintName for VariableIndex constraints. If you implement ConstraintName for other constraints, you can add the following two methods to disable ConstraintName for VariableIndex constraints.function MOI.supports(\n ::Optimizer,\n ::MOI.ConstraintName,\n ::Type{<:MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.AbstractScalarSet}},\n)\n return throw(MOI.VariableIndexConstraintNameError())\nend\nfunction MOI.set(\n ::Optimizer,\n ::MOI.ConstraintName,\n ::MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.AbstractScalarSet},\n ::String,\n)\n return throw(MOI.VariableIndexConstraintNameError())\nend","category":"page"},{"location":"tutorials/implementing/#Solutions","page":"Implementing a solver interface","title":"Solutions","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Implement optimize! to solve the model:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"optimize!","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"All Optimizers must implement the following attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"DualStatus\nPrimalStatus\nRawStatusString\nResultCount\nTerminationStatus","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"info: Info\nYou only need to implement get for solution attributes. Don't implement set or supports.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"note: Note\nSolver wrappers should document how the low-level statuses map to the MOI statuses. Statuses like NEARLY_FEASIBLE_POINT and INFEASIBLE_POINT, are designed to be used when the solver explicitly indicates that relaxed tolerances are satisfied or the returned point is infeasible, respectively.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"You should also implement the following attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ObjectiveValue\nSolveTimeSec\nVariablePrimal","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nAttributes like VariablePrimal and ObjectiveValue are indexed by the result count. Use MOI.check_result_index_bounds(model, attr) to throw an error if the attribute is not available.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver returns dual solutions, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ConstraintDual\nDualObjectiveValue","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For integer solvers, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ObjectiveBound\nRelativeGap","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If applicable, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"SimplexIterations\nBarrierIterations\nNodeCount","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver uses the Simplex method, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ConstraintBasisStatus","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver accepts primal or dual warm-starts, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"VariablePrimalStart\nConstraintDualStart","category":"page"},{"location":"tutorials/implementing/#Other-tips","page":"Implementing a solver interface","title":"Other tips","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Here are some other points to be aware of when writing your wrapper.","category":"page"},{"location":"tutorials/implementing/#Unsupported-constraints-at-runtime","page":"Implementing a solver interface","title":"Unsupported constraints at runtime","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In some cases, your solver may support a particular type of constraint (for example, quadratic constraints), but only if the data meets some condition (for example, it is convex).","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In this case, declare that you support the constraint, and throw AddConstraintNotAllowed.","category":"page"},{"location":"tutorials/implementing/#Dealing-with-multiple-variable-bounds","page":"Implementing a solver interface","title":"Dealing with multiple variable bounds","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MathOptInterface uses VariableIndex constraints to represent variable bounds. Defining multiple variable bounds on a single variable is not allowed.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Throw LowerBoundAlreadySet or UpperBoundAlreadySet if the user adds a constraint that results in multiple bounds.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Only throw if the constraints conflict. It is okay to add VariableIndex-in-GreaterThan and then VariableIndex-in-LessThan, but not VariableIndex-in-Interval and then VariableIndex-in-LessThan,","category":"page"},{"location":"tutorials/implementing/#Expect-duplicate-coefficients","page":"Implementing a solver interface","title":"Expect duplicate coefficients","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Solvers must expect that functions such as ScalarAffineFunction and VectorQuadraticFunction may contain duplicate coefficients.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example, ScalarAffineFunction([ScalarAffineTerm(x, 1), ScalarAffineTerm(x, 1)], 0.0).","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Use Utilities.canonical to return a new function with the duplicate coefficients aggregated together.","category":"page"},{"location":"tutorials/implementing/#Don't-modify-user-data","page":"Implementing a solver interface","title":"Don't modify user-data","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"All data passed to the solver must be copied immediately to internal data structures. Solvers may not modify any input vectors and must assume that input vectors will not be modified by users in the future.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"This applies, for example, to the terms vector in ScalarAffineFunction. Vectors returned to the user, for example, via ObjectiveFunction or ConstraintFunction attributes, must not be modified by the solver afterwards. The in-place version of get! can be used by users to avoid extra copies in this case.","category":"page"},{"location":"tutorials/implementing/#Column-Generation","page":"Implementing a solver interface","title":"Column Generation","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"There is no special interface for column generation. If the solver has a special API for setting coefficients in existing constraints when adding a new variable, it is possible to queue modifications and new variables and then call the solver's API once all of the new coefficients are known.","category":"page"},{"location":"tutorials/implementing/#Solver-specific-attributes","page":"Implementing a solver interface","title":"Solver-specific attributes","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"You don't need to restrict yourself to the attributes defined in the MathOptInterface.jl package.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Solver-specific attributes should be specified by creating an appropriate subtype of AbstractModelAttribute, AbstractOptimizerAttribute, AbstractVariableAttribute, or AbstractConstraintAttribute.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example, Gurobi.jl adds attributes for multiobjective optimization by defining:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"struct NumberOfObjectives <: MOI.AbstractModelAttribute end\n\nfunction MOI.set(model::Optimizer, ::NumberOfObjectives, n::Integer)\n # Code to set NumberOfObjectives\n return\nend\n\nfunction MOI.get(model::Optimizer, ::NumberOfObjectives)\n n = # Code to get NumberOfObjectives\n return n\nend","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Then, the user can write:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"model = Gurobi.Optimizer()\nMOI.set(model, Gurobi.NumberofObjectives(), 3)","category":"page"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Nonlinear/reference/#NonlinearAPI","page":"API Reference","title":"Nonlinear Modeling","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"More information can be found in the Nonlinear section of the manual.","category":"page"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear\nNonlinear.Model","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear","page":"API Reference","title":"MathOptInterface.Nonlinear","text":"Nonlinear\n\nwarning: Warning\nThe Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.\n\n\n\n\n\n","category":"module"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Model","page":"API Reference","title":"MathOptInterface.Nonlinear.Model","text":"Model()\n\nThe core datastructure for representing a nonlinear optimization problem.\n\nIt has the following fields:\n\nobjective::Union{Nothing,Expression} : holds the nonlinear objective function, if one exists, otherwise nothing.\nexpressions::Vector{Expression} : a vector of expressions in the model.\nconstraints::OrderedDict{ConstraintIndex,Constraint} : a map from ConstraintIndex to the corresponding Constraint. An OrderedDict is used instead of a Vector to support constraint deletion.\nparameters::Vector{Float64} : holds the current values of the parameters.\noperators::OperatorRegistry : stores the operators used in the model.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_expressions","page":"API Reference","title":"Expressions","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.ExpressionIndex\nNonlinear.add_expression","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ExpressionIndex","page":"API Reference","title":"MathOptInterface.Nonlinear.ExpressionIndex","text":"ExpressionIndex\n\nAn index to a nonlinear expression that is returned by add_expression.\n\nGiven data::Model and ex::ExpressionIndex, use data[ex] to retrieve the corresponding Expression.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.add_expression","page":"API Reference","title":"MathOptInterface.Nonlinear.add_expression","text":"add_expression(model::Model, expr)::ExpressionIndex\n\nParse expr into a Expression and add to model. Returns an ExpressionIndex that can be interpolated into other input expressions.\n\nexpr must be a type that is supported by parse_expression.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nex = add_expression(model, :($x^2 + 1))\nset_objective(model, :(sqrt($ex)))\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_parameters","page":"API Reference","title":"Parameters","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.ParameterIndex\nNonlinear.add_parameter","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ParameterIndex","page":"API Reference","title":"MathOptInterface.Nonlinear.ParameterIndex","text":"ParameterIndex\n\nAn index to a nonlinear parameter that is returned by add_parameter. Given data::Model and p::ParameterIndex, use data[p] to retrieve the current value of the parameter and data[p] = value to set a new value.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.add_parameter","page":"API Reference","title":"MathOptInterface.Nonlinear.add_parameter","text":"add_parameter(model::Model, value::Float64)::ParameterIndex\n\nAdd a new parameter to model with the default value value. Returns a ParameterIndex that can be interpolated into other input expressions and used to modify the value of the parameter.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\np = add_parameter(model, 1.2)\nc = add_constraint(model, :($x^2 - $p), MOI.LessThan(0.0))\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_objectives","page":"API Reference","title":"Objectives","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.set_objective","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.set_objective","page":"API Reference","title":"MathOptInterface.Nonlinear.set_objective","text":"set_objective(model::Model, obj)::Nothing\n\nParse obj into a Expression and set as the objective function of model.\n\nobj must be a type that is supported by parse_expression.\n\nTo remove the objective, pass nothing.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nset_objective(model, :($x^2 + 1))\nset_objective(model, x)\nset_objective(model, nothing)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_constraints","page":"API Reference","title":"Constraints","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.ConstraintIndex\nNonlinear.add_constraint\nNonlinear.delete","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ConstraintIndex","page":"API Reference","title":"MathOptInterface.Nonlinear.ConstraintIndex","text":"ConstraintIndex\n\nAn index to a nonlinear constraint that is returned by add_constraint.\n\nGiven data::Model and c::ConstraintIndex, use data[c] to retrieve the corresponding Constraint.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.add_constraint","page":"API Reference","title":"MathOptInterface.Nonlinear.add_constraint","text":"add_constraint(\n model::Model,\n func,\n set::Union{\n MOI.GreaterThan{Float64},\n MOI.LessThan{Float64},\n MOI.Interval{Float64},\n MOI.EqualTo{Float64},\n },\n)\n\nParse func and set into a Constraint and add to model. Returns a ConstraintIndex that can be used to delete the constraint or query solution information.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nc = add_constraint(model, :($x^2), MOI.LessThan(1.0))\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.delete","page":"API Reference","title":"MathOptInterface.Nonlinear.delete","text":"delete(model::Model, c::ConstraintIndex)::Nothing\n\nDelete the constraint index c from model.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nc = add_constraint(model, :($x^2), MOI.LessThan(1.0))\ndelete(model, c)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_operators","page":"API Reference","title":"User-defined operators","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.OperatorRegistry\nNonlinear.DEFAULT_UNIVARIATE_OPERATORS\nNonlinear.DEFAULT_MULTIVARIATE_OPERATORS\nNonlinear.register_operator\nNonlinear.register_operator_if_needed\nNonlinear.assert_registered\nNonlinear.check_return_type\nNonlinear.eval_univariate_function\nNonlinear.eval_univariate_gradient\nNonlinear.eval_univariate_hessian\nNonlinear.eval_multivariate_function\nNonlinear.eval_multivariate_gradient\nNonlinear.eval_multivariate_hessian\nNonlinear.eval_logic_function\nNonlinear.eval_comparison_function","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.OperatorRegistry","page":"API Reference","title":"MathOptInterface.Nonlinear.OperatorRegistry","text":"OperatorRegistry()\n\nCreate a new OperatorRegistry to store and evaluate univariate and multivariate operators.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS","page":"API Reference","title":"MathOptInterface.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS","text":"DEFAULT_UNIVARIATE_OPERATORS\n\nThe list of univariate operators that are supported by default.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS\n72-element Vector{Symbol}:\n :+\n :-\n :abs\n :sqrt\n :cbrt\n :abs2\n :inv\n :log\n :log10\n :log2\n ⋮\n :airybi\n :airyaiprime\n :airybiprime\n :besselj0\n :besselj1\n :bessely0\n :bessely1\n :erfcx\n :dawson\n\n\n\n\n\n","category":"constant"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS","page":"API Reference","title":"MathOptInterface.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS","text":"DEFAULT_MULTIVARIATE_OPERATORS\n\nThe list of multivariate operators that are supported by default.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS\n9-element Vector{Symbol}:\n :+\n :-\n :*\n :^\n :/\n :ifelse\n :atan\n :min\n :max\n\n\n\n\n\n","category":"constant"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.register_operator","page":"API Reference","title":"MathOptInterface.Nonlinear.register_operator","text":"register_operator(\n model::Model,\n op::Symbol,\n nargs::Int,\n f::Function,\n [∇f::Function],\n [∇²f::Function],\n)\n\nRegister the user-defined operator op with nargs input arguments in model.\n\nUnivariate functions\n\nf(x::T)::T must be a function that takes a single input argument x and returns the function evaluated at x. If ∇f and ∇²f are not provided, f must support any Real input type T.\n∇f(x::T)::T is a function that takes a single input argument x and returns the first derivative of f with respect to x. If ∇²f is not provided, ∇f must support any Real input type T.\n∇²f(x::T)::T is a function that takes a single input argument x and returns the second derivative of f with respect to x.\n\nMultivariate functions\n\nf(x::T...)::T must be a function that takes a nargs input arguments x and returns the function evaluated at x. If ∇f and ∇²f are not provided, f must support any Real input type T.\n∇f(g::AbstractVector{T}, x::T...)::T is a function that takes a cache vector g of length length(x), and fills each element g[i] with the partial derivative of f with respect to x[i].\n∇²f(H::AbstractMatrix, x::T...)::T is a function that takes a matrix H and fills the lower-triangular components H[i, j] with the Hessian of f with respect to x[i] and x[j] for i >= j.\n\nNotes for multivariate Hessians\n\nH has size(H) == (length(x), length(x)), but you must not access elements H[i, j] for i > j.\nH is dense, but you do not need to fill structural zeros.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.register_operator_if_needed","page":"API Reference","title":"MathOptInterface.Nonlinear.register_operator_if_needed","text":"register_operator_if_needed(\n registry::OperatorRegistry,\n op::Symbol,\n nargs::Int,\n f::Function;\n)\n\nSimilar to register_operator, but this function warns if the function is not registered, and skips silently if it already is.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.assert_registered","page":"API Reference","title":"MathOptInterface.Nonlinear.assert_registered","text":"assert_registered(registry::OperatorRegistry, op::Symbol, nargs::Int)\n\nThrow an error if op is not registered in registry with nargs arguments.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.check_return_type","page":"API Reference","title":"MathOptInterface.Nonlinear.check_return_type","text":"check_return_type(::Type{T}, ret::S) where {T,S}\n\nOverload this method for new types S to throw an informative error if a user-defined function returns the type S instead of T.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_univariate_function","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_univariate_function","text":"eval_univariate_function(\n registry::OperatorRegistry,\n op::Symbol,\n x::T,\n) where {T}\n\nEvaluate the operator op(x)::T, where op is a univariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_univariate_gradient","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_univariate_gradient","text":"eval_univariate_gradient(\n registry::OperatorRegistry,\n op::Symbol,\n x::T,\n) where {T}\n\nEvaluate the first-derivative of the operator op(x)::T, where op is a univariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_univariate_hessian","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_univariate_hessian","text":"eval_univariate_hessian(\n registry::OperatorRegistry,\n op::Symbol,\n x::T,\n) where {T}\n\nEvaluate the second-derivative of the operator op(x)::T, where op is a univariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_multivariate_function","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_multivariate_function","text":"eval_multivariate_function(\n registry::OperatorRegistry,\n op::Symbol,\n x::AbstractVector{T},\n) where {T}\n\nEvaluate the operator op(x)::T, where op is a multivariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_multivariate_gradient","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_multivariate_gradient","text":"eval_multivariate_gradient(\n registry::OperatorRegistry,\n op::Symbol,\n g::AbstractVector{T},\n x::AbstractVector{T},\n) where {T}\n\nEvaluate the gradient of operator g .= ∇op(x), where op is a multivariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_multivariate_hessian","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_multivariate_hessian","text":"eval_multivariate_hessian(\n registry::OperatorRegistry,\n op::Symbol,\n H::AbstractMatrix,\n x::AbstractVector{T},\n) where {T}\n\nEvaluate the Hessian of operator ∇²op(x), where op is a multivariate function in registry.\n\nThe Hessian is stored in the lower-triangular part of the matrix H.\n\nnote: Note\nImplementations of the Hessian operators will not fill structural zeros. Therefore, before calling this function you should pre-populate the matrix H with 0.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_logic_function","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_logic_function","text":"eval_logic_function(\n registry::OperatorRegistry,\n op::Symbol,\n lhs::T,\n rhs::T,\n)::Bool where {T}\n\nEvaluate (lhs op rhs)::Bool, where op is a logic operator in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_comparison_function","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_comparison_function","text":"eval_comparison_function(\n registry::OperatorRegistry,\n op::Symbol,\n lhs::T,\n rhs::T,\n)::Bool where {T}\n\nEvaluate (lhs op rhs)::Bool, where op is a comparison operator in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#Automatic-differentiation-backends","page":"API Reference","title":"Automatic-differentiation backends","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.Evaluator\nNonlinear.AbstractAutomaticDifferentiation\nNonlinear.ExprGraphOnly\nNonlinear.SparseReverseMode","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Evaluator","page":"API Reference","title":"MathOptInterface.Nonlinear.Evaluator","text":"Evaluator(\n model::Model,\n backend::AbstractAutomaticDifferentiation,\n ordered_variables::Vector{MOI.VariableIndex},\n)\n\nCreate Evaluator, a subtype of MOI.AbstractNLPEvaluator, from Model.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.AbstractAutomaticDifferentiation","page":"API Reference","title":"MathOptInterface.Nonlinear.AbstractAutomaticDifferentiation","text":"AbstractAutomaticDifferentiation\n\nAn abstract type for extending Evaluator.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ExprGraphOnly","page":"API Reference","title":"MathOptInterface.Nonlinear.ExprGraphOnly","text":"ExprGraphOnly() <: AbstractAutomaticDifferentiation\n\nThe default implementation of AbstractAutomaticDifferentiation. The only supported feature is :ExprGraph.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.SparseReverseMode","page":"API Reference","title":"MathOptInterface.Nonlinear.SparseReverseMode","text":"SparseReverseMode() <: AbstractAutomaticDifferentiation\n\nAn implementation of AbstractAutomaticDifferentiation that uses sparse reverse-mode automatic differentiation to compute derivatives. Supports all features in the MOI nonlinear interface.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#Data-structure","page":"API Reference","title":"Data-structure","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.Node\nNonlinear.NodeType\nNonlinear.Expression\nNonlinear.Constraint\nNonlinear.adjacency_matrix\nNonlinear.parse_expression\nNonlinear.convert_to_expr\nNonlinear.ordinal_index","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Node","page":"API Reference","title":"MathOptInterface.Nonlinear.Node","text":"struct Node\n type::NodeType\n index::Int\n parent::Int\nend\n\nA single node in a nonlinear expression tree. Used by Expression.\n\nSee the MathOptInterface documentation for information on how the nodes and values form an expression tree.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.NodeType","page":"API Reference","title":"MathOptInterface.Nonlinear.NodeType","text":"NodeType\n\nAn enum describing the possible node types. Each Node has a .index field, which should be interpreted as follows:\n\nNODE_CALL_MULTIVARIATE: the index into operators.multivariate_operators\nNODE_CALL_UNIVARIATE: the index into operators.univariate_operators\nNODE_LOGIC: the index into operators.logic_operators\nNODE_COMPARISON: the index into operators.comparison_operators\nNODE_MOI_VARIABLE: the value of MOI.VariableIndex(index) in the user's space of the model.\nNODE_VARIABLE: the 1-based index of the internal vector\nNODE_VALUE: the index into the .values field of Expression\nNODE_PARAMETER: the index into data.parameters\nNODE_SUBEXPRESSION: the index into data.expressions\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Expression","page":"API Reference","title":"MathOptInterface.Nonlinear.Expression","text":"struct Expression\n nodes::Vector{Node}\n values::Vector{Float64}\nend\n\nThe core type that represents a nonlinear expression. See the MathOptInterface documentation for information on how the nodes and values form an expression tree.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Constraint","page":"API Reference","title":"MathOptInterface.Nonlinear.Constraint","text":"struct Constraint\n expression::Expression\n set::Union{\n MOI.LessThan{Float64},\n MOI.GreaterThan{Float64},\n MOI.EqualTo{Float64},\n MOI.Interval{Float64},\n }\nend\n\nA type to hold information relating to the nonlinear constraint f(x) in S, where f(x) is defined by .expression, and S is .set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.adjacency_matrix","page":"API Reference","title":"MathOptInterface.Nonlinear.adjacency_matrix","text":"adjacency_matrix(nodes::Vector{Node})\n\nCompute the sparse adjacency matrix describing the parent-child relationships in nodes.\n\nThe element (i, j) is true if there is an edge from node[j] to node[i]. Since we get a column-oriented matrix, this gives us a fast way to look up the edges leaving any node (i.e., the children).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.parse_expression","page":"API Reference","title":"MathOptInterface.Nonlinear.parse_expression","text":"parse_expression(data::Model, input)::Expression\n\nParse input into a Expression.\n\n\n\n\n\nparse_expression(\n data::Model,\n expr::Expression,\n input::Any,\n parent_index::Int,\n)::Expression\n\nParse input into a Expression, and add it to expr as a child of expr.nodes[parent_index]. Existing subexpressions and parameters are stored in data.\n\nYou can extend parsing support to new types of objects by overloading this method with a different type on input::Any.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.convert_to_expr","page":"API Reference","title":"MathOptInterface.Nonlinear.convert_to_expr","text":"convert_to_expr(data::Model, expr::Expression)\n\nConvert the Expression expr into a Julia Expr.\n\nsubexpressions are represented by a ExpressionIndex object.\nparameters are represented by a ParameterIndex object.\nvariables are represennted by an MOI.VariableIndex object.\n\n\n\n\n\nconvert_to_expr(\n evaluator::Evaluator,\n expr::Expression;\n moi_output_format::Bool,\n)\n\nConvert the Expression expr into a Julia Expr.\n\nIf moi_output_format = true:\n\nsubexpressions will be converted to Julia Expr and substituted into the output expression.\nthe current value of each parameter will be interpolated into the expression\nvariables will be represented in the form x[MOI.VariableIndex(i)]\n\nIf moi_output_format = false:\n\nsubexpressions will be represented by a ExpressionIndex object.\nparameters will be represented by a ParameterIndex object.\nvariables will be represennted by an MOI.VariableIndex object.\n\nwarning: Warning\nTo use moi_output_format = true, you must have first called MOI.initialize with :ExprGraph as a requested feature.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ordinal_index","page":"API Reference","title":"MathOptInterface.Nonlinear.ordinal_index","text":"ordinal_index(evaluator::Evaluator, c::ConstraintIndex)::Int\n\nReturn the 1-indexed value of the constraint index c in evaluator.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nc1 = add_constraint(model, :($x^2), MOI.LessThan(1.0))\nc2 = add_constraint(model, :($x^2), MOI.LessThan(1.0))\nevaluator = Evaluator(model)\nMOI.initialize(evaluator, Symbol[])\nordinal_index(evaluator, c2) # Returns 2\ndelete(model, c1)\nevaluator = Evaluator(model)\nMOI.initialize(evaluator, Symbol[])\nordinal_index(model, c2) # Returns 1\n\n\n\n\n\n","category":"function"},{"location":"manual/models/","page":"Models","title":"Models","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/models/#Models","page":"Models","title":"Models","text":"","category":"section"},{"location":"manual/models/","page":"Models","title":"Models","text":"The most significant part of MOI is the definition of the model API that is used to specify an instance of an optimization problem (for example, by adding variables and constraints). Objects that implement the model API must inherit from the ModelLike abstract type.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"Notably missing from the model API is the method to solve an optimization problem. ModelLike objects may store an instance (for example, in memory or backed by a file format) without being linked to a particular solver. In addition to the model API, MOI defines AbstractOptimizer and provides methods to solve the model and interact with solutions. See the Solutions section for more details.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"info: Info\nThroughout the rest of the manual, model is used as a generic ModelLike, and optimizer is used as a generic AbstractOptimizer.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"tip: Tip\nMOI does not export functions, but for brevity we often omit qualifying names with the MOI module. Best practice is to haveimport MathOptInterface as MOIand prefix all MOI methods with MOI. in user code. If a name is also available in base Julia, we always explicitly use the module prefix, for example, with MOI.get.","category":"page"},{"location":"manual/models/#Attributes","page":"Models","title":"Attributes","text":"","category":"section"},{"location":"manual/models/","page":"Models","title":"Models","text":"Attributes are properties of the model that can be queried and modified. These include constants such as the number of variables in a model NumberOfVariables), and properties of variables and constraints such as the name of a variable (VariableName).","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"There are four types of attributes:","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"Model attributes (subtypes of AbstractModelAttribute) refer to properties of a model.\nOptimizer attributes (subtypes of AbstractOptimizerAttribute) refer to properties of an optimizer.\nConstraint attributes (subtypes of AbstractConstraintAttribute) refer to properties of an individual constraint.\nVariable attributes (subtypes of AbstractVariableAttribute) refer to properties of an individual variable.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"Some attributes are values that can be queried by the user but not modified, while other attributes can be modified by the user.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"All interactions with attributes occur through the get and set functions.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"Consult the docstrings of each attribute for information on what it represents.","category":"page"},{"location":"manual/models/#ModelLike-API","page":"Models","title":"ModelLike API","text":"","category":"section"},{"location":"manual/models/","page":"Models","title":"Models","text":"The following attributes are available:","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"ListOfConstraintAttributesSet\nListOfConstraintIndices\nListOfConstraintTypesPresent\nListOfModelAttributesSet\nListOfVariableAttributesSet\nListOfVariableIndices\nNumberOfConstraints\nNumberOfVariables\nName\nObjectiveFunction\nObjectiveFunctionType\nObjectiveSense","category":"page"},{"location":"manual/models/#AbstractOptimizer-API","page":"Models","title":"AbstractOptimizer API","text":"","category":"section"},{"location":"manual/models/","page":"Models","title":"Models","text":"The following attributes are available:","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"DualStatus\nPrimalStatus\nRawStatusString\nResultCount\nTerminationStatus\nBarrierIterations\nDualObjectiveValue\nNodeCount\nNumberOfThreads\nObjectiveBound\nObjectiveValue\nRelativeGap\nRawOptimizerAttribute\nRawSolver\nSilent\nSimplexIterations\nSolverName\nSolverVersion\nSolveTimeSec\nTimeLimitSec\nObjectiveLimit","category":"page"},{"location":"tutorials/mathprogbase/#Transitioning-from-MathProgBase","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"MathOptInterface is a replacement for MathProgBase.jl. However, it is not a direct replacement.","category":"page"},{"location":"tutorials/mathprogbase/#Transitioning-a-solver-interface","page":"Transitioning from MathProgBase","title":"Transitioning a solver interface","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"MathOptInterface is more extensive than MathProgBase which may make its implementation seem daunting at first. There are however numerous utilities in MathOptInterface that the simplify implementation process.","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"For more information, read Implementing a solver interface.","category":"page"},{"location":"tutorials/mathprogbase/#Transitioning-the-high-level-functions","page":"Transitioning from MathProgBase","title":"Transitioning the high-level functions","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"MathOptInterface doesn't provide replacements for the high-level interfaces in MathProgBase. We recommend you use JuMP as a modeling interface instead.","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"tip: Tip\nIf you haven't used JuMP before, start with the tutorial Getting started with JuMP","category":"page"},{"location":"tutorials/mathprogbase/#linprog","page":"Transitioning from MathProgBase","title":"linprog","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"Here is one way of transitioning from linprog:","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"using JuMP\n\nfunction linprog(c, A, sense, b, l, u, solver)\n N = length(c)\n model = Model(solver)\n @variable(model, l[i] <= x[i=1:N] <= u[i])\n @objective(model, Min, c' * x)\n eq_rows, ge_rows, le_rows = sense .== '=', sense .== '>', sense .== '<'\n @constraint(model, A[eq_rows, :] * x .== b[eq_rows])\n @constraint(model, A[ge_rows, :] * x .>= b[ge_rows])\n @constraint(model, A[le_rows, :] * x .<= b[le_rows])\n optimize!(model)\n return (\n status = termination_status(model),\n objval = objective_value(model),\n sol = value.(x)\n )\nend","category":"page"},{"location":"tutorials/mathprogbase/#mixintprog","page":"Transitioning from MathProgBase","title":"mixintprog","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"Here is one way of transitioning from mixintprog:","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"using JuMP\n\nfunction mixintprog(c, A, rowlb, rowub, vartypes, lb, ub, solver)\n N = length(c)\n model = Model(solver)\n @variable(model, lb[i] <= x[i=1:N] <= ub[i])\n for i in 1:N\n if vartypes[i] == :Bin\n set_binary(x[i])\n elseif vartypes[i] == :Int\n set_integer(x[i])\n end\n end\n @objective(model, Min, c' * x)\n @constraint(model, rowlb .<= A * x .<= rowub)\n optimize!(model)\n return (\n status = termination_status(model),\n objval = objective_value(model),\n sol = value.(x)\n )\nend","category":"page"},{"location":"tutorials/mathprogbase/#quadprog","page":"Transitioning from MathProgBase","title":"quadprog","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"Here is one way of transitioning from quadprog:","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"using JuMP\n\nfunction quadprog(c, Q, A, rowlb, rowub, lb, ub, solver)\n N = length(c)\n model = Model(solver)\n @variable(model, lb[i] <= x[i=1:N] <= ub[i])\n @objective(model, Min, c' * x + 0.5 * x' * Q * x)\n @constraint(model, rowlb .<= A * x .<= rowub)\n optimize!(model)\n return (\n status = termination_status(model),\n objval = objective_value(model),\n sol = value.(x)\n )\nend","category":"page"},{"location":"submodules/Test/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Test/reference/#test_reference","page":"API Reference","title":"The Test submodule","text":"","category":"section"},{"location":"submodules/Test/reference/","page":"API Reference","title":"API Reference","text":"Functions to help test implementations of MOI. See The Test submodule for more details.","category":"page"},{"location":"submodules/Test/reference/","page":"API Reference","title":"API Reference","text":"Test.Config\nTest.runtests\nTest.setup_test\nTest.version_added\nTest.@requires\nTest.RequirementUnmet","category":"page"},{"location":"submodules/Test/reference/#MathOptInterface.Test.Config","page":"API Reference","title":"MathOptInterface.Test.Config","text":"Config(\n ::Type{T} = Float64;\n atol::Real = Base.rtoldefault(T),\n rtol::Real = Base.rtoldefault(T),\n optimal_status::MOI.TerminationStatusCode = MOI.OPTIMAL,\n infeasible_status::MOI.TerminationStatusCode = MOI.INFEASIBLE,\n exclude::Vector{Any} = Any[],\n) where {T}\n\nReturn an object that is used to configure various tests.\n\nConfiguration arguments\n\natol::Real = Base.rtoldefault(T): Control the absolute tolerance used when comparing solutions.\nrtol::Real = Base.rtoldefault(T): Control the relative tolerance used when comparing solutions.\noptimal_status = MOI.OPTIMAL: Set to MOI.LOCALLY_SOLVED if the solver cannot prove global optimality.\ninfeasible_status = MOI.INFEASIBLE: Set to MOI.LOCALLY_INFEASIBLE if the solver cannot prove global infeasibility.\nexclude = Vector{Any}: Pass attributes or functions to exclude to skip parts of tests that require certain functionality. Common arguments include:\nMOI.delete to skip deletion-related tests\nMOI.optimize! to skip optimize-related tests\nMOI.ConstraintDual to skip dual-related tests\nMOI.VariableName to skip setting variable names\nMOI.ConstraintName to skip setting constraint names\n\nExamples\n\nFor a nonlinear solver that finds local optima and does not support finding dual variables or constraint names:\n\nConfig(\n Float64;\n optimal_status = MOI.LOCALLY_SOLVED,\n exclude = Any[\n MOI.ConstraintDual,\n MOI.VariableName,\n MOI.ConstraintName,\n MOI.delete,\n ],\n)\n\n\n\n\n\n","category":"type"},{"location":"submodules/Test/reference/#MathOptInterface.Test.runtests","page":"API Reference","title":"MathOptInterface.Test.runtests","text":"runtests(\n model::MOI.ModelLike,\n config::Config;\n include::Vector{Union{String,Regex}} = String[],\n exclude::Vector{Union{String,Regex}} = String[],\n warn_unsupported::Bool = false,\n exclude_tests_after::VersionNumber = v\"999.0.0\",\n)\n\nRun all tests in MathOptInterface.Test on model.\n\nConfiguration arguments\n\nconfig is a Test.Config object that can be used to modify the behavior of tests.\nIf include is not empty, only run tests if an element from include occursin the name of the test.\nIf exclude is not empty, skip tests if an element from exclude occursin the name of the test.\nexclude takes priority over include.\nIf warn_unsupported is false, runtests will silently skip tests that fail with a MOI.NotAllowedError, MOI.UnsupportedError, or RequirementUnmet error. (The latter is thrown when an @requires statement returns false.) When warn_unsupported is true, a warning will be printed. For most cases the default behavior, false, is what you want, since these tests likely test functionality that is not supported by model. However, it can be useful to run warn_unsupported = true to check you are not skipping tests due to a missing supports_constraint method or equivalent.\nexclude_tests_after is a version number that excludes any tests to MOI added after that version number. This is useful for solvers who can declare a fixed set of tests, and not cause their tests to break if a new patch of MOI is released with a new test.\n\nSee also: setup_test.\n\nExample\n\nconfig = MathOptInterface.Test.Config()\nMathOptInterface.Test.runtests(\n model,\n config;\n include = [\"test_linear_\", r\"^test_model_Name$\"],\n exclude = [\"VariablePrimalStart\"],\n warn_unsupported = true,\n exclude_tests_after = v\"0.10.5\",\n)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Test/reference/#MathOptInterface.Test.setup_test","page":"API Reference","title":"MathOptInterface.Test.setup_test","text":"setup_test(::typeof(f), model::MOI.ModelLike, config::Config)\n\nOverload this method to modify model before running the test function f on model with config. You can also modify the fields in config (e.g., to loosen the default tolerances).\n\nThis function should either return nothing, or return a function which, when called with zero arguments, undoes the setup to return the model to its previous state. You do not need to undo any modifications to config.\n\nThis function is most useful when writing new tests of the tests for MOI, but it can also be used to set test-specific tolerances, etc.\n\nSee also: runtests\n\nExample\n\nfunction MOI.Test.setup_test(\n ::typeof(MOI.Test.test_linear_VariablePrimalStart_partial),\n mock::MOIU.MockOptimizer,\n ::MOI.Test.Config,\n)\n MOIU.set_mock_optimize!(\n mock,\n (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 0.0]),\n )\n mock.eval_variable_constraint_dual = false\n\n function reset_function()\n mock.eval_variable_constraint_dual = true\n return\n end\n return reset_function\nend\n\n\n\n\n\n","category":"function"},{"location":"submodules/Test/reference/#MathOptInterface.Test.version_added","page":"API Reference","title":"MathOptInterface.Test.version_added","text":"version_added(::typeof(function_name))\n\nReturns the version of MOI in which the test function_name was added.\n\nThis method should be implemented for all new tests.\n\nSee the exclude_tests_after keyword of runtests for more details.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Test/reference/#MathOptInterface.Test.@requires","page":"API Reference","title":"MathOptInterface.Test.@requires","text":"@requires(x)\n\nCheck that the condition x is true. Otherwise, throw an RequirementUnmet error to indicate that the model does not support something required by the test function.\n\nExamples\n\n@requires MOI.supports(model, MOI.Silent())\n@test MOI.get(model, MOI.Silent())\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Test/reference/#MathOptInterface.Test.RequirementUnmet","page":"API Reference","title":"MathOptInterface.Test.RequirementUnmet","text":"RequirementUnmet(msg::String) <: Exception\n\nAn error for throwing in tests to indicate that the model does not support some requirement expected by the test function.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Benchmarks/overview/#The-Benchmarks-submodule","page":"Overview","title":"The Benchmarks submodule","text":"","category":"section"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"To aid the development of efficient solver wrappers, MathOptInterface provides benchmarking capability. Benchmarking a wrapper follows a two-step process.","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"First, prior to making changes, create a baseline for the benchmark results on a given benchmark suite as follows:","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"using SolverPackage # Replace with your choice of solver.\nimport MathOptInterface as MOI\n\nsuite = MOI.Benchmarks.suite() do\n SolverPackage.Optimizer()\nend\n\nMOI.Benchmarks.create_baseline(\n suite, \"current\"; directory = \"/tmp\", verbose = true\n)","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"Use the exclude argument to Benchmarks.suite to exclude benchmarks that the solver doesn't support.","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"Second, after making changes to the package, re-run the benchmark suite and compare to the prior saved results:","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"using SolverPackage\nimport MathOptInterface as MOI\n\nsuite = MOI.Benchmarks.suite() do\n SolverPackage.Optimizer()\nend\n\nMOI.Benchmarks.compare_against_baseline(\n suite, \"current\"; directory = \"/tmp\", verbose = true\n)","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"This comparison will create a report detailing improvements and regressions.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/FileFormats/overview/#The-FileFormats-submodule","page":"Overview","title":"The FileFormats submodule","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The FileFormats module provides functions for reading and writing MOI models using write_to_file and read_from_file.","category":"page"},{"location":"submodules/FileFormats/overview/#Supported-file-types","page":"Overview","title":"Supported file types","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"You must read and write files to a FileFormats.Model object. Specific the file-type by passing a FileFormats.FileFormat enum. For example:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The Conic Benchmark Format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF)\nA Conic Benchmark Format (CBF) model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The LP file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_LP)\nA .LP-file model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The MathOptFormat file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)\nA MathOptFormat Model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The MPS file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)\nA Mathematical Programming System (MPS) model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The NL file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_NL)\nAn AMPL (.nl) model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The REW file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_REW)\nA Mathematical Programming System (MPS) model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Note that the REW format is identical to the MPS file format, except that all names are replaced with generic identifiers.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The SDPA file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_SDPA)\nA SemiDefinite Programming Algorithm Format (SDPA) model","category":"page"},{"location":"submodules/FileFormats/overview/#Write-to-file","page":"Overview","title":"Write to file","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"To write a model src to a MathOptFormat file, use:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> src = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> MOI.add_variable(src)\nMOI.VariableIndex(1)\n\njulia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)\nA MathOptFormat Model\n\njulia> MOI.copy_to(dest, src)\nMathOptInterface.Utilities.IndexMap with 1 entry:\n MOI.VariableIndex(1) => MOI.VariableIndex(1)\n\njulia> MOI.write_to_file(dest, \"file.mof.json\")\n\njulia> print(read(\"file.mof.json\", String))\n{\n \"name\": \"MathOptFormat Model\",\n \"version\": {\n \"major\": 1,\n \"minor\": 5\n },\n \"variables\": [\n {\n \"name\": \"x1\"\n }\n ],\n \"objective\": {\n \"sense\": \"feasibility\"\n },\n \"constraints\": []\n}","category":"page"},{"location":"submodules/FileFormats/overview/#Read-from-file","page":"Overview","title":"Read from file","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"To read a MathOptFormat file, use:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)\nA MathOptFormat Model\n\njulia> MOI.read_from_file(dest, \"file.mof.json\")\n\njulia> MOI.get(dest, MOI.ListOfVariableIndices())\n1-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n\njulia> rm(\"file.mof.json\") # Clean up after ourselves.","category":"page"},{"location":"submodules/FileFormats/overview/#Detecting-the-file-type-automatically","page":"Overview","title":"Detecting the file-type automatically","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Instead of the format keyword, you can also use the filename keyword argument to FileFormats.Model. This will attempt to automatically guess the format from the file extension. For example:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> src = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> dest = MOI.FileFormats.Model(filename = \"file.cbf.gz\")\nA Conic Benchmark Format (CBF) model\n\njulia> MOI.copy_to(dest, src)\nMathOptInterface.Utilities.IndexMap()\n\njulia> MOI.write_to_file(dest, \"file.cbf.gz\")\n\njulia> src_2 = MOI.FileFormats.Model(filename = \"file.cbf.gz\")\nA Conic Benchmark Format (CBF) model\n\njulia> src = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> dest = MOI.FileFormats.Model(filename = \"file.cbf.gz\")\nA Conic Benchmark Format (CBF) model\n\njulia> MOI.copy_to(dest, src)\nMathOptInterface.Utilities.IndexMap()\n\njulia> MOI.write_to_file(dest, \"file.cbf.gz\")\n\njulia> src_2 = MOI.FileFormats.Model(filename = \"file.cbf.gz\")\nA Conic Benchmark Format (CBF) model\n\njulia> MOI.read_from_file(src_2, \"file.cbf.gz\")\n\njulia> rm(\"file.cbf.gz\") # Clean up after ourselves.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Note how the compression format (GZip) is also automatically detected from the filename.","category":"page"},{"location":"submodules/FileFormats/overview/#Unsupported-constraints","page":"Overview","title":"Unsupported constraints","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"In some cases src may contain constraints that are not supported by the file format (for example, the CBF format supports integer variables but not binary). If so, copy src to a bridged model using Bridges.full_bridge_optimizer:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"src = MOI.Utilities.Model{Float64}()\nx = MOI.add_variable(model)\nMOI.add_constraint(model, x, MOI.ZeroOne())\ndest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF)\nbridged = MOI.Bridges.full_bridge_optimizer(dest, Float64)\nMOI.copy_to(bridged, src)\nMOI.write_to_file(dest, \"my_model.cbf\")","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"note: Note\nEven after bridging, it may still not be possible to write the model to file because of unsupported constraints (for example, PSD variables in the LP file format).","category":"page"},{"location":"submodules/FileFormats/overview/#Read-and-write-to-io","page":"Overview","title":"Read and write to io","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"In addition to write_to_file and read_from_file, you can read and write directly from IO streams using Base.write and Base.read!:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> src = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)\nA Mathematical Programming System (MPS) model\n\njulia> MOI.copy_to(dest, src)\nMathOptInterface.Utilities.IndexMap()\n\njulia> io = IOBuffer();\n\njulia> write(io, dest)\n\njulia> seekstart(io);\n\njulia> src_2 = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)\nA Mathematical Programming System (MPS) model\n\njulia> read!(io, src_2);","category":"page"},{"location":"submodules/FileFormats/overview/#Validating-MOF-files","page":"Overview","title":"Validating MOF files","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"MathOptFormat files are governed by a schema. Use JSONSchema.jl to check if a .mof.json file satisfies the schema.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"First, construct the schema object as follows:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> import JSON, JSONSchema\n\njulia> schema = JSONSchema.Schema(JSON.parsefile(MOI.FileFormats.MOF.SCHEMA_PATH))\nA JSONSchema","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Then, check if a model file is valid using isvalid:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> good_model = JSON.parse(\"\"\"\n {\n \"version\": {\n \"major\": 1,\n \"minor\": 5\n },\n \"variables\": [{\"name\": \"x\"}],\n \"objective\": {\"sense\": \"feasibility\"},\n \"constraints\": []\n }\n \"\"\");\n\njulia> isvalid(schema, good_model)\ntrue","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"If we construct an invalid file, for example by mis-typing name as NaMe, the validation fails:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> bad_model = JSON.parse(\"\"\"\n {\n \"version\": {\n \"major\": 1,\n \"minor\": 5\n },\n \"variables\": [{\"NaMe\": \"x\"}],\n \"objective\": {\"sense\": \"feasibility\"},\n \"constraints\": []\n }\n \"\"\");\n\njulia> isvalid(schema, bad_model)\nfalse","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Use JSONSchema.validate to obtain more insight into why the validation failed:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> JSONSchema.validate(schema, bad_model)\nValidation failed:\npath: [variables][1]\ninstance: Dict{String, Any}(\"NaMe\" => \"x\")\nschema key: required\nschema value: Any[\"name\"]","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/example/#Solving-a-problem-using-MathOptInterface","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"In this tutorial we demonstrate how to use MathOptInterface to solve the binary-constrained knapsack problem:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"beginaligned\nmax c^top x \nst w^top x le C \n x_i in 01quad forall i=1ldotsn\nendaligned","category":"page"},{"location":"tutorials/example/#Required-packages","page":"Solving a problem using MathOptInterface","title":"Required packages","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"Load the MathOptInterface module and define the shorthand MOI:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"import MathOptInterface as MOI","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"As an optimizer, we choose GLPK:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"using GLPK\noptimizer = GLPK.Optimizer()","category":"page"},{"location":"tutorials/example/#Define-the-data","page":"Solving a problem using MathOptInterface","title":"Define the data","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"We first define the constants of the problem:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> c = [1.0, 2.0, 3.0]\n3-element Vector{Float64}:\n 1.0\n 2.0\n 3.0\n\njulia> w = [0.3, 0.5, 1.0]\n3-element Vector{Float64}:\n 0.3\n 0.5\n 1.0\n\njulia> C = 3.2\n3.2","category":"page"},{"location":"tutorials/example/#Add-the-variables","page":"Solving a problem using MathOptInterface","title":"Add the variables","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> x = MOI.add_variables(optimizer, length(c));","category":"page"},{"location":"tutorials/example/#set_objective_example","page":"Solving a problem using MathOptInterface","title":"Set the objective","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.set(\n optimizer,\n MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),\n MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(c, x), 0.0),\n );\n\njulia> MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"tip: Tip\nMOI.ScalarAffineTerm.(c, x) is a shortcut for [MOI.ScalarAffineTerm(c[i], x[i]) for i = 1:3]. This is Julia's broadcast syntax in action, and is used quite often throughout MOI.","category":"page"},{"location":"tutorials/example/#Add-the-constraints","page":"Solving a problem using MathOptInterface","title":"Add the constraints","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"We add the knapsack constraint and integrality constraints:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.add_constraint(\n optimizer,\n MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(w, x), 0.0),\n MOI.LessThan(C),\n );","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"Add integrality constraints:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> for x_i in x\n MOI.add_constraint(optimizer, x_i, MOI.ZeroOne())\n end","category":"page"},{"location":"tutorials/example/#Optimize-the-model","page":"Solving a problem using MathOptInterface","title":"Optimize the model","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.optimize!(optimizer)","category":"page"},{"location":"tutorials/example/#Understand-why-the-solver-stopped","page":"Solving a problem using MathOptInterface","title":"Understand why the solver stopped","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"The first thing to check after optimization is why the solver stopped, for example, did it stop because of a time limit or did it stop because it found the optimal solution?","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.get(optimizer, MOI.TerminationStatus())\nOPTIMAL::TerminationStatusCode = 1","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"Looks like we found an optimal solution.","category":"page"},{"location":"tutorials/example/#Understand-what-solution-was-returned","page":"Solving a problem using MathOptInterface","title":"Understand what solution was returned","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.get(optimizer, MOI.ResultCount())\n1\n\njulia> MOI.get(optimizer, MOI.PrimalStatus())\nFEASIBLE_POINT::ResultStatusCode = 1\n\njulia> MOI.get(optimizer, MOI.DualStatus())\nNO_SOLUTION::ResultStatusCode = 0","category":"page"},{"location":"tutorials/example/#Query-the-objective","page":"Solving a problem using MathOptInterface","title":"Query the objective","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"What is its objective value?","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.get(optimizer, MOI.ObjectiveValue())\n6.0","category":"page"},{"location":"tutorials/example/#Query-the-primal-solution","page":"Solving a problem using MathOptInterface","title":"Query the primal solution","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"And what is the value of the variables x?","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.get(optimizer, MOI.VariablePrimal(), x)\n3-element Vector{Float64}:\n 1.0\n 1.0\n 1.0","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Utilities/reference/#Utilities.Model","page":"API Reference","title":"Utilities.Model","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.Model","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.Model","page":"API Reference","title":"MathOptInterface.Utilities.Model","text":"An implementation of ModelLike that supports all functions and sets defined in MOI. It is parameterized by the coefficient type.\n\nExamples\n\nmodel = Model{Float64}()\nx = add_variable(model)\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#Utilities.UniversalFallback","page":"API Reference","title":"Utilities.UniversalFallback","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.UniversalFallback","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.UniversalFallback","page":"API Reference","title":"MathOptInterface.Utilities.UniversalFallback","text":"UniversalFallback\n\nThe UniversalFallback can be applied on a MOI.ModelLike model to create the model UniversalFallback(model) supporting any constraint and attribute. This allows to have a specialized implementation in model for performance critical constraints and attributes while still supporting other attributes with a small performance penalty. Note that model is unaware of constraints and attributes stored by UniversalFallback so this is not appropriate if model is an optimizer (for this reason, MOI.optimize! has not been implemented). In that case, optimizer bridges should be used instead.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#Utilities.@model","page":"API Reference","title":"Utilities.@model","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.@model\nUtilities.GenericModel\nUtilities.GenericOptimizer","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@model","page":"API Reference","title":"MathOptInterface.Utilities.@model","text":"macro model(\n model_name,\n scalar_sets,\n typed_scalar_sets,\n vector_sets,\n typed_vector_sets,\n scalar_functions,\n typed_scalar_functions,\n vector_functions,\n typed_vector_functions,\n is_optimizer = false\n)\n\nCreates a type model_name implementing the MOI model interface and containing scalar_sets scalar sets typed_scalar_sets typed scalar sets, vector_sets vector sets, typed_vector_sets typed vector sets, scalar_functions scalar functions, typed_scalar_functions typed scalar functions, vector_functions vector functions and typed_vector_functions typed vector functions. To give no set/function, write (), to give one set S, write (S,).\n\nThe function MOI.VariableIndex should not be given in scalar_functions. The model supports MOI.VariableIndex-in-S constraints where S is MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval, MOI.Integer, MOI.ZeroOne, MOI.Semicontinuous or MOI.Semiinteger. The sets supported with the MOI.VariableIndex cannot be controlled from the macro, use the UniversalFallback to support more sets.\n\nThis macro creates a model specialized for specific types of constraint, by defining specialized structures and methods. To create a model that, in addition to be optimized for specific constraints, also support arbitrary constraints and attributes, use UniversalFallback.\n\nIf is_optimizer = true, the resulting struct is a of GenericOptimizer, which is a subtype of MOI.AbstractOptimizer, otherwise, it is a GenericModel, which is a subtype of MOI.ModelLike.\n\nExamples\n\nThe model describing an linear program would be:\n\n@model(LPModel, # Name of model\n (), # untyped scalar sets\n (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval), # typed scalar sets\n (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives), # untyped vector sets\n (), # typed vector sets\n (), # untyped scalar functions\n (MOI.ScalarAffineFunction,), # typed scalar functions\n (MOI.VectorOfVariables,), # untyped vector functions\n (MOI.VectorAffineFunction,), # typed vector functions\n false\n )\n\nLet MOI denote MathOptInterface, MOIU denote MOI.Utilities. The macro would create the following types with struct_of_constraint_code:\n\nstruct LPModelScalarConstraints{T, C1, C2, C3, C4} <: MOIU.StructOfConstraints\n moi_equalto::C1\n moi_greaterthan::C2\n moi_lessthan::C3\n moi_interval::C4\nend\nstruct LPModelVectorConstraints{T, C1, C2, C3} <: MOIU.StructOfConstraints\n moi_zeros::C1\n moi_nonnegatives::C2\n moi_nonpositives::C3\nend\nstruct LPModelFunctionConstraints{T} <: MOIU.StructOfConstraints\n moi_scalaraffinefunction::LPModelScalarConstraints{\n T,\n MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.EqualTo{T}},\n MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.GreaterThan{T}},\n MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.LessThan{T}},\n MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.Interval{T}}\n }\n moi_vectorofvariables::LPModelVectorConstraints{\n T,\n MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Zeros},\n MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Nonnegatives},\n MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Nonpositives}\n }\n moi_vectoraffinefunction::LPModelVectorConstraints{\n T,\n MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Zeros},\n MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Nonnegatives},\n MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Nonpositives}\n }\nend\nconst LPModel{T} = MOIU.GenericModel{T,MOIU.ObjectiveContainer{T},MOIU.VariablesContainer{T},LPModelFunctionConstraints{T}}\n\nThe type LPModel implements the MathOptInterface API except methods specific to optimizers like optimize! or get with VariablePrimal.\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.GenericModel","page":"API Reference","title":"MathOptInterface.Utilities.GenericModel","text":"mutable struct GenericModel{T,O,V,C} <: AbstractModelLike{T}\n\nImplements a model supporting coefficients of type T and:\n\nAn objective function stored in .objective::O\nVariables and VariableIndex constraints stored in .variable_bounds::V\nF-in-S constraints (excluding VariableIndex constraints) stored in .constraints::C\n\nAll interactions should take place via the MOI interface, so the types O, V, and C should implement the API as needed for their functionality.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.GenericOptimizer","page":"API Reference","title":"MathOptInterface.Utilities.GenericOptimizer","text":"mutable struct GenericOptimizer{T,O,V,C} <: AbstractOptimizer{T}\n\nImplements a model supporting coefficients of type T and:\n\nAn objective function stored in .objective::O\nVariables and VariableIndex constraints stored in .variable_bounds::V\nF-in-S constraints (excluding VariableIndex constraints) stored in .constraints::C\n\nAll interactions should take place via the MOI interface, so the types O, V, and C should implement the API as needed for their functionality.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.objective","page":"API Reference","title":".objective","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.ObjectiveContainer","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ObjectiveContainer","page":"API Reference","title":"MathOptInterface.Utilities.ObjectiveContainer","text":"ObjectiveContainer{T}\n\nA helper struct to simplify the handling of objective functions in Utilities.Model.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.variables","page":"API Reference","title":".variables","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.VariablesContainer\nUtilities.FreeVariables","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.VariablesContainer","page":"API Reference","title":"MathOptInterface.Utilities.VariablesContainer","text":"struct VariablesContainer{T} <: AbstractVectorBounds\n set_mask::Vector{UInt16}\n lower::Vector{T}\n upper::Vector{T}\nend\n\nA struct for storing variables and VariableIndex-related constraints. Used in MOI.Utilities.Model by default.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.FreeVariables","page":"API Reference","title":"MathOptInterface.Utilities.FreeVariables","text":"mutable struct FreeVariables <: MOI.ModelLike\n n::Int64\n FreeVariables() = new(0)\nend\n\nA struct for storing free variables that can be used as the variables field of GenericModel or GenericModel. It represents a model that does not support any constraint nor objective function.\n\nExample\n\nThe following model type represents a conic model in geometric form. As opposed to VariablesContainer, FreeVariables does not support constraint bounds so they are bridged into an affine constraint in the MOI.Nonnegatives cone as expected for the geometric conic form.\n\njulia> MOI.Utilities.@product_of_sets(\n Cones,\n MOI.Zeros,\n MOI.Nonnegatives,\n MOI.SecondOrderCone,\n MOI.PositiveSemidefiniteConeTriangle,\n);\n\njulia> const ConicModel{T} = MOI.Utilities.GenericOptimizer{\n T,\n MOI.Utilities.ObjectiveContainer{T},\n MOI.Utilities.FreeVariables,\n MOI.Utilities.MatrixOfConstraints{\n T,\n MOI.Utilities.MutableSparseMatrixCSC{\n T,\n Int,\n MOI.Utilities.OneBasedIndexing,\n },\n Vector{T},\n Cones{T},\n },\n};\n\njulia> model = MOI.instantiate(ConicModel{Float64}, with_bridge_type=Float64);\n\njulia> x = MOI.add_variable(model)\nMathOptInterface.VariableIndex(1)\n\njulia> c = MOI.add_constraint(model, x, MOI.GreaterThan(1.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)\n\njulia> MOI.Bridges.is_bridged(model, c)\ntrue\n\njulia> bridge = MOI.Bridges.bridge(model, c)\nMathOptInterface.Bridges.Constraint.VectorizeBridge{Float64, MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives, MathOptInterface.VariableIndex}(MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1), 1.0)\n\njulia> bridge.vector_constraint\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)\n\njulia> MOI.Bridges.is_bridged(model, bridge.vector_constraint)\nfalse\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.constraints","page":"API Reference","title":".constraints","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.VectorOfConstraints\nUtilities.StructOfConstraints\nUtilities.@struct_of_constraints_by_function_types\nUtilities.@struct_of_constraints_by_set_types\nUtilities.struct_of_constraint_code","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.VectorOfConstraints","page":"API Reference","title":"MathOptInterface.Utilities.VectorOfConstraints","text":"mutable struct VectorOfConstraints{\n F<:MOI.AbstractFunction,\n S<:MOI.AbstractSet,\n} <: MOI.ModelLike\n constraints::CleverDicts.CleverDict{\n MOI.ConstraintIndex{F,S},\n Tuple{F,S},\n typeof(CleverDicts.key_to_index),\n typeof(CleverDicts.index_to_key),\n }\nend\n\nA struct storing F-in-S constraints as a mapping between the constraint indices to the corresponding tuple of function and set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.StructOfConstraints","page":"API Reference","title":"MathOptInterface.Utilities.StructOfConstraints","text":"abstract type StructOfConstraints <: MOI.ModelLike end\n\nA struct storing a subfields other structs storing constraints of different types.\n\nSee Utilities.@struct_of_constraints_by_function_types and Utilities.@struct_of_constraints_by_set_types.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@struct_of_constraints_by_function_types","page":"API Reference","title":"MathOptInterface.Utilities.@struct_of_constraints_by_function_types","text":"Utilities.@struct_of_constraints_by_function_types(name, func_types...)\n\nGiven a vector of n function types (F1, F2,..., Fn) in func_types, defines a subtype of StructOfConstraints of name name and which type parameters {T, C1, C2, ..., Cn}. It contains n field where the ith field has type Ci and stores the constraints of function type Fi.\n\nThe expression Fi can also be a union in which case any constraint for which the function type is in the union is stored in the field with type Ci.\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@struct_of_constraints_by_set_types","page":"API Reference","title":"MathOptInterface.Utilities.@struct_of_constraints_by_set_types","text":"Utilities.@struct_of_constraints_by_set_types(name, func_types...)\n\nGiven a vector of n set types (S1, S2,..., Sn) in func_types, defines a subtype of StructOfConstraints of name name and which type parameters {T, C1, C2, ..., Cn}. It contains n field where the ith field has type Ci and stores the constraints of set type Si. The expression Si can also be a union in which case any constraint for which the set type is in the union is stored in the field with type Ci. This can be useful if Ci is a MatrixOfConstraints in order to concatenate the coefficients of constraints of several different set types in the same matrix.\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.struct_of_constraint_code","page":"API Reference","title":"MathOptInterface.Utilities.struct_of_constraint_code","text":"struct_of_constraint_code(struct_name, types, field_types = nothing)\n\nGiven a vector of n Union{SymbolFun,_UnionSymbolFS{SymbolFun}} or Union{SymbolSet,_UnionSymbolFS{SymbolSet}} in types, defines a subtype of StructOfConstraints of name name and which type parameters {T, F1, F2, ..., Fn} if field_types is nothing and a {T} otherwise. It contains n field where the ith field has type Ci if field_types is nothing and type field_types[i] otherwise. If types is vector of Union{SymbolFun,_UnionSymbolFS{SymbolFun}} (resp. Union{SymbolSet,_UnionSymbolFS{SymbolSet}}) then the constraints of that function (resp. set) type are stored in the corresponding field.\n\nThis function is used by the macros @model, @struct_of_constraints_by_function_types and @struct_of_constraints_by_set_types.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Caching-optimizer","page":"API Reference","title":"Caching optimizer","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.CachingOptimizer\nUtilities.attach_optimizer\nUtilities.reset_optimizer\nUtilities.drop_optimizer\nUtilities.state\nUtilities.mode","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.CachingOptimizer","page":"API Reference","title":"MathOptInterface.Utilities.CachingOptimizer","text":"CachingOptimizer\n\nCachingOptimizer is an intermediate layer that stores a cache of the model and links it with an optimizer. It supports incremental model construction and modification even when the optimizer doesn't.\n\nConstructors\n\n CachingOptimizer(cache::MOI.ModelLike, optimizer::AbstractOptimizer)\n\nCreates a CachingOptimizer in AUTOMATIC mode, with the optimizer optimizer.\n\nThe type of the optimizer returned is CachingOptimizer{typeof(optimizer), typeof(cache)} so it does not support the function reset_optimizer(::CachingOptimizer, new_optimizer) if the type of new_optimizer is different from the type of optimizer.\n\n CachingOptimizer(cache::MOI.ModelLike, mode::CachingOptimizerMode)\n\nCreates a CachingOptimizer in the NO_OPTIMIZER state and mode mode.\n\nThe type of the optimizer returned is CachingOptimizer{MOI.AbstractOptimizer,typeof(cache)} so it does support the function reset_optimizer(::CachingOptimizer, new_optimizer) if the type of new_optimizer is different from the type of optimizer.\n\nAbout the type\n\nStates\n\nA CachingOptimizer may be in one of three possible states (CachingOptimizerState):\n\nNO_OPTIMIZER: The CachingOptimizer does not have any optimizer.\nEMPTY_OPTIMIZER: The CachingOptimizer has an empty optimizer. The optimizer is not synchronized with the cached model.\nATTACHED_OPTIMIZER: The CachingOptimizer has an optimizer, and it is synchronized with the cached model.\n\nModes\n\nA CachingOptimizer has two modes of operation (CachingOptimizerMode):\n\nMANUAL: The only methods that change the state of the CachingOptimizer are Utilities.reset_optimizer, Utilities.drop_optimizer, and Utilities.attach_optimizer. Attempting to perform an operation in the incorrect state results in an error.\nAUTOMATIC: The CachingOptimizer changes its state when necessary. For example, optimize! will automatically call attach_optimizer (an optimizer must have been previously set). Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to EMPTY_OPTIMIZER mode.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.attach_optimizer","page":"API Reference","title":"MathOptInterface.Utilities.attach_optimizer","text":"attach_optimizer(model::CachingOptimizer)\n\nAttaches the optimizer to model, copying all model data into it. Can be called only from the EMPTY_OPTIMIZER state. If the copy succeeds, the CachingOptimizer will be in state ATTACHED_OPTIMIZER after the call, otherwise an error is thrown; see MOI.copy_to for more details on which errors can be thrown.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.reset_optimizer","page":"API Reference","title":"MathOptInterface.Utilities.reset_optimizer","text":"reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer)\n\nSets or resets m to have the given empty optimizer optimizer.\n\nCan be called from any state. An assertion error will be thrown if optimizer is not empty.\n\nThe CachingOptimizer m will be in state EMPTY_OPTIMIZER after the call.\n\n\n\n\n\nreset_optimizer(m::CachingOptimizer)\n\nDetaches and empties the current optimizer. Can be called from ATTACHED_OPTIMIZER or EMPTY_OPTIMIZER state. The CachingOptimizer will be in state EMPTY_OPTIMIZER after the call.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.drop_optimizer","page":"API Reference","title":"MathOptInterface.Utilities.drop_optimizer","text":"drop_optimizer(m::CachingOptimizer)\n\nDrops the optimizer, if one is present. Can be called from any state. The CachingOptimizer will be in state NO_OPTIMIZER after the call.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.state","page":"API Reference","title":"MathOptInterface.Utilities.state","text":"state(m::CachingOptimizer)::CachingOptimizerState\n\nReturns the state of the CachingOptimizer m. See Utilities.CachingOptimizer.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.mode","page":"API Reference","title":"MathOptInterface.Utilities.mode","text":"mode(m::CachingOptimizer)::CachingOptimizerMode\n\nReturns the operating mode of the CachingOptimizer m. See Utilities.CachingOptimizer.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Mock-optimizer","page":"API Reference","title":"Mock optimizer","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.MockOptimizer","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.MockOptimizer","page":"API Reference","title":"MathOptInterface.Utilities.MockOptimizer","text":"MockOptimizer\n\nMockOptimizer is a fake optimizer especially useful for testing. Its main feature is that it can store the values that should be returned for each attribute.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#Printing","page":"API Reference","title":"Printing","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.latex_formulation","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.latex_formulation","page":"API Reference","title":"MathOptInterface.Utilities.latex_formulation","text":"latex_formulation(model::MOI.ModelLike; kwargs...)\n\nWrap model in a type so that it can be pretty-printed as text/latex in a notebook like IJulia, or in Documenter.\n\nTo render the model, end the cell with latex_formulation(model), or call display(latex_formulation(model)) in to force the display of the model from inside a function.\n\nPossible keyword arguments are:\n\nsimplify_coefficients : Simplify coefficients if possible by omitting them or removing trailing zeros.\ndefault_name : The name given to variables with an empty name.\nprint_types : Print the MOI type of each function and set for clarity.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Copy-utilities","page":"API Reference","title":"Copy utilities","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.default_copy_to\nUtilities.IndexMap\nUtilities.identity_index_map\nUtilities.ModelFilter","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.default_copy_to","page":"API Reference","title":"MathOptInterface.Utilities.default_copy_to","text":"default_copy_to(dest::MOI.ModelLike, src::MOI.ModelLike)\n\nA default implementation of MOI.copy_to(dest, src) for models that implement the incremental interface, i.e., MOI.supports_incremental_interface returns true.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.IndexMap","page":"API Reference","title":"MathOptInterface.Utilities.IndexMap","text":"IndexMap()\n\nThe dictionary-like object returned by MOI.copy_to.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.identity_index_map","page":"API Reference","title":"MathOptInterface.Utilities.identity_index_map","text":"identity_index_map(model::MOI.ModelLike)\n\nReturn an IndexMap that maps all variable and constraint indices of model to themselves.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ModelFilter","page":"API Reference","title":"MathOptInterface.Utilities.ModelFilter","text":"ModelFilter(filter::Function, model::MOI.ModelLike)\n\nA layer to filter out various components of model.\n\nThe filter function takes a single argument, which is each element from the list returned by the attributes below. It returns true if the element should be visible in the filtered model and false otherwise.\n\nThe components that are filtered are:\n\nEntire constraint types via:\nMOI.ListOfConstraintTypesPresent\nIndividual constraints via:\nMOI.ListOfConstraintIndices{F,S}\nSpecific attributes via:\nMOI.ListOfModelAttributesSet\nMOI.ListOfConstraintAttributesSet\nMOI.ListOfVariableAttributesSet\n\nwarning: Warning\nThe list of attributes filtered may change in a future release. You should write functions that are generic and not limited to the five types listed above. Thus, you should probably define a fallback filter(::Any) = true.\n\nSee below for examples of how this works.\n\nnote: Note\nThis layer has a limited scope. It is intended by be used in conjunction with MOI.copy_to.\n\nExample: copy model excluding integer constraints\n\nUse the do syntax to provide a single function.\n\nfiltered_src = MOI.Utilities.ModelFilter(src) do item\n return item != (MOI.VariableIndex, MOI.Integer)\nend\nMOI.copy_to(dest, filtered_src)\n\nExample: copy model excluding names\n\nUse type dispatch to simplify the implementation:\n\nmy_filter(::Any) = true # Note the generic fallback!\nmy_filter(::MOI.VariableName) = false\nmy_filter(::MOI.ConstraintName) = false\nfiltered_src = MOI.Utilities.ModelFilter(my_filter, src)\nMOI.copy_to(dest, filtered_src)\n\nExample: copy irreducible infeasible subsystem\n\nmy_filter(::Any) = true # Note the generic fallback!\nfunction my_filter(ci::MOI.ConstraintIndex)\n status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)\n return status != MOI.NOT_IN_CONFLICT\nend\nfiltered_src = MOI.Utilities.ModelFilter(my_filter, src)\nMOI.copy_to(dest, filtered_src)\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#Penalty-relaxation","page":"API Reference","title":"Penalty relaxation","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.PenaltyRelaxation\nUtilities.ScalarPenaltyRelaxation","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.PenaltyRelaxation","page":"API Reference","title":"MathOptInterface.Utilities.PenaltyRelaxation","text":"PenaltyRelaxation(\n penalties = Dict{MOI.ConstraintIndex,Float64}();\n default::Union{Nothing,T} = 1.0,\n)\n\nA problem modifier that, when passed to MOI.modify, destructively modifies the model in-place to create a penalized relaxation of the constraints.\n\nwarning: Warning\nThis is a destructive routine that modifies the model in-place. If you don't want to modify the original model, use JuMP.copy_model to create a copy before calling MOI.modify.\n\nReformulation\n\nSee Utilities.ScalarPenaltyRelaxation for details of the reformulation.\n\nFor each constraint ci, the penalty passed to Utilities.ScalarPenaltyRelaxation is get(penalties, ci, default). If the value is nothing, because ci does not exist in penalties and default = nothing, then the constraint is skipped.\n\nReturn value\n\nMOI.modify(model, PenaltyRelaxation()) returns a Dict{MOI.ConstraintIndex,MOI.ScalarAffineFunction} that maps each constraint index to the corresponding y + z as a MOI.ScalarAffineFunction. In an optimal solution, query the value of these functions to compute the violation of each constraint.\n\nRelax a subset of constraints\n\nTo relax a subset of constraints, pass a penalties dictionary and set default = nothing.\n\nSupported constraint types\n\nThe penalty relaxation is currently limited to modifying MOI.ScalarAffineFunction and MOI.ScalarQuadraticFunction constraints in the linear sets MOI.LessThan, MOI.GreaterThan, MOI.EqualTo and MOI.Interval.\n\nIt does not include variable bound or integrality constraints, because these cannot be modified in-place.\n\nTo modify variable bounds, rewrite them as linear constraints.\n\nExamples\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(default = 2.0));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 2.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> map[c] isa MOI.ScalarAffineFunction{Float64}\ntrue\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 3.0)));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 3.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> map[c] isa MOI.ScalarAffineFunction{Float64}\ntrue\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ScalarPenaltyRelaxation","page":"API Reference","title":"MathOptInterface.Utilities.ScalarPenaltyRelaxation","text":"ScalarPenaltyRelaxation(penalty::T) where {T}\n\nA problem modifier that, when passed to MOI.modify, destructively modifies the constraint in-place to create a penalized relaxation of the constraint.\n\nwarning: Warning\nThis is a destructive routine that modifies the constraint in-place. If you don't want to modify the original model, use JuMP.copy_model to create a copy before calling MOI.modify.\n\nReformulation\n\nThe penalty relaxation modifies constraints of the form f(x) in S into f(x) + y - z in S, where y z ge 0, and then it introduces a penalty term into the objective of a times (y + z) (if minimizing, else -a), where a is penalty\n\nWhen S is MOI.LessThan or MOI.GreaterThan, we omit y or z respectively as a performance optimization.\n\nReturn value\n\nMOI.modify(model, ci, ScalarPenaltyRelaxation(penalty)) returns y + z as a MOI.ScalarAffineFunction. In an optimal solution, query the value of this function to compute the violation of the constraint.\n\nExamples\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 2.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> f isa MOI.ScalarAffineFunction{Float64}\ntrue\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MatrixOfConstraints","page":"API Reference","title":"MatrixOfConstraints","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.MatrixOfConstraints","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.MatrixOfConstraints","page":"API Reference","title":"MathOptInterface.Utilities.MatrixOfConstraints","text":"mutable struct MatrixOfConstraints{T,AT,BT,ST} <: MOI.ModelLike\n coefficients::AT\n constants::BT\n sets::ST\n caches::Vector{Any}\n are_indices_mapped::Vector{BitSet}\n final_touch::Bool\nend\n\nRepresent ScalarAffineFunction and VectorAffinefunction constraints in a matrix form where the linear coefficients of the functions are stored in the coefficients field, the constants of the functions or sets are stored in the constants field. Additional information about the sets are stored in the sets field.\n\nThis model can only be used as the constraints field of a MOI.Utilities.AbstractModel.\n\nWhen the constraints are added, they are stored in the caches field. They are only loaded in the coefficients and constants fields once MOI.Utilities.final_touch is called. For this reason, MatrixOfConstraints should not be used by an incremental interface. Use MOI.copy_to instead.\n\nThe constraints can be added in two different ways:\n\nWith add_constraint, in which case a canonicalized copy of the function is stored in caches.\nWith pass_nonvariable_constraints, in which case the functions and sets are stored themselves in caches without mapping the variable indices. The corresponding index in caches is added in are_indices_mapped. This avoids doing a copy of the function in case the getter of CanonicalConstraintFunction does not make a copy for the source model, e.g., this is the case of VectorOfConstraints.\n\nWe illustrate this with an example. Suppose a model is copied from a src::MOI.Utilities.Model to a bridged model with a MatrixOfConstraints. For all the types that are not bridged, the constraints will be copied with pass_nonvariable_constraints. Hence the functions stored in caches are exactly the same as the ones stored in src. This is ok since this is only during the copy_to operation during which src cannot be modified. On the other hand, for the types that are bridged, the functions added may contain duplicates even if the functions did not contain duplicates in src so duplicates are removed with MOI.Utilities.canonical.\n\nInterface\n\nThe .coefficients::AT type must implement:\n\nAT()\nMOI.empty(::AT)!\nMOI.Utilities.add_column\nMOI.Utilities.set_number_of_rows\nMOI.Utilities.allocate_terms\nMOI.Utilities.load_terms\nMOI.Utilities.final_touch\n\nThe .constants::BT type must implement:\n\nBT()\nBase.empty!(::BT)\nBase.resize(::BT)\nMOI.Utilities.load_constants\nMOI.Utilities.function_constants\nMOI.Utilities.set_from_constants\n\nThe .sets::ST type must implement:\n\nST()\nMOI.is_empty(::ST)\nMOI.empty(::ST)\nMOI.dimension(::ST)\nMOI.is_valid(::ST, ::MOI.ConstraintIndex)\nMOI.get(::ST, ::MOI.ListOfConstraintTypesPresent)\nMOI.get(::ST, ::MOI.NumberOfConstraints)\nMOI.get(::ST, ::MOI.ListOfConstraintIndices)\nMOI.Utilities.set_types\nMOI.Utilities.set_index\nMOI.Utilities.add_set\nMOI.Utilities.rows\nMOI.Utilities.final_touch\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.coefficients","page":"API Reference","title":".coefficients","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.add_column\nUtilities.allocate_terms\nUtilities.set_number_of_rows\nUtilities.load_terms\nUtilities.final_touch\nUtilities.extract_function","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.add_column","page":"API Reference","title":"MathOptInterface.Utilities.add_column","text":"add_column(coefficients)::Nothing\n\nTell coefficients to pre-allocate datastructures as needed to store one column.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.allocate_terms","page":"API Reference","title":"MathOptInterface.Utilities.allocate_terms","text":"allocate_terms(coefficients, index_map, func)::Nothing\n\nTell coefficients that the terms of the function func where the variable indices are mapped with index_map will be loaded with load_terms.\n\nThe function func must be canonicalized before calling allocate_terms. See is_canonical.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_number_of_rows","page":"API Reference","title":"MathOptInterface.Utilities.set_number_of_rows","text":"set_number_of_rows(coefficients, n)::Nothing\n\nTell coefficients to pre-allocate datastructures as needed to store n rows.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.load_terms","page":"API Reference","title":"MathOptInterface.Utilities.load_terms","text":"load_terms(coefficients, index_map, func, offset)::Nothing\n\nLoads the terms of func to coefficients, mapping the variable indices with index_map.\n\nThe ith dimension of func is loaded at the (offset + i)th row of coefficients.\n\nThe function must be allocated first with allocate_terms.\n\nThe function func must be canonicalized, see is_canonical.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.final_touch","page":"API Reference","title":"MathOptInterface.Utilities.final_touch","text":"final_touch(coefficients)::Nothing\n\nInforms the coefficients that all functions have been added with load_terms. No more modification is allowed unless MOI.empty! is called.\n\nfinal_touch(sets)::Nothing\n\nInforms the sets that all functions have been added with add_set. No more modification is allowed unless MOI.empty! is called.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.extract_function","page":"API Reference","title":"MathOptInterface.Utilities.extract_function","text":"extract_function(coefficients, row::Integer, constant::T) where {T}\n\nReturn the MOI.ScalarAffineFunction{T} function corresponding to row row in coefficients.\n\nextract_function(\n coefficients,\n rows::UnitRange,\n constants::Vector{T},\n) where{T}\n\nReturn the MOI.VectorAffineFunction{T} function corresponding to rows rows in coefficients.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.MutableSparseMatrixCSC\nUtilities.AbstractIndexing\nUtilities.ZeroBasedIndexing\nUtilities.OneBasedIndexing","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.MutableSparseMatrixCSC","page":"API Reference","title":"MathOptInterface.Utilities.MutableSparseMatrixCSC","text":"mutable struct MutableSparseMatrixCSC{Tv,Ti<:Integer,I<:AbstractIndexing}\n indexing::I\n m::Int\n n::Int\n colptr::Vector{Ti}\n rowval::Vector{Ti}\n nzval::Vector{Tv}\n nz_added::Vector{Ti}\nend\n\nMatrix type loading sparse matrices in the Compressed Sparse Column format. The indexing used is indexing, see AbstractIndexing. The other fields have the same meaning than for SparseArrays.SparseMatrixCSC except that the indexing is different unless indexing is OneBasedIndexing. In addition, nz_added is used to cache the number of non-zero terms that have been added to each column due to the incremental nature of load_terms.\n\nThe matrix is loaded in 5 steps:\n\nMOI.empty! is called.\nMOI.Utilities.add_column and MOI.Utilities.allocate_terms are called in any order.\nMOI.Utilities.set_number_of_rows is called.\nMOI.Utilities.load_terms is called for each affine function.\nMOI.Utilities.final_touch is called.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.AbstractIndexing","page":"API Reference","title":"MathOptInterface.Utilities.AbstractIndexing","text":"abstract type AbstractIndexing end\n\nIndexing to be used for storing the row and column indices of MutableSparseMatrixCSC. See ZeroBasedIndexing and OneBasedIndexing.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ZeroBasedIndexing","page":"API Reference","title":"MathOptInterface.Utilities.ZeroBasedIndexing","text":"struct ZeroBasedIndexing <: AbstractIndexing end\n\nZero-based indexing: the ith row or column has index i - 1. This is useful when the vectors of row and column indices need to be communicated to a library using zero-based indexing such as C libraries.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.OneBasedIndexing","page":"API Reference","title":"MathOptInterface.Utilities.OneBasedIndexing","text":"struct ZeroBasedIndexing <: AbstractIndexing end\n\nOne-based indexing: the ith row or column has index i. This enables an allocation-free conversion of MutableSparseMatrixCSC to SparseArrays.SparseMatrixCSC.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.constants","page":"API Reference","title":".constants","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.load_constants\nUtilities.function_constants\nUtilities.set_from_constants","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.load_constants","page":"API Reference","title":"MathOptInterface.Utilities.load_constants","text":"load_constants(constants, offset, func_or_set)::Nothing\n\nThis function loads the constants of func_or_set in constants at an offset of offset. Where offset is the sum of the dimensions of the constraints already loaded. The storage should be preallocated with resize! before calling this function.\n\nThis function should be implemented to be usable as storage of constants for MatrixOfConstraints.\n\nThe constants are loaded in three steps:\n\nBase.empty! is called.\nBase.resize! is called with the sum of the dimensions of all constraints.\nMOI.Utilities.load_constants is called for each function for vector constraint or set for scalar constraint.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.function_constants","page":"API Reference","title":"MathOptInterface.Utilities.function_constants","text":"function_constants(constants, rows)\n\nThis function returns the function constants that were loaded with load_constants at the rows rows.\n\nThis function should be implemented to be usable as storage of constants for MatrixOfConstraints.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_from_constants","page":"API Reference","title":"MathOptInterface.Utilities.set_from_constants","text":"set_from_constants(constants, S::Type, rows)::S\n\nThis function returns an instance of the set S for which the constants where loaded with load_constants at the rows rows.\n\nThis function should be implemented to be usable as storage of constants for MatrixOfConstraints.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.Hyperrectangle","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.Hyperrectangle","page":"API Reference","title":"MathOptInterface.Utilities.Hyperrectangle","text":"struct Hyperrectangle{T} <: AbstractVectorBounds\n lower::Vector{T}\n upper::Vector{T}\nend\n\nA struct for the .constants field in MatrixOfConstraints.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.sets","page":"API Reference","title":".sets","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.set_index\nUtilities.set_types\nUtilities.add_set\nUtilities.rows\nUtilities.num_rows\nUtilities.set_with_dimension","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_index","page":"API Reference","title":"MathOptInterface.Utilities.set_index","text":"set_index(sets, ::Type{S})::Union{Int,Nothing} where {S<:MOI.AbstractSet}\n\nReturn an integer corresponding to the index of the set type in the list given by set_types.\n\nIf S is not part of the list, return nothing.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_types","page":"API Reference","title":"MathOptInterface.Utilities.set_types","text":"set_types(sets)::Vector{Type}\n\nReturn the list of the types of the sets allowed in sets.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.add_set","page":"API Reference","title":"MathOptInterface.Utilities.add_set","text":"add_set(sets, i)::Int64\n\nAdd a scalar set of type index i.\n\nadd_set(sets, i, dim)::Int64\n\nAdd a vector set of type index i and dimension dim.\n\nBoth methods return a unique Int64 of the set that can be used to reference this set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.rows","page":"API Reference","title":"MathOptInterface.Utilities.rows","text":"rows(sets, ci::MOI.ConstraintIndex)::Union{Int,UnitRange{Int}}\n\nReturn the rows in 1:MOI.dimension(sets) corresponding to the set of id ci.value.\n\nFor scalar sets, this returns an Int. For vector sets, this returns an UnitRange{Int}.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.num_rows","page":"API Reference","title":"MathOptInterface.Utilities.num_rows","text":"num_rows(sets::OrderedProductOfSets, ::Type{S}) where {S}\n\nReturn the number of rows corresponding to a set of type S. That is, it is the sum of the dimensions of the sets of type S.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_with_dimension","page":"API Reference","title":"MathOptInterface.Utilities.set_with_dimension","text":"set_with_dimension(::Type{S}, dim) where {S<:MOI.AbstractVectorSet}\n\nReturns the instance of S of MOI.dimension dim. This needs to be implemented for sets of type S to be useable with MatrixOfConstraints.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.ProductOfSets\nUtilities.MixOfScalarSets\nUtilities.@mix_of_scalar_sets\nUtilities.OrderedProductOfSets\nUtilities.@product_of_sets","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ProductOfSets","page":"API Reference","title":"MathOptInterface.Utilities.ProductOfSets","text":"abstract type ProductOfSets{T} end\n\nRepresents a cartesian product of sets of given types.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.MixOfScalarSets","page":"API Reference","title":"MathOptInterface.Utilities.MixOfScalarSets","text":"abstract type MixOfScalarSets{T} <: ProductOfSets{T} end\n\nProduct of scalar sets in the order the constraints are added, mixing the constraints of different types.\n\nUse @mix_of_scalar_sets to generate a new subtype.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@mix_of_scalar_sets","page":"API Reference","title":"MathOptInterface.Utilities.@mix_of_scalar_sets","text":"@mix_of_scalar_sets(name, set_types...)\n\nGenerate a new MixOfScalarSets subtype.\n\nExample\n\n@mix_of_scalar_sets(\n MixedIntegerLinearProgramSets,\n MOI.GreaterThan{T},\n MOI.LessThan{T},\n MOI.EqualTo{T},\n MOI.Integer,\n)\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.OrderedProductOfSets","page":"API Reference","title":"MathOptInterface.Utilities.OrderedProductOfSets","text":"abstract type OrderedProductOfSets{T} <: ProductOfSets{T} end\n\nProduct of sets in the order the constraints are added, grouping the constraints of the same types contiguously.\n\nUse @product_of_sets to generate new subtypes.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@product_of_sets","page":"API Reference","title":"MathOptInterface.Utilities.@product_of_sets","text":"@product_of_sets(name, set_types...)\n\nGenerate a new OrderedProductOfSets subtype.\n\nExample\n\n@product_of_sets(\n LinearOrthants,\n MOI.Zeros,\n MOI.Nonnegatives,\n MOI.Nonpositives,\n MOI.ZeroOne,\n)\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#Fallbacks","page":"API Reference","title":"Fallbacks","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.get_fallback","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.get_fallback","page":"API Reference","title":"MathOptInterface.Utilities.get_fallback","text":"get_fallback(model::MOI.ModelLike, ::MOI.ObjectiveValue)\n\nCompute the objective function value using the VariablePrimal results and the ObjectiveFunction value.\n\n\n\n\n\nget_fallback(model::MOI.ModelLike, ::MOI.DualObjectiveValue, T::Type)::T\n\nCompute the dual objective value of type T using the ConstraintDual results and the ConstraintFunction and ConstraintSet values. Note that the nonlinear part of the model is ignored.\n\n\n\n\n\nget_fallback(model::MOI.ModelLike, ::MOI.ConstraintPrimal,\n constraint_index::MOI.ConstraintIndex)\n\nCompute the value of the function of the constraint of index constraint_index using the VariablePrimal results and the ConstraintFunction values.\n\n\n\n\n\nget_fallback(model::MOI.ModelLike, attr::MOI.ConstraintDual,\n ci::MOI.ConstraintIndex{Union{MOI.VariableIndex,\n MOI.VectorOfVariables}})\n\nCompute the dual of the constraint of index ci using the ConstraintDual of other constraints and the ConstraintFunction values. Throws an error if some constraints are quadratic or if there is one another MOI.VariableIndex-in-S or MOI.VectorOfVariables-in-S constraint with one of the variables in the function of the constraint ci.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Function-utilities","page":"API Reference","title":"Function utilities","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utilities are available for functions:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.eval_variables\nUtilities.map_indices\nUtilities.substitute_variables\nUtilities.filter_variables\nUtilities.remove_variable\nUtilities.all_coefficients\nUtilities.unsafe_add\nUtilities.isapprox_zero\nUtilities.modify_function\nUtilities.zero_with_output_dimension","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.eval_variables","page":"API Reference","title":"MathOptInterface.Utilities.eval_variables","text":"eval_variables(value_fn::Function, f::MOI.AbstractFunction)\n\nReturns the value of function f if each variable index vi is evaluated as value_fn(vi).\n\nNote that value_fn must return a Number. See substitute_variables for a similar function where value_fn returns an MOI.AbstractScalarFunction.\n\nwarning: Warning\nThe two-argument version of eval_variables is deprecated and may be removed in MOI v2.0.0. Use the three-argument method eval_variables(::Function, ::MOI.ModelLike, ::MOI.AbstractFunction) instead.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.map_indices","page":"API Reference","title":"MathOptInterface.Utilities.map_indices","text":"map_indices(index_map::Function, attr::MOI.AnyAttribute, x::X)::X where {X}\n\nSubstitute any MOI.VariableIndex (resp. MOI.ConstraintIndex) in x by the MOI.VariableIndex (resp. MOI.ConstraintIndex) of the same type given by index_map(x).\n\nWhen to implement this method for new types X\n\nThis function is used by implementations of MOI.copy_to on constraint functions, attribute values and submittable values. If you define a new attribute whose values x::X contain variable or constraint indices, you must also implement this function.\n\n\n\n\n\nmap_indices(\n variable_map::AbstractDict{T,T},\n x::X,\n)::X where {T<:MOI.Index,X}\n\nShortcut for map_indices(vi -> variable_map[vi], x).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.substitute_variables","page":"API Reference","title":"MathOptInterface.Utilities.substitute_variables","text":"substitute_variables(variable_map::Function, x)\n\nSubstitute any MOI.VariableIndex in x by variable_map(x). The variable_map function returns either MOI.VariableIndex or MOI.ScalarAffineFunction, see eval_variables for a similar function where variable_map returns a number.\n\nThis function is used by bridge optimizers on constraint functions, attribute values and submittable values when at least one variable bridge is used hence it needs to be implemented for custom types that are meant to be used as attribute or submittable value.\n\nnote: Note\nWhen implementing a new method, don't use substitute_variables(::Function, because Julia will not specialize on it. Use instead substitute_variables(::F, ...) where {F<:Function}.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.filter_variables","page":"API Reference","title":"MathOptInterface.Utilities.filter_variables","text":"filter_variables(keep::Function, f::AbstractFunction)\n\nReturn a new function f with the variable vi such that !keep(vi) removed.\n\nWARNING: Don't define filter_variables(::Function, ...) because Julia will not specialize on this. Define instead filter_variables(::F, ...) where {F<:Function}.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.remove_variable","page":"API Reference","title":"MathOptInterface.Utilities.remove_variable","text":"remove_variable(f::AbstractFunction, vi::VariableIndex)\n\nReturn a new function f with the variable vi removed.\n\n\n\n\n\nremove_variable(f::MOI.AbstractFunction, s::MOI.AbstractSet, vi::MOI.VariableIndex)\n\nReturn a tuple (g, t) representing the constraint f-in-s with the variable vi removed. That is, the terms containing the variable vi in the function f are removed and the dimension of the set s is updated if needed (e.g. when f is a VectorOfVariables with vi being one of the variables).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.all_coefficients","page":"API Reference","title":"MathOptInterface.Utilities.all_coefficients","text":"all_coefficients(p::Function, f::MOI.AbstractFunction)\n\nDetermine whether predicate p returns true for all coefficients of f, returning false as soon as the first coefficient of f for which p returns false is encountered (short-circuiting). Similar to all.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.unsafe_add","page":"API Reference","title":"MathOptInterface.Utilities.unsafe_add","text":"unsafe_add(t1::MOI.ScalarAffineTerm, t2::MOI.ScalarAffineTerm)\n\nSums the coefficients of t1 and t2 and returns an output MOI.ScalarAffineTerm. It is unsafe because it uses the variable of t1 as the variable of the output without checking that it is equal to that of t2.\n\n\n\n\n\nunsafe_add(t1::MOI.ScalarQuadraticTerm, t2::MOI.ScalarQuadraticTerm)\n\nSums the coefficients of t1 and t2 and returns an output MOI.ScalarQuadraticTerm. It is unsafe because it uses the variable's of t1 as the variable's of the output without checking that they are the same (up to permutation) to those of t2.\n\n\n\n\n\nunsafe_add(t1::MOI.VectorAffineTerm, t2::MOI.VectorAffineTerm)\n\nSums the coefficients of t1 and t2 and returns an output MOI.VectorAffineTerm. It is unsafe because it uses the output_index and variable of t1 as the output_index and variable of the output term without checking that they are equal to those of t2.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.isapprox_zero","page":"API Reference","title":"MathOptInterface.Utilities.isapprox_zero","text":"isapprox_zero(f::MOI.AbstractFunction, tol)\n\nReturn a Bool indicating whether the function f is approximately zero using tol as a tolerance.\n\nImportant note\n\nThis function assumes that f does not contain any duplicate terms, you might want to first call canonical if that is not guaranteed. For instance, given\n\nf = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([1, -1], [x, x]), 0)\n\nthen isapprox_zero(f) is false but isapprox_zero(MOIU.canonical(f)) is true.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.modify_function","page":"API Reference","title":"MathOptInterface.Utilities.modify_function","text":"modify_function(f::AbstractFunction, change::AbstractFunctionModification)\n\nReturn a copy of the function f, modified according to change.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.zero_with_output_dimension","page":"API Reference","title":"MathOptInterface.Utilities.zero_with_output_dimension","text":"zero_with_output_dimension(::Type{T}, output_dimension::Integer) where {T}\n\nCreate an instance of type T with the output dimension output_dimension.\n\nThis is mostly useful in Bridges, when code needs to be agnostic to the type of vector-valued function that is passed in.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following functions can be used to canonicalize a function:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.is_canonical\nUtilities.canonical\nUtilities.canonicalize!","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.is_canonical","page":"API Reference","title":"MathOptInterface.Utilities.is_canonical","text":"is_canonical(f::Union{ScalarAffineFunction, VectorAffineFunction})\n\nReturns a Bool indicating whether the function is in canonical form. See canonical.\n\n\n\n\n\nis_canonical(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})\n\nReturns a Bool indicating whether the function is in canonical form. See canonical.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.canonical","page":"API Reference","title":"MathOptInterface.Utilities.canonical","text":"canonical(f::MOI.AbstractFunction)\n\nReturns the function in a canonical form, i.e.\n\nA term appear only once.\nThe coefficients are nonzero.\nThe terms appear in increasing order of variable where there the order of the variables is the order of their value.\nFor a AbstractVectorFunction, the terms are sorted in ascending order of output index.\n\nThe output of canonical can be assumed to be a copy of f, even for VectorOfVariables.\n\nExamples\n\nIf x (resp. y, z) is VariableIndex(1) (resp. 2, 3). The canonical representation of ScalarAffineFunction([y, x, z, x, z], [2, 1, 3, -2, -3], 5) is ScalarAffineFunction([x, y], [-1, 2], 5).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.canonicalize!","page":"API Reference","title":"MathOptInterface.Utilities.canonicalize!","text":"canonicalize!(f::Union{ScalarAffineFunction, VectorAffineFunction})\n\nConvert a function to canonical form in-place, without allocating a copy to hold the result. See canonical.\n\n\n\n\n\ncanonicalize!(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})\n\nConvert a function to canonical form in-place, without allocating a copy to hold the result. See canonical.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following functions can be used to manipulate functions with basic algebra:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.scalar_type\nUtilities.scalarize\nUtilities.eachscalar\nUtilities.promote_operation\nUtilities.operate\nUtilities.operate!\nUtilities.operate_output_index!\nUtilities.vectorize","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.scalar_type","page":"API Reference","title":"MathOptInterface.Utilities.scalar_type","text":"scalar_type(F::Type{<:MOI.AbstractVectorFunction})\n\nType of functions obtained by indexing objects obtained by calling eachscalar on functions of type F.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.scalarize","page":"API Reference","title":"MathOptInterface.Utilities.scalarize","text":"scalarize(func::MOI.VectorOfVariables, ignore_constants::Bool = false)\n\nReturns a vector of scalar functions making up the vector function in the form of a Vector{MOI.SingleVariable}.\n\nSee also eachscalar.\n\n\n\n\n\nscalarize(func::MOI.VectorAffineFunction{T}, ignore_constants::Bool = false)\n\nReturns a vector of scalar functions making up the vector function in the form of a Vector{MOI.ScalarAffineFunction{T}}.\n\nSee also eachscalar.\n\n\n\n\n\nscalarize(func::MOI.VectorQuadraticFunction{T}, ignore_constants::Bool = false)\n\nReturns a vector of scalar functions making up the vector function in the form of a Vector{MOI.ScalarQuadraticFunction{T}}.\n\nSee also eachscalar.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.eachscalar","page":"API Reference","title":"MathOptInterface.Utilities.eachscalar","text":"eachscalar(f::MOI.AbstractVectorFunction)\n\nReturns an iterator for the scalar components of the vector function.\n\nSee also scalarize.\n\n\n\n\n\neachscalar(f::MOI.AbstractVector)\n\nReturns an iterator for the scalar components of the vector.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.promote_operation","page":"API Reference","title":"MathOptInterface.Utilities.promote_operation","text":"promote_operation(\n op::Function,\n ::Type{T},\n ArgsTypes::Type{<:Union{T,AbstractVector{T},MOI.AbstractFunction}}...,\n) where {T<:Number}\n\nCompute the return type of the call operate(op, T, args...), where the types of the arguments args are ArgsTypes.\n\nOne assumption is that the element type T is invariant under each operation. That is, op(::T, ::T)::T where op is a +, -, *, and /.\n\nThere are six methods for which we implement Utilities.promote_operation:\n\n+ a. promote_operation(::typeof(+), ::Type{T}, ::Type{F1}, ::Type{F2})\n- a. promote_operation(::typeof(-), ::Type{T}, ::Type{F}) b. promote_operation(::typeof(-), ::Type{T}, ::Type{F1}, ::Type{F2})\n* a. promote_operation(::typeof(*), ::Type{T}, ::Type{T}, ::Type{F}) b. promote_operation(::typeof(*), ::Type{T}, ::Type{F}, ::Type{T}) c. promote_operation(::typeof(*), ::Type{T}, ::Type{F1}, ::Type{F2}) where F1 and F2 are VariableIndex or ScalarAffineFunction d. promote_operation(::typeof(*), ::Type{T}, ::Type{<:Diagonal{T}}, ::Type{F}\n/ a. promote_operation(::typeof(/), ::Type{T}, ::Type{F}, ::Type{T})\nvcat a. promote_operation(::typeof(vcat), ::Type{T}, ::Type{F}...)\nimag a. promote_operation(::typeof(imag), ::Type{T}, ::Type{F}) where F is VariableIndex or VectorOfVariables\n\nIn each case, F (or F1 and F2) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define promote_operation(-, T, F1, F2) where F1 is a scalar-valued function and F2 is a vector-valued function. The ten supported types are:\n\n::T\n::VariableIndex\n::ScalarAffineFunction{T}\n::ScalarQuadraticFunction{T}\n::ScalarNonlinearFunction\n::AbstractVector{T}\n::VectorOfVariables\n::VectorAffineFunction{T}\n::VectorQuadraticFunction{T}\n::VectorNonlinearFunction\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.operate","page":"API Reference","title":"MathOptInterface.Utilities.operate","text":"operate(\n op::Function,\n ::Type{T},\n args::Union{T,MOI.AbstractFunction}...,\n)::MOI.AbstractFunction where {T<:Number}\n\nReturns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T.\n\nNo argument can be modified.\n\nMethods\n\n+ a. operate(::typeof(+), ::Type{T}, ::F1) b. operate(::typeof(+), ::Type{T}, ::F1, ::F2) c. operate(::typeof(+), ::Type{T}, ::F1...)\n- a. operate(::typeof(-), ::Type{T}, ::F) b. operate(::typeof(-), ::Type{T}, ::F1, ::F2)\n* a. operate(::typeof(*), ::Type{T}, ::T, ::F) b. operate(::typeof(*), ::Type{T}, ::F, ::T) c. operate(::typeof(*), ::Type{T}, ::F1, ::F2) where F1 and F2 are VariableIndex or ScalarAffineFunction d. operate(::typeof(*), ::Type{T}, ::Diagonal{T}, ::F)\n/ a. operate(::typeof(/), ::Type{T}, ::F, ::T)\nvcat a. operate(::typeof(vcat), ::Type{T}, ::F...)\nimag a. operate(::typeof(imag), ::Type{T}, ::F) where F is VariableIndex or VectorOfVariables\n\nOne assumption is that the element type T is invariant under each operation. That is, op(::T, ::T)::T where op is a +, -, *, and /.\n\nIn each case, F (or F1 and F2) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define promote_operation(-, T, F1, F2) where F1 is a scalar-valued function and F2 is a vector-valued function. The ten supported types are:\n\n::T\n::VariableIndex\n::ScalarAffineFunction{T}\n::ScalarQuadraticFunction{T}\n::ScalarNonlinearFunction\n::AbstractVector{T}\n::VectorOfVariables\n::VectorAffineFunction{T}\n::VectorQuadraticFunction{T}\n::VectorNonlinearFunction\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.operate!","page":"API Reference","title":"MathOptInterface.Utilities.operate!","text":"operate!(\n op::Function,\n ::Type{T},\n args::Union{T,MOI.AbstractFunction}...,\n)::MOI.AbstractFunction where {T<:Number}\n\nReturns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T.\n\nThe first argument may be modified, in which case the return value is identical to the first argument. For operations which cannot be implemented in-place, this function returns a new object.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.operate_output_index!","page":"API Reference","title":"MathOptInterface.Utilities.operate_output_index!","text":"operate_output_index!(\n op::Union{typeof(+),typeof(-)},\n ::Type{T},\n output_index::Integer,\n f::Union{AbstractVector{T},MOI.AbstractVectorFunction}\n g::Union{T,MOI.AbstractScalarFunction}...\n) where {T<:Number}\n\nReturn an MOI.AbstractVectorFunction in which the scalar function in row output_index is the result of op(f[output_index], g).\n\nThe functions at output index different to output_index are the same as the functions at the same output index in func. The first argument may be modified.\n\nMethods\n\n+ a. operate_output_index!(+, ::Type{T}, ::Int, ::VectorF, ::ScalarF)\n- a. operate_output_index!(-, ::Type{T}, ::Int, ::VectorF, ::ScalarF)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.vectorize","page":"API Reference","title":"MathOptInterface.Utilities.vectorize","text":"vectorize(x::AbstractVector{<:Number})\n\nReturns x.\n\n\n\n\n\nvectorize(x::AbstractVector{MOI.VariableIndex})\n\nReturns the vector of scalar affine functions in the form of a MOI.VectorAffineFunction{T}.\n\n\n\n\n\nvectorize(funcs::AbstractVector{MOI.ScalarAffineFunction{T}}) where T\n\nReturns the vector of scalar affine functions in the form of a MOI.VectorAffineFunction{T}.\n\n\n\n\n\nvectorize(funcs::AbstractVector{MOI.ScalarQuadraticFunction{T}}) where T\n\nReturns the vector of scalar quadratic functions in the form of a MOI.VectorQuadraticFunction{T}.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Constraint-utilities","page":"API Reference","title":"Constraint utilities","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utilities are available for moving the function constant to the set for scalar constraints:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.shift_constant\nUtilities.supports_shift_constant\nUtilities.normalize_and_add_constraint\nUtilities.normalize_constant","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.shift_constant","page":"API Reference","title":"MathOptInterface.Utilities.shift_constant","text":"shift_constant(set::MOI.AbstractScalarSet, offset)\n\nReturns a new scalar set new_set such that func-in-set is equivalent to func + offset-in-new_set.\n\nOnly define this function if it makes sense to!\n\nUse supports_shift_constant to check if the set supports shifting:\n\nif supports_shift_constant(typeof(old_set))\n new_set = shift_constant(old_set, offset)\n f.constant = 0\n add_constraint(model, f, new_set)\nelse\n add_constraint(model, f, old_set)\nend\n\nSee also supports_shift_constant.\n\nExamples\n\nThe call shift_constant(MOI.Interval(-2, 3), 1) is equal to MOI.Interval(-1, 4).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.supports_shift_constant","page":"API Reference","title":"MathOptInterface.Utilities.supports_shift_constant","text":"supports_shift_constant(::Type{S}) where {S<:MOI.AbstractSet}\n\nReturn true if shift_constant is defined for set S.\n\nSee also shift_constant.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.normalize_and_add_constraint","page":"API Reference","title":"MathOptInterface.Utilities.normalize_and_add_constraint","text":"normalize_and_add_constraint(\n model::MOI.ModelLike,\n func::MOI.AbstractScalarFunction,\n set::MOI.AbstractScalarSet;\n allow_modify_function::Bool = false,\n)\n\nAdds the scalar constraint obtained by moving the constant term in func to the set in model. If allow_modify_function is true then the function func can be modified.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.normalize_constant","page":"API Reference","title":"MathOptInterface.Utilities.normalize_constant","text":"normalize_constant(\n func::MOI.AbstractScalarFunction,\n set::MOI.AbstractScalarSet;\n allow_modify_function::Bool = false,\n)\n\nReturn the func-in-set constraint in normalized form. That is, if func is MOI.ScalarQuadraticFunction or MOI.ScalarAffineFunction, the constant is moved to the set. If allow_modify_function is true then the function func can be modified.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utility identifies those constraints imposing bounds on a given variable, and returns those bound values:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.get_bounds","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.get_bounds","page":"API Reference","title":"MathOptInterface.Utilities.get_bounds","text":"get_bounds(model::MOI.ModelLike, ::Type{T}, x::MOI.VariableIndex)\n\nReturn a tuple (lb, ub) of type Tuple{T, T}, where lb and ub are lower and upper bounds, respectively, imposed on x in model.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utilities are useful when working with symmetric matrix cones.","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.is_diagonal_vectorized_index\nUtilities.side_dimension_for_vectorized_dimension","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.is_diagonal_vectorized_index","page":"API Reference","title":"MathOptInterface.Utilities.is_diagonal_vectorized_index","text":"is_diagonal_vectorized_index(index::Base.Integer)\n\nReturn whether index is the index of a diagonal element in a MOI.AbstractSymmetricMatrixSetTriangle set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.side_dimension_for_vectorized_dimension","page":"API Reference","title":"MathOptInterface.Utilities.side_dimension_for_vectorized_dimension","text":"side_dimension_for_vectorized_dimension(n::Integer)\n\nReturn the dimension d such that MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(d)) is n.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Set-utilities","page":"API Reference","title":"Set utilities","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utilities are available for sets:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.AbstractDistance\nUtilities.ProjectionUpperBoundDistance\nUtilities.distance_to_set\nUtilities.set_dot","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.AbstractDistance","page":"API Reference","title":"MathOptInterface.Utilities.AbstractDistance","text":"abstract type AbstractDistance end\n\nAn abstract type used to enabble dispatch of Utilities.distance_to_set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ProjectionUpperBoundDistance","page":"API Reference","title":"MathOptInterface.Utilities.ProjectionUpperBoundDistance","text":"ProjectionUpperBoundDistance() <: AbstractDistance\n\nAn upper bound on the minimum distance between point and the closest feasible point in set.\n\nDefinition of distance\n\nThe minimum distance is computed as:\n\nd(x mathcalK) = min_y in mathcalK x - y \n\nwhere x is point and mathcalK is set. The norm is computed as:\n\nx = sqrtf(x x mathcalK)\n\nwhere f is Utilities.set_dot.\n\nIn the default case, where the set does not have a specialized method for Utilities.set_dot, the norm is equivalent to the Euclidean norm x = sqrtsum x_i^2.\n\nWhy an upper bound?\n\nIn most cases, distance_to_set should return the smallest upper bound, but it may return a larger value if the smallest upper bound is expensive to compute.\n\nFor example, given an epigraph from of a conic set, (t x) f(x) le t, it may be simpler to return delta such that f(x) le t + delta, rather than computing the nearest projection onto the set.\n\nIf the distance is not the smallest upper bound, the docstring of the appropriate distance_to_set method must describe the way that the distance is computed.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.distance_to_set","page":"API Reference","title":"MathOptInterface.Utilities.distance_to_set","text":"distance_to_set(\n [d::AbstractDistance = ProjectionUpperBoundDistance()],]\n point::T,\n set::MOI.AbstractScalarSet,\n) where {T}\n\ndistance_to_set(\n [d::AbstractDistance = ProjectionUpperBoundDistance(),]\n point::AbstractVector{T},\n set::MOI.AbstractVectorSet,\n) where {T}\n\nCompute the distance between point and set using the distance metric d. If point is in the set set, this function must return zero(T).\n\nIf d is omitted, the default distance is Utilities.ProjectionUpperBoundDistance.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_dot","page":"API Reference","title":"MathOptInterface.Utilities.set_dot","text":"set_dot(x::AbstractVector, y::AbstractVector, set::AbstractVectorSet)\n\nReturn the scalar product between a vector x of the set set and a vector y of the dual of the set s.\n\n\n\n\n\nset_dot(x, y, set::AbstractScalarSet)\n\nReturn the scalar product between a number x of the set set and a number y of the dual of the set s.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#DoubleDicts","page":"API Reference","title":"DoubleDicts","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.DoubleDicts.DoubleDict\nUtilities.DoubleDicts.DoubleDictInner\nUtilities.DoubleDicts.IndexDoubleDict\nUtilities.DoubleDicts.IndexDoubleDictInner\nUtilities.DoubleDicts.outer_keys\nUtilities.DoubleDicts.nonempty_outer_keys","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.DoubleDict","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.DoubleDict","text":"DoubleDict{V}\n\nAn optimized dictionary to map MOI.ConstraintIndex to values of type V.\n\nWorks as a AbstractDict{MOI.ConstraintIndex,V} with minimal differences.\n\nIf V is also a MOI.ConstraintIndex, use IndexDoubleDict.\n\nNote that MOI.ConstraintIndex is not a concrete type, opposed to MOI.ConstraintIndex{MOI.VariableIndex, MOI.Integers}, which is a concrete type.\n\nWhen looping through multiple keys of the same Function-in-Set type, use\n\ninner = dict[F, S]\n\nto return a type-stable DoubleDictInner.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.DoubleDictInner","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.DoubleDictInner","text":"DoubleDictInner{F,S,V}\n\nA type stable inner dictionary of DoubleDict.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.IndexDoubleDict","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.IndexDoubleDict","text":"IndexDoubleDict\n\nA specialized version of [DoubleDict] in which the values are of type MOI.ConstraintIndex\n\nWhen looping through multiple keys of the same Function-in-Set type, use\n\ninner = dict[F, S]\n\nto return a type-stable IndexDoubleDictInner.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.IndexDoubleDictInner","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.IndexDoubleDictInner","text":"IndexDoubleDictInner{F,S}\n\nA type stable inner dictionary of IndexDoubleDict.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.outer_keys","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.outer_keys","text":"outer_keys(d::AbstractDoubleDict)\n\nReturn an iterator over the outer keys of the AbstractDoubleDict d. Each outer key is a Tuple{Type,Type} so that a double loop can be easily used:\n\nfor (F, S) in DoubleDicts.outer_keys(dict)\n for (k, v) in dict[F, S]\n # ...\n end\nend\n\nFor performance, it is recommended that the inner loop lies in a separate function to gurantee type-stability. Some outer keys (F, S) might lead to an empty dict[F, S]. If you want only nonempty dict[F, S], use nonempty_outer_keys.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.nonempty_outer_keys","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.nonempty_outer_keys","text":"nonempty_outer_keys(d::AbstractDoubleDict)\n\nReturn a vector of outer keys of the AbstractDoubleDict d.\n\nOnly outer keys that have a nonempty set of inner keys will be returned.\n\nEach outer key is a Tuple{Type,Type} so that a double loop can be easily used\n\nfor (F, S) in DoubleDicts.nonempty_outer_keys(dict)\n for (k, v) in dict[F, S]\n # ...\n end\nend\nFor performance, it is recommended that the inner loop lies in a separate\nfunction to gurantee type-stability.\n\nIf you want an iterator of all current outer keys, use [`outer_keys`](@ref).\n\n\n\n\n\n","category":"function"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"background/infeasibility_certificates/#Infeasibility-certificates","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"When given a conic problem that is infeasible or unbounded, some solvers can produce a certificate of infeasibility. This page explains what a certificate of infeasibility is, and the related conventions that MathOptInterface adopts.","category":"page"},{"location":"background/infeasibility_certificates/#Conic-duality","page":"Infeasibility certificates","title":"Conic duality","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"MathOptInterface uses conic duality to define infeasibility certificates. A full explanation is given in the section Duality, but here is a brief overview.","category":"page"},{"location":"background/infeasibility_certificates/#Minimization-problems","page":"Infeasibility certificates","title":"Minimization problems","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"For a minimization problem in geometric conic form, the primal is:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n min_x in mathbbR^n a_0^top x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"and the dual is a maximization problem in standard conic form:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n max_y_1 ldots y_m -sum_i=1^m b_i^top y_i + b_0\n\n textst a_0 - sum_i=1^m A_i^top y_i = 0\n\n y_i in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"where each mathcalC_i is a closed convex cone and mathcalC_i^* is its dual cone.","category":"page"},{"location":"background/infeasibility_certificates/#Maximization-problems","page":"Infeasibility certificates","title":"Maximization problems","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"For a maximization problem in geometric conic form, the primal is:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n max_x in mathbbR^n a_0^top x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"and the dual is a minimization problem in standard conic form:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n min_y_1 ldots y_m sum_i=1^m b_i^top y_i + b_0\n\n textst a_0 + sum_i=1^m A_i^top y_i = 0\n\n y_i in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/#Unbounded-problems","page":"Infeasibility certificates","title":"Unbounded problems","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A problem is unbounded if and only if:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"there exists a feasible primal solution\nthe dual is infeasible.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A feasible primal solution—if one exists—can be obtained by setting ObjectiveSense to FEASIBILITY_SENSE before optimizing. Therefore, most solvers stop after they prove the dual is infeasible via a certificate of dual infeasibility, but before they have found a feasible primal solution. This is also the reason that MathOptInterface defines the DUAL_INFEASIBLE status instead of UNBOUNDED.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A certificate of dual infeasibility is an improving ray of the primal problem. That is, there exists some vector d such that for all eta 0:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A_i (x + eta d) + b_i in mathcalC_i i = 1 ldots m","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"and (for minimization problems):","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"a_0^top (x + eta d) + b_0 a_0^top x + b_0","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"for any feasible point x. The latter simplifies to a_0^top d 0. For maximization problems, the inequality is reversed, so that a_0^top d 0.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"If the solver has found a certificate of dual infeasibility:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"TerminationStatus must be DUAL_INFEASIBLE\nPrimalStatus must be INFEASIBILITY_CERTIFICATE\nVariablePrimal must be the corresponding value of d\nConstraintPrimal must be the corresponding value of A_i d\nObjectiveValue must be the value a_0^top d. Note that this is the value of the objective function at d, ignoring the constant b_0.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"note: Note\nThe choice of whether to scale the ray d to have magnitude 1 is left to the solver.","category":"page"},{"location":"background/infeasibility_certificates/#Infeasible-problems","page":"Infeasibility certificates","title":"Infeasible problems","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A certificate of primal infeasibility is an improving ray of the dual problem. However, because infeasibility is independent of the objective function, we first homogenize the primal problem by removing its objective.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"For a minimization problem, a dual improving ray is some vector d such that for all eta 0:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n-sum_i=1^m A_i^top (y_i + eta d_i) = 0 \n(y_i + eta d_i) in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"and:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"-sum_i=1^m b_i^top (y_i + eta d_i) -sum_i=1^m b_i^top y_i","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"for any feasible dual solution y. The latter simplifies to -sum_i=1^m b_i^top d_i 0. For a maximization problem, the inequality is sum_i=1^m b_i^top d_i 0. (Note that these are the same inequality, modulo a - sign.)","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"If the solver has found a certificate of primal infeasibility:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"TerminationStatus must be INFEASIBLE\nDualStatus must be INFEASIBILITY_CERTIFICATE\nConstraintDual must be the corresponding value of d\nDualObjectiveValue must be the value -sum_i=1^m b_i^top d_i for minimization problems and sum_i=1^m b_i^top d_i for maximization problems.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"note: Note\nThe choice of whether to scale the ray d to have magnitude 1 is left to the solver.","category":"page"},{"location":"background/infeasibility_certificates/#Infeasibility-certificates-of-variable-bounds","page":"Infeasibility certificates","title":"Infeasibility certificates of variable bounds","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"Many linear solvers (for example, Gurobi) do not provide explicit access to the primal infeasibility certificate of a variable bound. However, given a set of linear constraints:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\nl_A le A x le u_A \nl_x le x le u_x\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"the primal certificate of the variable bounds can be computed using the primal certificate associated with the affine constraints, d. (Note that d will have one element for each row of the A matrix, and that some or all of the elements in the vectors l_A and u_A may be pm infty. If both l_A and u_A are finite for some row, the corresponding element in `d must be 0.)","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"Given d, compute bard = d^top A. If the bound is finite, a certificate for the lower variable bound of x_i is maxbard_i 0, and a certificate for the upper variable bound is minbard_i 0.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/modification/#Problem-modification","page":"Problem modification","title":"Problem modification","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"In addition to adding and deleting constraints and variables, MathOptInterface supports modifying, in-place, coefficients in the constraints and the objective function of a model.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"These modifications can be grouped into two categories:","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"modifications which replace the set of function of a constraint with a new set or function\nmodifications which change, in-place, a component of a function","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"warning: Warning\nSome ModelLike objects do not support problem modification.","category":"page"},{"location":"manual/modification/#Modify-the-set-of-a-constraint","page":"Problem modification","title":"Modify the set of a constraint","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use set and ConstraintSet to modify the set of a constraint by replacing it with a new instance of the same type.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> MOI.set(model, MOI.ConstraintSet(), c, MOI.EqualTo(2.0));\n\njulia> MOI.get(model, MOI.ConstraintSet(), c) == MOI.EqualTo(2.0)\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"However, the following will fail as the new set is of a different type to the original set:","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan(2.0))\nERROR: [...]","category":"page"},{"location":"manual/modification/#Special-cases:-set-transforms","page":"Problem modification","title":"Special cases: set transforms","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"If our constraint is an affine inequality, then this corresponds to modifying the right-hand side of a constraint in linear programming.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"In some special cases, solvers may support efficiently changing the set of a constraint (for example, from LessThan to GreaterThan). For these cases, MathOptInterface provides the transform method.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"The transform function returns a new constraint index, and the old constraint index (that is, c) is no longer valid.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.LessThan(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}}(1)\n\njulia> new_c = MOI.transform(model, c, MOI.GreaterThan(2.0));\n\njulia> MOI.is_valid(model, c)\nfalse\n\njulia> MOI.is_valid(model, new_c)\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"note: Note\ntransform cannot be called with a set of the same type. Use set instead.","category":"page"},{"location":"manual/modification/#Modify-the-function-of-a-constraint","page":"Problem modification","title":"Modify the function of a constraint","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use set and ConstraintFunction to modify the function of a constraint by replacing it with a new instance of the same type.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 1.0);\n\njulia> MOI.set(model, MOI.ConstraintFunction(), c, new_f);\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"However, the following will fail as the new function is of a different type to the original function:","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> MOI.set(model, MOI.ConstraintFunction(), c, x)\nERROR: [...]","category":"page"},{"location":"manual/modification/#Modify-constant-term-in-a-scalar-function","page":"Problem modification","title":"Modify constant term in a scalar function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and ScalarConstantChange to modify the constant term in a ScalarAffineFunction or ScalarQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> MOI.modify(model, c, MOI.ScalarConstantChange(1.0));\n\njulia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 1.0);\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"ScalarConstantChange can also be used to modify the objective function by passing an instance of ObjectiveFunction:","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> MOI.set(\n model,\n MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),\n new_f,\n );\n\njulia> MOI.modify(\n model,\n MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),\n MOI.ScalarConstantChange(-1.0)\n );\n\njulia> MOI.get(\n model,\n MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),\n ) ≈ MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], -1.0)\ntrue","category":"page"},{"location":"manual/modification/#Modify-constant-terms-in-a-vector-function","page":"Problem modification","title":"Modify constant terms in a vector function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and VectorConstantChange to modify the constant vector in a VectorAffineFunction or VectorQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.VectorAffineFunction([\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),\n ],\n [0.0, 0.0],\n ),\n MOI.Nonnegatives(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)\n\njulia> MOI.modify(model, c, MOI.VectorConstantChange([3.0, 4.0]));\n\njulia> new_f = MOI.VectorAffineFunction(\n [\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),\n ],\n [3.0, 4.0],\n );\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/#Modify-affine-coefficients-in-a-scalar-function","page":"Problem modification","title":"Modify affine coefficients in a scalar function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and ScalarCoefficientChange to modify the affine coefficient of a ScalarAffineFunction or ScalarQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> MOI.modify(model, c, MOI.ScalarCoefficientChange(x, 2.0));\n\njulia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 0.0);\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"ScalarCoefficientChange can also be used to modify the objective function by passing an instance of ObjectiveFunction.","category":"page"},{"location":"manual/modification/#Modify-affine-coefficients-in-a-vector-function","page":"Problem modification","title":"Modify affine coefficients in a vector function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and MultirowChange to modify a vector of affine coefficients in a VectorAffineFunction or a VectorQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.VectorAffineFunction([\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),\n ],\n [0.0, 0.0],\n ),\n MOI.Nonnegatives(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)\n\njulia> MOI.modify(model, c, MOI.MultirowChange(x, [(1, 3.0), (2, 4.0)]));\n\njulia> new_f = MOI.VectorAffineFunction(\n [\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(3.0, x)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(4.0, x)),\n ],\n [0.0, 0.0],\n );\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/variables/#Variables","page":"Variables","title":"Variables","text":"","category":"section"},{"location":"manual/variables/#Add-a-variable","page":"Variables","title":"Add a variable","text":"","category":"section"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Use add_variable to add a single variable.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"add_variable returns a VariableIndex type, which is used to refer to the added variable in other calls.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Check if a VariableIndex is valid using is_valid.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> MOI.is_valid(model, x)\ntrue","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Use add_variables to add a number of variables.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> y = MOI.add_variables(model, 2)\n2-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"warning: Warning\nThe integer does not necessarily correspond to the column inside an optimizer.","category":"page"},{"location":"manual/variables/#Delete-a-variable","page":"Variables","title":"Delete a variable","text":"","category":"section"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Delete a variable using delete.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> MOI.delete(model, x)\n\njulia> MOI.is_valid(model, x)\nfalse","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"warning: Warning\nNot all ModelLike models support deleting variables. A DeleteNotAllowed error is thrown if this is not supported.","category":"page"},{"location":"manual/variables/#Variable-attributes","page":"Variables","title":"Variable attributes","text":"","category":"section"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"The following attributes are available for variables:","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"VariableName\nVariablePrimalStart\nVariablePrimal","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Get and set these attributes using get and set.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> MOI.set(model, MOI.VariableName(), x, \"var_x\")\n\njulia> MOI.get(model, MOI.VariableName(), x)\n\"var_x\"","category":"page"},{"location":"submodules/FileFormats/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/FileFormats/reference/#File-Formats","page":"API Reference","title":"File Formats","text":"","category":"section"},{"location":"submodules/FileFormats/reference/","page":"API Reference","title":"API Reference","text":"Functions to help read and write MOI models to/from various file formats. See The FileFormats submodule for more details.","category":"page"},{"location":"submodules/FileFormats/reference/","page":"API Reference","title":"API Reference","text":"FileFormats.Model\nFileFormats.FileFormat\nFileFormats.CBF.Model\nFileFormats.LP.Model\nFileFormats.MOF.Model\nFileFormats.MPS.Model\nFileFormats.NL.Model\nFileFormats.SDPA.Model","category":"page"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.Model","page":"API Reference","title":"MathOptInterface.FileFormats.Model","text":"Model(\n ;\n format::FileFormat = FORMAT_AUTOMATIC,\n filename::Union{Nothing, String} = nothing,\n kwargs...\n)\n\nReturn model corresponding to the FileFormat format, or, if format == FORMAT_AUTOMATIC, guess the format from filename.\n\nThe filename argument is only needed if format == FORMAT_AUTOMATIC.\n\nkwargs are passed to the underlying model constructor.\n\n\n\n\n\n","category":"function"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.FileFormat","page":"API Reference","title":"MathOptInterface.FileFormats.FileFormat","text":"FileFormat\n\nList of accepted export formats.\n\nFORMAT_AUTOMATIC: try to detect the file format based on the file name\nFORMAT_CBF: the Conic Benchmark format\nFORMAT_LP: the LP file format\nFORMAT_MOF: the MathOptFormat file format\nFORMAT_MPS: the MPS file format\nFORMAT_NL: the AMPL .nl file format\nFORMAT_REW: the .rew file format, which is MPS with generic names\nFORMAT_SDPA: the SemiDefinite Programming Algorithm format\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.CBF.Model","page":"API Reference","title":"MathOptInterface.FileFormats.CBF.Model","text":"Model()\n\nCreate an empty instance of FileFormats.CBF.Model.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.LP.Model","page":"API Reference","title":"MathOptInterface.FileFormats.LP.Model","text":"Model(; kwargs...)\n\nCreate an empty instance of FileFormats.LP.Model.\n\nKeyword arguments are:\n\nmaximum_length::Int=255: the maximum length for the name of a variable. lp_solve 5.0 allows only 16 characters, while CPLEX 12.5+ allow 255.\nwarn::Bool=false: print a warning when variables or constraints are renamed.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.MOF.Model","page":"API Reference","title":"MathOptInterface.FileFormats.MOF.Model","text":"Model(; kwargs...)\n\nCreate an empty instance of FileFormats.MOF.Model.\n\nKeyword arguments are:\n\nprint_compact::Bool=false: print the JSON file in a compact format without spaces or newlines.\nwarn::Bool=false: print a warning when variables or constraints are renamed\ndifferentiation_backend::MOI.Nonlinear.AbstractAutomaticDifferentiation = MOI.Nonlinear.SparseReverseMode(): automatic differentiation backend to use when reading models with nonlinear constraints and objectives.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.MPS.Model","page":"API Reference","title":"MathOptInterface.FileFormats.MPS.Model","text":"Model(; kwargs...)\n\nCreate an empty instance of FileFormats.MPS.Model.\n\nKeyword arguments are:\n\nwarn::Bool=false: print a warning when variables or constraints are renamed.\nprint_objsense::Bool=false: print the OBJSENSE section when writing\ngeneric_names::Bool=false: strip all names in the model and replace them with the generic names C$i and R$i for the i'th column and row respectively.\nquadratic_format::QuadraticFormat = kQuadraticFormatGurobi: specify the solver-specific extension used when writing the quadratic components of the model. Options are kQuadraticFormatGurobi, kQuadraticFormatCPLEX, and kQuadraticFormatMosek.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.NL.Model","page":"API Reference","title":"MathOptInterface.FileFormats.NL.Model","text":"Model(; use_nlp_block::Bool = true)\n\nCreate a new Optimizer object.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.SDPA.Model","page":"API Reference","title":"MathOptInterface.FileFormats.SDPA.Model","text":"Model(; number_type::Type = Float64)\n\nCreate an empty instance of FileFormats.SDPA.Model{number_type}.\n\nIt is important to be aware that the SDPA file format is interpreted in geometric form and not standard conic form. The standard conic form and geometric conic form are two dual standard forms for semidefinite programs (SDPs). The geometric conic form of an SDP is as follows:\n\nbeginalign\n min_y in mathbbR^m b^T y\n\n textst sum_i=1^m A_i y_i - C in mathbbK\nendalign\n\nwhere mathcalK is a cartesian product of nonnegative orthant and positive semidefinite matrices that align with a block diagonal structure shared with the matrices A_i and C.\n\nIn other words, the geometric conic form contains free variables and affine constraints in either the nonnegative orthant or the positive semidefinite cone. That is, in the MathOptInterface's terminology, MOI.VectorAffineFunction-in-MOI.Nonnegatives and MOI.VectorAffineFunction-in-MOI.PositiveSemidefiniteConeTriangle constraints.\n\nThe corresponding standard conic form of the dual SDP is as follows:\n\nbeginalign\n max_X in mathbbK texttr(CX)\n\n textst texttr(A_iX) = b_i i = 1 ldots m\nendalign\n\nIn other words, the standard conic form contains nonnegative and positive semidefinite variables with equality constraints. That is, in the MathOptInterface's terminology, MOI.VectorOfVariables-in-MOI.Nonnegatives, MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle and MOI.ScalarAffineFunction-in-MOI.EqualTo constraints.\n\nIf a model is in standard conic form, use Dualization.jl to transform it into the geometric conic form before writting it. Otherwise, the nonnegative (resp. positive semidefinite) variables will be bridged into free variables with affine constraints constraining them to belong to the nonnegative orthant (resp. positive semidefinite cone) by the MOI.Bridges.Constraint.VectorFunctionizeBridge. Moreover, equality constraints will be bridged into pairs of affine constraints in the nonnegative orthant by the MOI.Bridges.Constraint.SplitIntervalBridge and then the MOI.Bridges.Constraint.VectorizeBridge.\n\nIf a solver is in standard conic form, use Dualization.jl to transform the model read into standard conic form before copying it to the solver. Otherwise, the free variables will be bridged into pairs of variables in the nonnegative orthant by the MOI.Bridges.Variable.FreeBridge and affine constraints will be bridged into equality constraints by creating a slack variable by the MOI.Bridges.Constraint.VectorSlackBridge.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#Other-helpers","page":"API Reference","title":"Other helpers","text":"","category":"section"},{"location":"submodules/FileFormats/reference/","page":"API Reference","title":"API Reference","text":"FileFormats.NL.SolFileResults","category":"page"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.NL.SolFileResults","page":"API Reference","title":"MathOptInterface.FileFormats.NL.SolFileResults","text":"SolFileResults(filename::String, model::Model)\n\nParse the .sol file filename created by solving model and return a SolFileResults struct.\n\nThe returned struct supports the MOI.get API for querying result attributes such as MOI.TerminationStatus, MOI.VariablePrimal, and MOI.ConstraintDual.\n\n\n\n\n\nSolFileResults(\n raw_status::String,\n termination_status::MOI.TerminationStatusCode,\n)\n\nReturn a SolFileResults struct with MOI.RawStatusString set to raw_status, MOI.TerminationStatus set to termination_status, and MOI.PrimalStatus and MOI.DualStatus set to NO_SOLUTION.\n\nAll other attributes are un-set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Benchmarks/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Benchmarks/reference/#Benchmarks","page":"API Reference","title":"Benchmarks","text":"","category":"section"},{"location":"submodules/Benchmarks/reference/","page":"API Reference","title":"API Reference","text":"Functions to help benchmark the performance of solver wrappers. See The Benchmarks submodule for more details.","category":"page"},{"location":"submodules/Benchmarks/reference/","page":"API Reference","title":"API Reference","text":"Benchmarks.suite\nBenchmarks.create_baseline\nBenchmarks.compare_against_baseline","category":"page"},{"location":"submodules/Benchmarks/reference/#MathOptInterface.Benchmarks.suite","page":"API Reference","title":"MathOptInterface.Benchmarks.suite","text":"suite(\n new_model::Function;\n exclude::Vector{Regex} = Regex[]\n)\n\nCreate a suite of benchmarks. new_model should be a function that takes no arguments, and returns a new instance of the optimizer you wish to benchmark.\n\nUse exclude to exclude a subset of benchmarks.\n\nExamples\n\nsuite() do\n GLPK.Optimizer()\nend\nsuite(exclude = [r\"delete\"]) do\n Gurobi.Optimizer(OutputFlag=0)\nend\n\n\n\n\n\n","category":"function"},{"location":"submodules/Benchmarks/reference/#MathOptInterface.Benchmarks.create_baseline","page":"API Reference","title":"MathOptInterface.Benchmarks.create_baseline","text":"create_baseline(suite, name::String; directory::String = \"\"; kwargs...)\n\nRun all benchmarks in suite and save to files called name in directory.\n\nExtra kwargs are based to BenchmarkTools.run.\n\nExamples\n\nmy_suite = suite(() -> GLPK.Optimizer())\ncreate_baseline(my_suite, \"glpk_master\"; directory = \"/tmp\", verbose = true)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Benchmarks/reference/#MathOptInterface.Benchmarks.compare_against_baseline","page":"API Reference","title":"MathOptInterface.Benchmarks.compare_against_baseline","text":"compare_against_baseline(\n suite, name::String; directory::String = \"\",\n report_filename::String = \"report.txt\"\n)\n\nRun all benchmarks in suite and compare against files called name in directory that were created by a call to create_baseline.\n\nA report summarizing the comparison is written to report_filename in directory.\n\nExtra kwargs are based to BenchmarkTools.run.\n\nExamples\n\nmy_suite = suite(() -> GLPK.Optimizer())\ncompare_against_baseline(\n my_suite, \"glpk_master\"; directory = \"/tmp\", verbose = true\n)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Test/overview/#test_module","page":"Overview","title":"The Test submodule","text":"","category":"section"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"The Test submodule provides tools to help solvers implement unit tests in order to ensure they implement the MathOptInterface API correctly, and to check for solver-correctness.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"We use a centralized repository of tests, so that if we find a bug in one solver, instead of adding a test to that particular repository, we add it here so that all solvers can benefit.","category":"page"},{"location":"submodules/Test/overview/#How-to-test-a-solver","page":"Overview","title":"How to test a solver","text":"","category":"section"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"The skeleton below can be used for the wrapper test file of a solver named FooBar.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"# ============================ /test/MOI_wrapper.jl ============================\nmodule TestFooBar\n\nimport FooBar\nusing Test\n\nimport MathOptInterface as MOI\n\nconst OPTIMIZER = MOI.instantiate(\n MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true),\n)\n\nconst BRIDGED = MOI.instantiate(\n MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true),\n with_bridge_type = Float64,\n)\n\n# See the docstring of MOI.Test.Config for other arguments.\nconst CONFIG = MOI.Test.Config(\n # Modify tolerances as necessary.\n atol = 1e-6,\n rtol = 1e-6,\n # Use MOI.LOCALLY_SOLVED for local solvers.\n optimal_status = MOI.OPTIMAL,\n # Pass attributes or MOI functions to `exclude` to skip tests that\n # rely on this functionality.\n exclude = Any[MOI.VariableName, MOI.delete],\n)\n\n\"\"\"\n runtests()\n\nThis function runs all functions in the this Module starting with `test_`.\n\"\"\"\nfunction runtests()\n for name in names(@__MODULE__; all = true)\n if startswith(\"$(name)\", \"test_\")\n @testset \"$(name)\" begin\n getfield(@__MODULE__, name)()\n end\n end\n end\nend\n\n\"\"\"\n test_runtests()\n\nThis function runs all the tests in MathOptInterface.Test.\n\nPass arguments to `exclude` to skip tests for functionality that is not\nimplemented or that your solver doesn't support.\n\"\"\"\nfunction test_runtests()\n MOI.Test.runtests(\n BRIDGED,\n CONFIG,\n exclude = [\n \"test_attribute_NumberOfThreads\",\n \"test_quadratic_\",\n ],\n # This argument is useful to prevent tests from failing on future\n # releases of MOI that add new tests. Don't let this number get too far\n # behind the current MOI release though. You should periodically check\n # for new tests to fix bugs and implement new features.\n exclude_tests_after = v\"0.10.5\",\n )\n return\nend\n\n\"\"\"\n test_SolverName()\n\nYou can also write new tests for solver-specific functionality. Write each new\ntest as a function with a name beginning with `test_`.\n\"\"\"\nfunction test_SolverName()\n @test MOI.get(FooBar.Optimizer(), MOI.SolverName()) == \"FooBar\"\n return\nend\n\nend # module TestFooBar\n\n# This line at tne end of the file runs all the tests!\nTestFooBar.runtests()","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Then modify your runtests.jl file to include the MOI_wrapper.jl file:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"# ============================ /test/runtests.jl ============================\n\nusing Test\n\n@testset \"MOI\" begin\n include(\"test/MOI_wrapper.jl\")\nend","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"info: Info\nThe optimizer BRIDGED constructed with instantiate automatically bridges constraints that are not supported by OPTIMIZER using the bridges listed in Bridges. It is recommended for an implementation of MOI to only support constraints that are natively supported by the solver and let bridges transform the constraint to the appropriate form. For this reason it is expected that tests may not pass if OPTIMIZER is used instead of BRIDGED.","category":"page"},{"location":"submodules/Test/overview/#How-to-debug-a-failing-test","page":"Overview","title":"How to debug a failing test","text":"","category":"section"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"When writing a solver, it's likely that you will initially fail many tests. Some failures will be bugs, but other failures you may choose to exclude.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"There are two ways to exclude tests:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Exclude tests whose names contain a string using:\nMOI.Test.runtests(\n model,\n config;\n exclude = String[\"test_to_exclude\", \"test_conic_\"],\n)\nThis will exclude tests whose name contains either of the two strings provided.\nExclude tests which rely on specific functionality using:\nMOI.Test.Config(exclude = Any[MOI.VariableName, MOI.optimize!])\nThis will exclude tests which use the MOI.VariableName attribute, or which call MOI.optimize!.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Each test that fails can be independently called as:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"model = FooBar.Optimizer()\nconfig = MOI.Test.Config()\nMOI.empty!(model)\nMOI.Test.test_category_name_that_failed(model, config)","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"You can look-up the source code of the test that failed by searching for it in the src/Test/test_category.jl file.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nEach test function also has a docstring that explains what the test is for. Use ? MOI.Test.test_category_name_that_failed from the REPL to read it.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Periodically, you should re-run excluded tests to see if they now pass. The easiest way to do this is to swap the exclude keyword argument of runtests to include. For example:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"MOI.Test.runtests(\n model,\n config;\n exclude = String[\"test_to_exclude\", \"test_conic_\"],\n)","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"becomes","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"MOI.Test.runtests(\n model,\n config;\n include = String[\"test_to_exclude\", \"test_conic_\"],\n)","category":"page"},{"location":"submodules/Test/overview/#How-to-add-a-test","page":"Overview","title":"How to add a test","text":"","category":"section"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"To detect bugs in solvers, we add new tests to MOI.Test.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"As an example, ECOS errored calling optimize! twice in a row. (See ECOS.jl PR #72.) We could add a test to ECOS.jl, but that would only stop us from re-introducing the bug to ECOS.jl in the future, but it would not catch other solvers in the ecosystem with the same bug. Instead, if we add a test to MOI.Test, then all solvers will also check that they handle a double optimize call.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"For this test, we care about correctness, rather than performance. therefore, we don't expect solvers to efficiently decide that they have already solved the problem, only that calling optimize! twice doesn't throw an error or give the wrong answer.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Step 1","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Install the MathOptInterface julia package in dev mode:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"julia> ]\n(@v1.6) pkg> dev MathOptInterface","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Step 2","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"From here on, proceed with making the following changes in the ~/.julia/dev/MathOptInterface folder (or equivalent dev path on your machine).","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Step 3","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Since the double-optimize error involves solving an optimization problem, add a new test to src/Test/test_solve.jl:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"\"\"\"\n test_unit_optimize!_twice(model::MOI.ModelLike, config::Config)\n\nTest that calling `MOI.optimize!` twice does not error.\n\nThis problem was first detected in ECOS.jl PR#72:\nhttps://github.com/jump-dev/ECOS.jl/pull/72\n\"\"\"\nfunction test_unit_optimize!_twice(\n model::MOI.ModelLike,\n config::Config{T},\n) where {T}\n # Use the `@requires` macro to check conditions that the test function\n # requires to run. Models failing this `@requires` check will silently skip\n # the test.\n @requires MOI.supports_constraint(\n model,\n MOI.VariableIndex,\n MOI.GreaterThan{Float64},\n )\n @requires _supports(config, MOI.optimize!)\n # If needed, you can test that the model is empty at the start of the test.\n # You can assume that this will be the case for tests run via `runtests`.\n # User's calling tests individually need to call `MOI.empty!` themselves.\n @test MOI.is_empty(model)\n # Create a simple model. Try to make this as simple as possible so that the\n # majority of solvers can run the test.\n x = MOI.add_variable(model)\n MOI.add_constraint(model, x, MOI.GreaterThan(one(T)))\n MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)\n MOI.set(\n model,\n MOI.ObjectiveFunction{MOI.VariableIndex}(),\n x,\n )\n # The main component of the test: does calling `optimize!` twice error?\n MOI.optimize!(model)\n MOI.optimize!(model)\n # Check we have a solution.\n @test MOI.get(model, MOI.TerminationStatus()) == MOI.OPTIMAL\n # There is a three-argument version of `Base.isapprox` for checking\n # approximate equality based on the tolerances defined in `config`:\n @test isapprox(MOI.get(model, MOI.VariablePrimal(), x), one(T), config)\n # For code-style, these tests should always `return` `nothing`.\n return\nend","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"info: Info\nMake sure the function is agnostic to the number type T; don't assume it is a Float64 capable solver.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"We also need to write a test for the test. Place this function immediately below the test you just wrote in the same file:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"function setup_test(\n ::typeof(test_unit_optimize!_twice),\n model::MOI.Utilities.MockOptimizer,\n ::Config,\n)\n MOI.Utilities.set_mock_optimize!(\n model,\n (mock::MOI.Utilities.MockOptimizer) -> MOIU.mock_optimize!(\n mock,\n MOI.OPTIMAL,\n (MOI.FEASIBLE_POINT, [1.0]),\n ),\n )\n return\nend","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Finally, you also need to implement Test.version_added. If we added this test when the latest released version of MOI was v0.10.5, define:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"version_added(::typeof(test_unit_optimize!_twice)) = v\"0.10.6\"","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Step 6","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Commit the changes to git from ~/.julia/dev/MathOptInterface and submit the PR for review.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nIf you need help writing a test, open an issue on GitHub, or ask the Developer Chatroom.","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/errors/#Errors","page":"Errors","title":"Errors","text":"","category":"section"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"When an MOI call fails on a model, precise errors should be thrown when possible instead of simply calling error with a message. The docstrings for the respective methods describe the errors that the implementation should throw in certain situations. This error-reporting system allows code to distinguish between internal errors (that should be shown to the user) and unsupported operations which may have automatic workarounds.","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"When an invalid index is used in an MOI call, an InvalidIndex is thrown:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"InvalidIndex","category":"page"},{"location":"reference/errors/#MathOptInterface.InvalidIndex","page":"Errors","title":"MathOptInterface.InvalidIndex","text":"struct InvalidIndex{IndexType<:Index} <: Exception\n index::IndexType\nend\n\nAn error indicating that the index index is invalid.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"When an invalid result index is used to retrieve an attribute, a ResultIndexBoundsError is thrown:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"ResultIndexBoundsError\ncheck_result_index_bounds","category":"page"},{"location":"reference/errors/#MathOptInterface.ResultIndexBoundsError","page":"Errors","title":"MathOptInterface.ResultIndexBoundsError","text":"struct ResultIndexBoundsError{AttrType} <: Exception\n attr::AttrType\n result_count::Int\nend\n\nAn error indicating that the requested attribute attr could not be retrieved, because the solver returned too few results compared to what was requested. For instance, the user tries to retrieve VariablePrimal(2) when only one solution is available, or when the model is infeasible and has no solution.\n\nSee also: check_result_index_bounds.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.check_result_index_bounds","page":"Errors","title":"MathOptInterface.check_result_index_bounds","text":"check_result_index_bounds(model::ModelLike, attr)\n\nThis function checks whether enough results are available in the model for the requested attr, using its result_index field. If the model does not have sufficient results to answer the query, it throws a ResultIndexBoundsError.\n\n\n\n\n\n","category":"function"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"As discussed in JuMP mapping, for scalar constraint with a nonzero function constant, a ScalarFunctionConstantNotZero exception may be thrown:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"ScalarFunctionConstantNotZero","category":"page"},{"location":"reference/errors/#MathOptInterface.ScalarFunctionConstantNotZero","page":"Errors","title":"MathOptInterface.ScalarFunctionConstantNotZero","text":"struct ScalarFunctionConstantNotZero{T, F, S} <: Exception\n constant::T\nend\n\nAn error indicating that the constant part of the function in the constraint F-in-S is nonzero.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"Some VariableIndex constraints cannot be combined on the same variable:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"LowerBoundAlreadySet\nUpperBoundAlreadySet","category":"page"},{"location":"reference/errors/#MathOptInterface.LowerBoundAlreadySet","page":"Errors","title":"MathOptInterface.LowerBoundAlreadySet","text":"LowerBoundAlreadySet{S1, S2}\n\nError thrown when setting a VariableIndex-in-S2 when a VariableIndex-in-S1 has already been added and the sets S1, S2 both set a lower bound, i.e. they are EqualTo, GreaterThan, Interval, Semicontinuous or Semiinteger.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.UpperBoundAlreadySet","page":"Errors","title":"MathOptInterface.UpperBoundAlreadySet","text":"UpperBoundAlreadySet{S1, S2}\n\nError thrown when setting a VariableIndex-in-S2 when a VariableIndex-in-S1 has already been added and the sets S1, S2 both set an upper bound, i.e. they are EqualTo, LessThan, Interval, Semicontinuous or Semiinteger.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"As discussed in AbstractCallback, trying to get attributes inside a callback may throw:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"OptimizeInProgress","category":"page"},{"location":"reference/errors/#MathOptInterface.OptimizeInProgress","page":"Errors","title":"MathOptInterface.OptimizeInProgress","text":"struct OptimizeInProgress{AttrType<:AnyAttribute} <: Exception\n attr::AttrType\nend\n\nError thrown from optimizer when MOI.get(optimizer, attr) is called inside an AbstractCallback while it is only defined once optimize! has completed. This can only happen when is_set_by_optimize(attr) is true.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"Trying to submit the wrong type of AbstractSubmittable inside an AbstractCallback (for example, a UserCut inside a LazyConstraintCallback) will throw:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"InvalidCallbackUsage","category":"page"},{"location":"reference/errors/#MathOptInterface.InvalidCallbackUsage","page":"Errors","title":"MathOptInterface.InvalidCallbackUsage","text":"struct InvalidCallbackUsage{C, S} <: Exception\n callback::C\n submittable::S\nend\n\nAn error indicating that submittable cannot be submitted inside callback.\n\nFor example, UserCut cannot be submitted inside LazyConstraintCallback.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"The rest of the errors defined in MOI fall in two categories represented by the following two abstract types:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"UnsupportedError\nNotAllowedError","category":"page"},{"location":"reference/errors/#MathOptInterface.UnsupportedError","page":"Errors","title":"MathOptInterface.UnsupportedError","text":"UnsupportedError <: Exception\n\nAbstract type for error thrown when an element is not supported by the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.NotAllowedError","page":"Errors","title":"MathOptInterface.NotAllowedError","text":"NotAllowedError <: Exception\n\nAbstract type for error thrown when an operation is supported but cannot be applied in the current state of the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"The different UnsupportedError and NotAllowedError are the following errors:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"UnsupportedAttribute\nSetAttributeNotAllowed\nAddVariableNotAllowed\nUnsupportedConstraint\nAddConstraintNotAllowed\nModifyConstraintNotAllowed\nModifyObjectiveNotAllowed\nDeleteNotAllowed\nUnsupportedSubmittable\nSubmitNotAllowed\nUnsupportedNonlinearOperator","category":"page"},{"location":"reference/errors/#MathOptInterface.UnsupportedAttribute","page":"Errors","title":"MathOptInterface.UnsupportedAttribute","text":"struct UnsupportedAttribute{AttrType} <: UnsupportedError\n attr::AttrType\n message::String\nend\n\nAn error indicating that the attribute attr is not supported by the model, i.e. that supports returns false.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.SetAttributeNotAllowed","page":"Errors","title":"MathOptInterface.SetAttributeNotAllowed","text":"struct SetAttributeNotAllowed{AttrType} <: NotAllowedError\n attr::AttrType\n message::String\nend\n\nAn error indicating that the attribute attr is supported (see supports) but cannot be set for some reason (see the error string).\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.AddVariableNotAllowed","page":"Errors","title":"MathOptInterface.AddVariableNotAllowed","text":"struct AddVariableNotAllowed <: NotAllowedError\n message::String # Human-friendly explanation why the attribute cannot be set\nend\n\nAn error indicating that variables cannot be added to the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.UnsupportedConstraint","page":"Errors","title":"MathOptInterface.UnsupportedConstraint","text":"struct UnsupportedConstraint{F<:AbstractFunction, S<:AbstractSet} <: UnsupportedError\n message::String # Human-friendly explanation why the attribute cannot be set\nend\n\nAn error indicating that constraints of type F-in-S are not supported by the model, i.e. that supports_constraint returns false.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.AddConstraintNotAllowed","page":"Errors","title":"MathOptInterface.AddConstraintNotAllowed","text":"struct AddConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet} <: NotAllowedError\n message::String # Human-friendly explanation why the attribute cannot be set\nend\n\nAn error indicating that constraints of type F-in-S are supported (see supports_constraint) but cannot be added.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.ModifyConstraintNotAllowed","page":"Errors","title":"MathOptInterface.ModifyConstraintNotAllowed","text":"struct ModifyConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet,\n C<:AbstractFunctionModification} <: NotAllowedError\n constraint_index::ConstraintIndex{F, S}\n change::C\n message::String\nend\n\nAn error indicating that the constraint modification change cannot be applied to the constraint of index ci.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.ModifyObjectiveNotAllowed","page":"Errors","title":"MathOptInterface.ModifyObjectiveNotAllowed","text":"struct ModifyObjectiveNotAllowed{C<:AbstractFunctionModification} <: NotAllowedError\n change::C\n message::String\nend\n\nAn error indicating that the objective modification change cannot be applied to the objective.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.DeleteNotAllowed","page":"Errors","title":"MathOptInterface.DeleteNotAllowed","text":"struct DeleteNotAllowed{IndexType <: Index} <: NotAllowedError\n index::IndexType\n message::String\nend\n\nAn error indicating that the index index cannot be deleted.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.UnsupportedSubmittable","page":"Errors","title":"MathOptInterface.UnsupportedSubmittable","text":"struct UnsupportedSubmittable{SubmitType} <: UnsupportedError\n sub::SubmitType\n message::String\nend\n\nAn error indicating that the submittable sub is not supported by the model, i.e. that supports returns false.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.SubmitNotAllowed","page":"Errors","title":"MathOptInterface.SubmitNotAllowed","text":"struct SubmitNotAllowed{SubmitTyp<:AbstractSubmittable} <: NotAllowedError\n sub::SubmitType\n message::String\nend\n\nAn error indicating that the submittable sub is supported (see supports) but cannot be added for some reason (see the error string).\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.UnsupportedNonlinearOperator","page":"Errors","title":"MathOptInterface.UnsupportedNonlinearOperator","text":"UnsupportedNonlinearOperator(head::Symbol[, message::String]) <: UnsupportedError\n\nAn error thrown by optimizers if they do not support the operator head in a ScalarNonlinearFunction.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> throw(MOI.UnsupportedNonlinearOperator(:black_box))\nERROR: MathOptInterface.UnsupportedNonlinearOperator: The nonlinear operator `:black_box` is not supported by the model.\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"Note that setting the ConstraintFunction of a VariableIndex constraint is not allowed:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"SettingVariableIndexNotAllowed","category":"page"},{"location":"reference/errors/#MathOptInterface.SettingVariableIndexNotAllowed","page":"Errors","title":"MathOptInterface.SettingVariableIndexNotAllowed","text":"SettingVariableIndexNotAllowed()\n\nError type that should be thrown when the user calls set to change the ConstraintFunction of a VariableIndex constraint.\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/","page":"Variables","title":"Variables","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/variables/#Variables","page":"Variables","title":"Variables","text":"","category":"section"},{"location":"reference/variables/#Functions","page":"Variables","title":"Functions","text":"","category":"section"},{"location":"reference/variables/","page":"Variables","title":"Variables","text":"add_variable\nadd_variables\nadd_constrained_variable\nadd_constrained_variables\nsupports_add_constrained_variable\nsupports_add_constrained_variables\nis_valid(::ModelLike,::VariableIndex)\ndelete(::ModelLike, ::VariableIndex)\ndelete(::ModelLike, ::Vector{VariableIndex})","category":"page"},{"location":"reference/variables/#MathOptInterface.add_variable","page":"Variables","title":"MathOptInterface.add_variable","text":"add_variable(model::ModelLike)::VariableIndex\n\nAdd a scalar variable to the model, returning a variable index.\n\nA AddVariableNotAllowed error is thrown if adding variables cannot be done in the current state of the model model.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.add_variables","page":"Variables","title":"MathOptInterface.add_variables","text":"add_variables(model::ModelLike, n::Int)::Vector{VariableIndex}\n\nAdd n scalar variables to the model, returning a vector of variable indices.\n\nA AddVariableNotAllowed error is thrown if adding variables cannot be done in the current state of the model model.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.add_constrained_variable","page":"Variables","title":"MathOptInterface.add_constrained_variable","text":"add_constrained_variable(\n model::ModelLike,\n set::AbstractScalarSet\n)::Tuple{MOI.VariableIndex,\n MOI.ConstraintIndex{MOI.VariableIndex, typeof(set)}}\n\nAdd to model a scalar variable constrained to belong to set, returning the index of the variable created and the index of the constraint constraining the variable to belong to set.\n\nBy default, this function falls back to creating a free variable with add_variable and then constraining it to belong to set with add_constraint.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.add_constrained_variables","page":"Variables","title":"MathOptInterface.add_constrained_variables","text":"add_constrained_variables(\n model::ModelLike,\n sets::AbstractVector{<:AbstractScalarSet}\n)::Tuple{\n Vector{MOI.VariableIndex},\n Vector{MOI.ConstraintIndex{MOI.VariableIndex,eltype(sets)}},\n}\n\nAdd to model scalar variables constrained to belong to sets, returning the indices of the variables created and the indices of the constraints constraining the variables to belong to each set in sets. That is, if it returns variables and constraints, constraints[i] is the index of the constraint constraining variable[i] to belong to sets[i].\n\nBy default, this function falls back to calling add_constrained_variable on each set.\n\n\n\n\n\nadd_constrained_variables(\n model::ModelLike,\n set::AbstractVectorSet,\n)::Tuple{\n Vector{MOI.VariableIndex},\n MOI.ConstraintIndex{MOI.VectorOfVariables,typeof(set)},\n}\n\nAdd to model a vector of variables constrained to belong to set, returning the indices of the variables created and the index of the constraint constraining the vector of variables to belong to set.\n\nBy default, this function falls back to creating free variables with add_variables and then constraining it to belong to set with add_constraint.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.supports_add_constrained_variable","page":"Variables","title":"MathOptInterface.supports_add_constrained_variable","text":"supports_add_constrained_variable(\n model::ModelLike,\n S::Type{<:AbstractScalarSet}\n)::Bool\n\nReturn a Bool indicating whether model supports constraining a variable to belong to a set of type S either on creation of the variable with add_constrained_variable or after the variable is created with add_constraint.\n\nBy default, this function falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VariableIndex, S) which is the correct definition for most models.\n\nExample\n\nSuppose that a solver supports only two kind of variables: binary variables and continuous variables with a lower bound. If the solver decides not to support VariableIndex-in-Binary and VariableIndex-in-GreaterThan constraints, it only has to implement add_constrained_variable for these two sets which prevents the user to add both a binary constraint and a lower bound on the same variable. Moreover, if the user adds a VariableIndex-in-GreaterThan constraint, implementing this interface (i.e., supports_add_constrained_variables) enables the constraint to be transparently bridged into a supported constraint.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.supports_add_constrained_variables","page":"Variables","title":"MathOptInterface.supports_add_constrained_variables","text":"supports_add_constrained_variables(\n model::ModelLike,\n S::Type{<:AbstractVectorSet}\n)::Bool\n\nReturn a Bool indicating whether model supports constraining a vector of variables to belong to a set of type S either on creation of the vector of variables with add_constrained_variables or after the variable is created with add_constraint.\n\nBy default, if S is Reals then this function returns true and otherwise, it falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VectorOfVariables, S) which is the correct definition for most models.\n\nExample\n\nIn the standard conic form (see Duality), the variables are grouped into several cones and the constraints are affine equality constraints. If Reals is not one of the cones supported by the solvers then it needs to implement supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false as free variables are not supported. The solvers should then implement supports_add_constrained_variables(::Optimizer, ::Type{<:SupportedCones}) = true where SupportedCones is the union of all cone types that are supported; it does not have to implement the method supports_constraint(::Type{VectorOfVariables}, Type{<:SupportedCones}) as it should return false and it's the default. This prevents the user to constrain the same variable in two different cones. When a VectorOfVariables-in-S is added, the variables of the vector have already been created so they already belong to given cones. If bridges are enabled, the constraint will therefore be bridged by adding slack variables in S and equality constraints ensuring that the slack variables are equal to the corresponding variables of the given constraint function.\n\nNote that there may also be sets for which !supports_add_constrained_variables(model, S) and supports_constraint(model, MOI.VectorOfVariables, S). For instance, suppose a solver supports positive semidefinite variable constraints and two types of variables: binary variables and nonnegative variables. Then the solver should support adding VectorOfVariables-in-PositiveSemidefiniteConeTriangle constraints, but it should not support creating variables constrained to belong to the PositiveSemidefiniteConeTriangle because the variables in PositiveSemidefiniteConeTriangle should first be created as either binary or non-negative.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.is_valid-Tuple{MathOptInterface.ModelLike, MathOptInterface.VariableIndex}","page":"Variables","title":"MathOptInterface.is_valid","text":"is_valid(model::ModelLike, index::Index)::Bool\n\nReturn a Bool indicating whether this index refers to a valid object in the model model.\n\n\n\n\n\n","category":"method"},{"location":"reference/variables/#MathOptInterface.delete-Tuple{MathOptInterface.ModelLike, MathOptInterface.VariableIndex}","page":"Variables","title":"MathOptInterface.delete","text":"delete(model::ModelLike, index::Index)\n\nDelete the referenced object from the model. Throw DeleteNotAllowed if if index cannot be deleted.\n\nThe following modifications also take effect if Index is VariableIndex:\n\nIf index used in the objective function, it is removed from the function, i.e., it is substituted for zero.\nFor each func-in-set constraint of the model:\nIf func isa VariableIndex and func == index then the constraint is deleted.\nIf func isa VectorOfVariables and index in func.variables then\nif length(func.variables) == 1 is one, the constraint is deleted;\nif length(func.variables) > 1 and supports_dimension_update(set) then then the variable is removed from func and set is replaced by update_dimension(set, MOI.dimension(set) - 1).\nOtherwise, a DeleteNotAllowed error is thrown.\nOtherwise, the variable is removed from func, i.e., it is substituted for zero.\n\n\n\n\n\n","category":"method"},{"location":"reference/variables/#MathOptInterface.delete-Tuple{MathOptInterface.ModelLike, Vector{MathOptInterface.VariableIndex}}","page":"Variables","title":"MathOptInterface.delete","text":"delete(model::ModelLike, indices::Vector{R<:Index}) where {R}\n\nDelete the referenced objects in the vector indices from the model. It may be assumed that R is a concrete type. The default fallback sequentially deletes the individual items in indices, although specialized implementations may be more efficient.\n\n\n\n\n\n","category":"method"},{"location":"reference/variables/#Attributes","page":"Variables","title":"Attributes","text":"","category":"section"},{"location":"reference/variables/","page":"Variables","title":"Variables","text":"AbstractVariableAttribute\nVariableName\nVariablePrimalStart\nVariablePrimal\nVariableBasisStatus","category":"page"},{"location":"reference/variables/#MathOptInterface.AbstractVariableAttribute","page":"Variables","title":"MathOptInterface.AbstractVariableAttribute","text":"AbstractVariableAttribute\n\nAbstract supertype for attribute objects that can be used to set or get attributes (properties) of variables in the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/#MathOptInterface.VariableName","page":"Variables","title":"MathOptInterface.VariableName","text":"VariableName()\n\nA variable attribute for a string identifying the variable. It is valid for two variables to have the same name; however, variables with duplicate names cannot be looked up using get. It has a default value of \"\" if not set`.\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/#MathOptInterface.VariablePrimalStart","page":"Variables","title":"MathOptInterface.VariablePrimalStart","text":"VariablePrimalStart()\n\nA variable attribute for the initial assignment to some primal variable's value that the optimizer may use to warm-start the solve. May be a number or nothing (unset).\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/#MathOptInterface.VariablePrimal","page":"Variables","title":"MathOptInterface.VariablePrimal","text":"VariablePrimal(result_index::Int = 1)\n\nA variable attribute for the assignment to some primal variable's value in result result_index. If result_index is omitted, it is 1 by default.\n\nIf the solver does not have a primal value for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the VariablePrimal attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/#MathOptInterface.VariableBasisStatus","page":"Variables","title":"MathOptInterface.VariableBasisStatus","text":"VariableBasisStatus(result_index::Int = 1)\n\nA variable attribute for the BasisStatusCode of a variable in result result_index, with respect to an available optimal solution basis.\n\nIf the solver does not have a basis statue for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the VariableBasisStatus attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#List-of-bridges","page":"List of bridges","title":"List of bridges","text":"","category":"section"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"This section describes the Bridges.AbstractBridges that are implemented in MathOptInterface.","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#constraint_bridges_ref","page":"List of bridges","title":"Constraint bridges","text":"","category":"section"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"These bridges are subtypes of Bridges.Constraint.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"Bridges.Constraint.GreaterToIntervalBridge\nBridges.Constraint.LessToIntervalBridge\nBridges.Constraint.GreaterToLessBridge\nBridges.Constraint.LessToGreaterBridge\nBridges.Constraint.NonnegToNonposBridge\nBridges.Constraint.NonposToNonnegBridge\nBridges.Constraint.VectorizeBridge\nBridges.Constraint.ScalarizeBridge\nBridges.Constraint.ScalarSlackBridge\nBridges.Constraint.VectorSlackBridge\nBridges.Constraint.ScalarFunctionizeBridge\nBridges.Constraint.VectorFunctionizeBridge\nBridges.Constraint.ToScalarQuadraticBridge\nBridges.Constraint.ToVectorQuadraticBridge\nBridges.Constraint.ToScalarNonlinearBridge\nBridges.Constraint.FunctionConversionBridge\nBridges.Constraint.SplitComplexEqualToBridge\nBridges.Constraint.SplitComplexZerosBridge\nBridges.Constraint.SplitHyperRectangleBridge\nBridges.Constraint.SplitIntervalBridge\nBridges.Constraint.SOCtoRSOCBridge\nBridges.Constraint.RSOCtoSOCBridge\nBridges.Constraint.SOCtoNonConvexQuadBridge\nBridges.Constraint.RSOCtoNonConvexQuadBridge\nBridges.Constraint.QuadtoSOCBridge\nBridges.Constraint.SOCtoPSDBridge\nBridges.Constraint.RSOCtoPSDBridge\nBridges.Constraint.NormInfinityBridge\nBridges.Constraint.NormOneBridge\nBridges.Constraint.NormToPowerBridge\nBridges.Constraint.NormOneConeToNormConeBridge\nBridges.Constraint.SecondOrderConeToNormConeBridge\nBridges.Constraint.NormInfinityConeToNormConeBridge\nBridges.Constraint.GeoMeantoRelEntrBridge\nBridges.Constraint.GeoMeanToPowerBridge\nBridges.Constraint.GeoMeanBridge\nBridges.Constraint.RelativeEntropyBridge\nBridges.Constraint.NormSpectralBridge\nBridges.Constraint.NormNuclearBridge\nBridges.Constraint.SquareBridge\nBridges.Constraint.HermitianToSymmetricPSDBridge\nBridges.Constraint.SetDotScalingBridge\nBridges.Constraint.SetDotInverseScalingBridge\nBridges.Constraint.RootDetBridge\nBridges.Constraint.LogDetBridge\nBridges.Constraint.IndicatorActiveOnFalseBridge\nBridges.Constraint.IndicatorGreaterToLessThanBridge\nBridges.Constraint.IndicatorLessToGreaterThanBridge\nBridges.Constraint.IndicatorSOS1Bridge\nBridges.Constraint.SemiToBinaryBridge\nBridges.Constraint.ZeroOneBridge\nBridges.Constraint.IntegerToZeroOneBridge\nBridges.Constraint.NumberConversionBridge\nBridges.Constraint.AllDifferentToCountDistinctBridge\nBridges.Constraint.ReifiedAllDifferentToCountDistinctBridge\nBridges.Constraint.BinPackingToMILPBridge\nBridges.Constraint.CircuitToMILPBridge\nBridges.Constraint.CountAtLeastToCountBelongsBridge\nBridges.Constraint.CountBelongsToMILPBridge\nBridges.Constraint.CountDistinctToMILPBridge\nBridges.Constraint.ReifiedCountDistinctToMILPBridge\nBridges.Constraint.CountGreaterThanToMILPBridge\nBridges.Constraint.TableToMILPBridge","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GreaterToIntervalBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GreaterToIntervalBridge","text":"GreaterToIntervalBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nGreaterToIntervalBridge implements the following reformulations:\n\nf(x) ge l into f(x) in l infty)\n\nSource node\n\nGreaterToIntervalBridge supports:\n\nF in MOI.GreaterThan{T}\n\nTarget nodes\n\nGreaterToIntervalBridge creates:\n\nF in MOI.Interval{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.LessToIntervalBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.LessToIntervalBridge","text":"LessToIntervalBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nLessToIntervalBridge implements the following reformulations:\n\nf(x) le u into f(x) in (-infty u\n\nSource node\n\nLessToIntervalBridge supports:\n\nF in MOI.LessThan{T}\n\nTarget nodes\n\nLessToIntervalBridge creates:\n\nF in MOI.Interval{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GreaterToLessBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GreaterToLessBridge","text":"GreaterToLessBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nGreaterToLessBridge implements the following reformulation:\n\nf(x) ge l into -f(x) le -l\n\nSource node\n\nGreaterToLessBridge supports:\n\nG in MOI.GreaterThan{T}\n\nTarget nodes\n\nGreaterToLessBridge creates:\n\nF in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.LessToGreaterBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.LessToGreaterBridge","text":"LessToGreaterBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nLessToGreaterBridge implements the following reformulation:\n\nf(x) le u into -f(x) ge -u\n\nSource node\n\nLessToGreaterBridge supports:\n\nG in MOI.LessThan{T}\n\nTarget nodes\n\nLessToGreaterBridge creates:\n\nF in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NonnegToNonposBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NonnegToNonposBridge","text":"NonnegToNonposBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNonnegToNonposBridge implements the following reformulation:\n\nf(x) in mathbbR_+ into -f(x) in mathbbR_-\n\nSource node\n\nNonnegToNonposBridge supports:\n\nG in MOI.Nonnegatives\n\nTarget nodes\n\nNonnegToNonposBridge creates:\n\nF in MOI.Nonpositives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NonposToNonnegBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NonposToNonnegBridge","text":"NonposToNonnegBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNonposToNonnegBridge implements the following reformulation:\n\nf(x) in mathbbR_- into -f(x) in mathbbR_+\n\nSource node\n\nNonposToNonnegBridge supports:\n\nG in MOI.Nonpositives\n\nTarget nodes\n\nNonposToNonnegBridge creates:\n\nF in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.VectorizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.VectorizeBridge","text":"VectorizeBridge{T,F,S,G} <: Bridges.Constraint.AbstractBridge\n\nVectorizeBridge implements the following reformulations:\n\ng(x) ge a into g(x) - a in mathbbR_+\ng(x) le a into g(x) - a in mathbbR_-\ng(x) == a into g(x) - a in 0\n\nwhere T is the coefficient type of g(x) - a.\n\nSource node\n\nVectorizeBridge supports:\n\nG in MOI.GreaterThan{T}\nG in MOI.LessThan{T}\nG in MOI.EqualTo{T}\n\nTarget nodes\n\nVectorizeBridge creates:\n\nF in S, where S is one of MOI.Nonnegatives, MOI.Nonpositives, MOI.Zeros depending on the type of the input set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ScalarizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ScalarizeBridge","text":"ScalarizeBridge{T,F,S}\n\nScalarizeBridge implements the following reformulations:\n\nf(x) - a in mathbbR_+ into f_i(x) ge a_i for all i\nf(x) - a in mathbbR_- into f_i(x) le a_i for all i\nf(x) - a in 0 into f_i(x) == a_i for all i\n\nSource node\n\nScalarizeBridge supports:\n\nG in MOI.Nonnegatives{T}\nG in MOI.Nonpositives{T}\nG in MOI.Zeros{T}\n\nTarget nodes\n\nScalarizeBridge creates:\n\nF in S, where S is one of MOI.GreaterThan{T}, MOI.LessThan{T}, and MOI.EqualTo{T}, depending on the type of the input set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ScalarSlackBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ScalarSlackBridge","text":"ScalarSlackBridge{T,F,S} <: Bridges.Constraint.AbstractBridge\n\nScalarSlackBridge implements the following reformulation:\n\nf(x) in S into f(x) - y == 0 and y in S\n\nSource node\n\nScalarSlackBridge supports:\n\nG in S, where G is not MOI.VariableIndex and S is not MOI.EqualTo\n\nTarget nodes\n\nScalarSlackBridge creates:\n\nF in MOI.EqualTo{T}\nMOI.VariableIndex in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.VectorSlackBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.VectorSlackBridge","text":"VectorSlackBridge{T,F,S} <: Bridges.Constraint.AbstractBridge\n\nVectorSlackBridge implements the following reformulation:\n\nf(x) in S into f(x) - y in 0 and y in S\n\nSource node\n\nVectorSlackBridge supports:\n\nG in S, where G is not MOI.VectorOfVariables and S is not MOI.Zeros\n\nTarget nodes\n\nVectorSlackBridge creates:\n\nF in MOI.Zeros\nMOI.VectorOfVariables in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ScalarFunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ScalarFunctionizeBridge","text":"ScalarFunctionizeBridge{T,S} = FunctionConversionBridge{T,MOI.ScalarAffineFunction{T},MOI.VariableIndex,S}\n\nScalarFunctionizeBridge implements the following reformulations:\n\nx in S into 1x + 0 in S\n\nSource node\n\nScalarFunctionizeBridge supports:\n\nMOI.VariableIndex in S\n\nTarget nodes\n\nScalarFunctionizeBridge creates:\n\nMOI.ScalarAffineFunction{T} in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.VectorFunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.VectorFunctionizeBridge","text":"VectorFunctionizeBridge{T,S} = FunctionConversionBridge{T,MOI.VectorAffineFunction{T},S}\n\nVectorFunctionizeBridge implements the following reformulations:\n\nx in S into Ix + 0 in S\n\nSource node\n\nVectorFunctionizeBridge supports:\n\nMOI.VectorOfVariables in S\n\nTarget nodes\n\nVectorFunctionizeBridge creates:\n\nMOI.VectorAffineFunction{T} in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ToScalarQuadraticBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ToScalarQuadraticBridge","text":"ToScalarQuadraticBridge{T,G,S} <: AbstractFunctionConversionBridge{G,S}\n\nToScalarQuadraticBridge implements the following reformulation:\n\ng(x) in S into f(x) in S\n\nwhere g is an abstract scalar function and f is a MOI.ScalarQuadraticFunction.\n\nSource node\n\nToScalarQuadraticBridge supports:\n\nG<:AbstractScalarFunction in S\n\nTarget nodes\n\nToScalarQuadraticBridge creates:\n\nMOI.ScalarQuadraticFunction in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ToVectorQuadraticBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ToVectorQuadraticBridge","text":"ToVectorQuadraticBridge{T,G,S} <: AbstractFunctionConversionBridge{G,S}\n\nToVectorQuadraticBridge implements the following reformulation:\n\ng(x) in S into f(x) in S\n\nwhere g is an abstract vector function and f is a MOI.VectorQuadraticFunction.\n\nSource node\n\nToVectorQuadraticBridge supports:\n\nG<:AbstractVectorFunction in S\n\nTarget nodes\n\nToVectorQuadraticBridge creates:\n\nMOI.VectorQuadraticFunction in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ToScalarNonlinearBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ToScalarNonlinearBridge","text":"ToScalarNonlinearBridge{T,G,S} <: AbstractFunctionConversionBridge{G,S}\n\nToScalarNonlinearBridge implements the following reformulation:\n\ng(x) in S into f(x) in S\n\nwhere g is an abstract scalar function and f is a MOI.ScalarNonlinearFunction.\n\nSource node\n\nToScalarNonlinearBridge supports:\n\nG<:AbstractScalarFunction in S\n\nTarget nodes\n\nToScalarNonlinearBridge creates:\n\nMOI.ScalarNonlinearFunction in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.FunctionConversionBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.FunctionConversionBridge","text":"FunctionConversionBridge{T,F,G,S} <: AbstractFunctionConversionBridge{G,S}\n\nFunctionConversionBridge implements the following reformulations:\n\ng(x) in S into f(x) in S\n\nfor these pairs of functions:\n\nMOI.ScalarAffineFunctionto [MOI.ScalarQuadraticFunction`](@ref)\nMOI.ScalarQuadraticFunction to MOI.ScalarNonlinearFunction\nMOI.VectorAffineFunction to MOI.VectorQuadraticFunction\n\nSource node\n\nFunctionConversionBridge supports:\n\nG in S\n\nTarget nodes\n\nFunctionConversionBridge creates:\n\nF in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SplitComplexEqualToBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SplitComplexEqualToBridge","text":"SplitComplexEqualToBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nSplitComplexEqualToBridge implements the following reformulation:\n\nf(x) + g(x) * im = a + b * im into f(x) = a and g(x) = b\n\nSource node\n\nSplitComplexEqualToBridge supports:\n\nG in MOI.EqualTo{Complex{T}}\n\nwhere G is a function with Complex coefficients.\n\nTarget nodes\n\nSplitComplexEqualToBridge creates:\n\nF in MOI.EqualTo{T}\n\nwhere F is the type of the real/imaginary part of G.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SplitComplexZerosBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SplitComplexZerosBridge","text":"SplitComplexZerosBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nSplitComplexZerosBridge implements the following reformulation:\n\nf(x) in 0^n into textRe(f(x)) in 0^n and textIm(f(x)) in 0^n\n\nSource node\n\nSplitComplexZerosBridge supports:\n\nG in MOI.Zeros\n\nwhere G is a function with Complex coefficients.\n\nTarget nodes\n\nSplitComplexZerosBridge creates:\n\nF in MOI.Zeros\n\nwhere F is the type of the real/imaginary part of G.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SplitHyperRectangleBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SplitHyperRectangleBridge","text":"SplitHyperRectangleBridge{T,G,F} <: Bridges.Constraint.AbstractBridge\n\nSplitHyperRectangleBridge implements the following reformulation:\n\nf(x) in textsfHyperRectangle(l u) to f(x) - l u - f(x) in mathbbR_+.\n\nSource node\n\nSplitHyperRectangleBridge supports:\n\nF in MOI.HyperRectangle\n\nTarget nodes\n\nSplitHyperRectangleBridge creates:\n\nG in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SplitIntervalBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SplitIntervalBridge","text":"SplitIntervalBridge{T,F,S,LS,US} <: Bridges.Constraint.AbstractBridge\n\nSplitIntervalBridge implements the following reformulations:\n\nl le f(x) le u into f(x) ge l and f(x) le u\nf(x) = b into f(x) ge b and f(x) le b\nf(x) in 0 into f(x) in mathbbR_+ and f(x) in mathbbR_-\n\nSource node\n\nSplitIntervalBridge supports:\n\nF in MOI.Interval{T}\nF in MOI.EqualTo{T}\nF in MOI.Zeros\n\nTarget nodes\n\nSplitIntervalBridge creates:\n\nF in MOI.LessThan{T}\nF in MOI.GreaterThan{T}\n\nor\n\nF in MOI.Nonnegatives\nF in MOI.Nonpositives\n\nnote: Note\nIf T<:AbstractFloat and S is MOI.Interval{T} then no lower (resp. upper) bound constraint is created if the lower (resp. upper) bound is typemin(T) (resp. typemax(T)). Similarly, when MOI.ConstraintSet is set, a lower or upper bound constraint may be deleted or created accordingly.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SOCtoRSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOCtoRSOCBridge","text":"SOCtoRSOCBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nSOCtoRSOCBridge implements the following reformulation:\n\nx_2 le t into (t+x_1)(t-x_1)ge (x_2ldotsx_N)_2^2\n\nAssumptions\n\nSOCtoRSOCBridge assumes that the length of x is at least one.\n\nSource node\n\nSOCtoRSOCBridge supports:\n\nG in MOI.SecondOrderCone\n\nTarget node\n\nSOCtoRSOCBridge creates:\n\nF in MOI.RotatedSecondOrderCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RSOCtoSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RSOCtoSOCBridge","text":"RSOCtoSOCBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nRSOCtoSOCBridge implements the following reformulation:\n\nx_2^2 le 2tu into fract - usqrt 2 x_2 le fract + usqrt 2\n\nSource node\n\nRSOCtoSOCBridge supports:\n\nG in MOI.RotatedSecondOrderCone\n\nTarget node\n\nRSOCtoSOCBridge creates:\n\nF in MOI.SecondOrderCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SOCtoNonConvexQuadBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOCtoNonConvexQuadBridge","text":"SOCtoNonConvexQuadBridge{T} <: Bridges.Constraint.AbstractBridge\n\nSOCtoNonConvexQuadBridge implements the following reformulations:\n\nx_2 le t into sum x^2 - t^2 le 0 and 1t + 0 ge 0\n\nThe MOI.ScalarAffineFunction 1t + 0 is used in case the variable has other bound constraints.\n\nwarning: Warning\nThis transformation starts from a convex constraint and creates a non-convex constraint. Unless the solver has explicit support for detecting second-order cones in quadratic form, this may (wrongly) be interpreted by the solver as being non-convex. Therefore, this bridge is not added automatically by MOI.Bridges.full_bridge_optimizer. Care is recommended when adding this bridge to a optimizer.\n\nSource node\n\nSOCtoNonConvexQuadBridge supports:\n\nMOI.VectorOfVariables in MOI.SecondOrderCone\n\nTarget nodes\n\nSOCtoNonConvexQuadBridge creates:\n\nMOI.ScalarQuadraticFunction{T} in MOI.LessThan{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RSOCtoNonConvexQuadBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RSOCtoNonConvexQuadBridge","text":"RSOCtoNonConvexQuadBridge{T} <: Bridges.Constraint.AbstractBridge\n\nRSOCtoNonConvexQuadBridge implements the following reformulations:\n\nx_2^2 le 2tu into sum x^2 - 2tu le 0, 1t + 0 ge 0, and 1u + 0 ge 0.\n\nThe MOI.ScalarAffineFunctions 1t + 0 and 1u + 0 are used in case the variables have other bound constraints.\n\nwarning: Warning\nThis transformation starts from a convex constraint and creates a non-convex constraint. Unless the solver has explicit support for detecting rotated second-order cones in quadratic form, this may (wrongly) be interpreted by the solver as being non-convex. Therefore, this bridge is not added automatically by MOI.Bridges.full_bridge_optimizer. Care is recommended when adding this bridge to a optimizer.\n\nSource node\n\nRSOCtoNonConvexQuadBridge supports:\n\nMOI.VectorOfVariables in MOI.RotatedSecondOrderCone\n\nTarget nodes\n\nRSOCtoNonConvexQuadBridge creates:\n\nMOI.ScalarQuadraticFunction{T} in MOI.LessThan{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.QuadtoSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.QuadtoSOCBridge","text":"QuadtoSOCBridge{T} <: Bridges.Constraint.AbstractBridge\n\nQuadtoSOCBridge converts quadratic inequalities\n\nfrac12x^T Q x + a^T x le ub\n\ninto MOI.RotatedSecondOrderCone constraints, but it only applies when Q is positive definite.\n\nThis is because, if Q is positive definite, there exists U such that Q = U^T U, and so the inequality can then be rewritten as;\n\nU x_2^2 le 2 (-a^T x + ub)\n\nTherefore, QuadtoSOCBridge implements the following reformulations:\n\nfrac12x^T Q x + a^T x le ub into (1 -a^T x + ub Ux) in RotatedSecondOrderCone where Q = U^T U\nfrac12x^T Q x + a^T x ge lb into (1 a^T x - lb Ux) in RotatedSecondOrderCone where -Q = U^T U\n\nSource node\n\nQuadtoSOCBridge supports:\n\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\n\nTarget nodes\n\nRelativeEntropyBridge creates:\n\nMOI.VectorAffineFunction{T} in MOI.RotatedSecondOrderCone\n\nErrors\n\nThis bridge errors if Q is not positive definite.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SOCtoPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOCtoPSDBridge","text":"SOCtoPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nSOCtoPSDBridge implements the following reformulation:\n\nx_2 le t into leftbeginarrayc ct x^top x t mathbfIendarrayrightsucceq 0\n\nwarning: Warning\nThis bridge is not added by default by MOI.Bridges.full_bridge_optimizer because bridging second order cone constraints to semidefinite constraints can be achieved by the SOCtoRSOCBridge followed by the RSOCtoPSDBridge, while creating a smaller semidefinite constraint.\n\nSource node\n\nSOCtoPSDBridge supports:\n\nG in MOI.SecondOrderCone\n\nTarget nodes\n\nSOCtoPSDBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RSOCtoPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RSOCtoPSDBridge","text":"RSOCtoPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nRSOCtoPSDBridge implements the following reformulation:\n\nx_2^2 le 2tcdot u into leftbeginarrayc ct x^top x 2tu mathbfIendarrayrightsucceq 0\n\nSource node\n\nRSOCtoPSDBridge supports:\n\nG in MOI.RotatedSecondOrderCone\n\nTarget nodes\n\nRSOCtoPSDBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormInfinityBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormInfinityBridge","text":"NormInfinityBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNormInfinityBridge implements the following reformulation:\n\nx_infty le t into t - x_i t + x_i in mathbbR_+.\n\nSource node\n\nNormInfinityBridge supports:\n\nG in MOI.NormInfinityCone{T}\n\nTarget nodes\n\nNormInfinityBridge creates:\n\nF in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormOneBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormOneBridge","text":"NormOneBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNormOneBridge implements the following reformulation:\n\nsum x_i le t into t - sum y_i y_i - x_i y_i + x_i in mathbbR_+.\n\nSource node\n\nNormOneBridge supports:\n\nG in MOI.NormOneCone{T}\n\nTarget nodes\n\nNormOneBridge creates:\n\nF in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormToPowerBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormToPowerBridge","text":"NormToPowerBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nNormToPowerBridge implements the following reformulation:\n\n(t x) in NormCone(p 1+d) into (r_i t x_i) in PowerCone(1 p) for all i, and sumlimits_i r_i == t.\n\nFor details, see Alizadeh, F., and Goldfarb, D. (2001). \"Second-order cone programming.\" Mathematical Programming, Series B, 95:3-51.\n\nSource node\n\nNormToPowerBridge supports:\n\nF in MOI.NormCone\n\nTarget nodes\n\nNormToPowerBridge creates:\n\nF in MOI.PowerCone{T}\nMOI.ScalarAffineFunction in MOI.EqualTo\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormOneConeToNormConeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormOneConeToNormConeBridge","text":"NormOneConeToNormConeBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nNormOneConeToNormConeBridge implements the following reformulations:\n\n(t x) in NormOneCone(d) into (t x) in NormCone(1 d)\n\nSource node\n\nNormOneConeToNormConeBridge supports:\n\nF in MOI.NormOneCone\n\nTarget nodes\n\nNormOneConeToNormConeBridge creates:\n\nF in MOI.NormCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SecondOrderConeToNormConeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SecondOrderConeToNormConeBridge","text":"SecondOrderConeToNormConeBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nSecondOrderConeToNormConeBridge implements the following reformulations:\n\n(t x) in SecondOrderCone(d) into (t x) in NormCone(2 d)\n\nSource node\n\nSecondOrderConeToNormConeBridge supports:\n\nF in MOI.SecondOrderCone\n\nTarget nodes\n\nSecondOrderConeToNormConeBridge creates:\n\nF in MOI.NormCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormInfinityConeToNormConeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormInfinityConeToNormConeBridge","text":"NormInfinityConeToNormConeBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nNormInfinityConeToNormConeBridge implements the following reformulations:\n\n(t x) in NormInfinityCone(d) into (t x) in NormCone(Inf d)\n\nSource node\n\nNormInfinityConeToNormConeBridge supports:\n\nF in MOI.NormInfinityCone\n\nTarget nodes\n\nNormInfinityConeToNormConeBridge creates:\n\nF in MOI.NormCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GeoMeantoRelEntrBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GeoMeantoRelEntrBridge","text":"GeoMeantoRelEntrBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nGeoMeantoRelEntrBridge implements the following reformulation:\n\n(u w) in GeometricMeanCone into (0 w (u + y)mathbf1)in RelativeEntropyCone and y ge 0\n\nSource node\n\nGeoMeantoRelEntrBridge supports:\n\nH in MOI.GeometricMeanCone\n\nTarget nodes\n\nGeoMeantoRelEntrBridge creates:\n\nG in MOI.RelativeEntropyCone\nF in MOI.Nonnegatives\n\nDerivation\n\nThe derivation of the bridge is as follows:\n\nbeginaligned\n(u w) in GeometricMeanCone iff u le left(prod_i=1^n w_iright)^1n \niff 0 le u + y le left(prod_i=1^n w_iright)^1n y ge 0 \niff 1 le fracleft(prod_i=1^n w_iright)^1nu + y y ge 0 \niff 1 le left(prod_i=1^n fracw_iu + yright)^1n y ge 0 \niff 0 le sum_i=1^n logleft(fracw_iu + yright) y ge 0 \niff 0 ge sum_i=1^n logleft(fracu + yw_iright) y ge 0 \niff 0 ge sum_i=1^n (u + y) logleft(fracu + yw_iright) y ge 0 \niff (0 w (u + y)mathbf1) in RelativeEntropyCone y ge 0 \nendaligned\n\nThis derivation assumes that u + y 0, which is enforced by the relative entropy cone.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GeoMeanToPowerBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GeoMeanToPowerBridge","text":"GeoMeanToPowerBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nGeoMeanToPowerBridge implements the following reformulation:\n\n(y x) in GeometricMeanCone(1+d) into (x_1 t y) in PowerCone(1d) and (t x_2 x_d) in GeometricMeanCone(d), which is then recursively expanded into more PowerCone constraints.\n\nSource node\n\nGeoMeanToPowerBridge supports:\n\nF in MOI.GeometricMeanCone\n\nTarget nodes\n\nGeoMeanToPowerBridge creates:\n\nF in MOI.PowerCone{T}\nMOI.VectorOfVariables in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GeoMeanBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GeoMeanBridge","text":"GeoMeanBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nGeoMeanBridge implements a reformulation from MOI.GeometricMeanCone into MOI.RotatedSecondOrderCone.\n\nThe reformulation is best described in an example.\n\nConsider the cone of dimension 4:\n\nt le sqrt3x_1 x_2 x_3\n\nThis can be rewritten as exists y ge 0 such that:\n\nbeginalign*\n t le y\n y^4 le x_1 x_2 x_3 y\nendalign*\n\nNote that we need to create y and not use t^4 directly because t is allowed to be negative.\n\nThis is equivalent to:\n\nbeginalign*\n t le fracy_1sqrt4\n y_1^2 le 2y_2 y_3\n y_2^2 le 2x_1 x_2 \n y_3^2 le 2x_3(y_1sqrt4) \n y ge 0\nendalign*\n\nMore generally, you can show how the geometric mean code is recursively expanded into a set of new variables y in MOI.Nonnegatives, a set of MOI.RotatedSecondOrderCone constraints, and a MOI.LessThan constraint between t and y_1.\n\nSource node\n\nGeoMeanBridge supports:\n\nH in MOI.GeometricMeanCone\n\nTarget nodes\n\nGeoMeanBridge creates:\n\nF in MOI.LessThan{T}\nG in MOI.RotatedSecondOrderCone\nG in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RelativeEntropyBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RelativeEntropyBridge","text":"RelativeEntropyBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nRelativeEntropyBridge implements the following reformulation that converts a MOI.RelativeEntropyCone into an MOI.ExponentialCone:\n\nu ge sum_i=1^n w_i log left(fracw_iv_iright) into y_i ge 0, u ge sum_i=1^n y_i, and (-y_i w_i v_i) in ExponentialCone.\n\nSource node\n\nRelativeEntropyBridge supports:\n\nH in MOI.RelativeEntropyCone\n\nTarget nodes\n\nRelativeEntropyBridge creates:\n\nF in MOI.GreaterThan{T}\nG in MOI.ExponentialCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormSpectralBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormSpectralBridge","text":"NormSpectralBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNormSpectralBridge implements the following reformulation:\n\nt ge sigma_1(X) into leftbeginarrayc ctmathbfI X^top X t mathbfIendarrayright succeq 0\n\nSource node\n\nNormSpectralBridge supports:\n\nG in MOI.NormSpectralCone\n\nTarget nodes\n\nNormSpectralBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormNuclearBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormNuclearBridge","text":"NormNuclearBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nNormNuclearBridge implements the following reformulation:\n\nt ge sum_i sigma_i (X) into leftbeginarrayc cU X^top X Vendarrayright succeq 0 and 2t ge tr(U) + tr(V).\n\nSource node\n\nNormNuclearBridge supports:\n\nH in MOI.NormNuclearCone\n\nTarget nodes\n\nNormNuclearBridge creates:\n\nF in MOI.GreaterThan{T}\nG in MOI.PositiveSemidefiniteConeTriangle\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SquareBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SquareBridge","text":"SquareBridge{T,F,G,TT,ST} <: Bridges.Constraint.AbstractBridge\n\nSquareBridge implements the following reformulations:\n\n(t u X) in LogDetConeSquare into (t u Y) in LogDetConeTriangle\n(t X) in RootDetConeSquare into (t Y) in RootDetConeTriangle\nX in AbstractSymmetricMatrixSetSquare into Y in AbstractSymmetricMatrixSetTriangle\n\nwhere Y is the upper triangluar component of X.\n\nIn addition, constraints are added as necessary to constrain the matrix X to be symmetric. For example, the constraint for the matrix:\n\nbeginpmatrix\n 1 1 + x 2 - 3x\n 1 + x 2 + x 3 - x\n 2 - 3x 2 + x 2x\nendpmatrix\n\ncan be broken down to the constraint of the symmetric matrix\n\nbeginpmatrix\n 1 1 + x 2 - 3x\n cdot 2 + x 3 - x\n cdot cdot 2x\nendpmatrix\n\nand the equality constraint between the off-diagonal entries (2, 3) and (3, 2) 3 - x == 2 + x. Note that no symmetrization constraint needs to be added between the off-diagonal entries (1, 2) and (2, 1) or between (1, 3) and (3, 1) because the expressions are the same.\n\nSource node\n\nSquareBridge supports:\n\nF in ST\n\nTarget nodes\n\nSquareBridge creates:\n\nG in TT\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.HermitianToSymmetricPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.HermitianToSymmetricPSDBridge","text":"HermitianToSymmetricPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nHermitianToSymmetricPSDBridge implements the following reformulation:\n\nHermitian positive semidefinite n x n complex matrix to a symmetric positive semidefinite 2n x 2n real matrix.\n\nSee also MOI.Bridges.Variable.HermitianToSymmetricPSDBridge.\n\nSource node\n\nHermitianToSymmetricPSDBridge supports:\n\nG in MOI.HermitianPositiveSemidefiniteConeTriangle\n\nTarget node\n\nHermitianToSymmetricPSDBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\n\nReformulation\n\nThe reformulation is best described by example.\n\nThe Hermitian matrix:\n\nbeginbmatrix\n x_11 x_12 + y_12im x_13 + y_13im\n x_12 - y_12im x_22 x_23 + y_23im\n x_13 - y_13im x_23 - y_23im x_33\nendbmatrix\n\nis positive semidefinite if and only if the symmetric matrix:\n\nbeginbmatrix\n x_11 x_12 x_13 0 y_12 y_13 \n x_22 x_23 -y_12 0 y_23 \n x_33 -y_13 -y_23 0 \n x_11 x_12 x_13 \n x_22 x_23 \n x_33\nendbmatrix\n\nis positive semidefinite.\n\nThe bridge achieves this reformulation by constraining the above matrix to belong to the MOI.PositiveSemidefiniteConeTriangle(6).\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SetDotScalingBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SetDotScalingBridge","text":"SetDotScalingBridge{T,S,F,G} <: Bridges.Constraint.AbstractBridge\n\nSetDotScalingBridge implements the reformulation from constraints in S to constraints in MOI.Scaled{S}.\n\nSource node\n\nSetDotScalingBridge supports:\n\nG in S\n\nTarget node\n\nSetDotScalingBridge creates:\n\nF in MOI.Scaled{S}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SetDotInverseScalingBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SetDotInverseScalingBridge","text":"SetDotInverseScalingBridge{T,S,F,G} <: Bridges.Constraint.AbstractBridge\n\nSetDotInverseScalingBridge implements the reformulation from constraints in the MOI.Scaled{S} to constraints in the S.\n\nSource node\n\nSetDotInverseScalingBridge supports:\n\nG in MOI.Scaled{S}\n\nTarget node\n\nSetDotInverseScalingBridge creates:\n\nF in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RootDetBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RootDetBridge","text":"RootDetBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nThe MOI.RootDetConeTriangle is representable by MOI.PositiveSemidefiniteConeTriangle and MOI.GeometricMeanCone constraints, see [1, p. 149].\n\nIndeed, t le det(X)^1n if and only if there exists a lower triangular matrix Δ such that:\n\nbeginalign*\n beginpmatrix\n X Δ\n Δ^top mathrmDiag(Δ)\n endpmatrix succeq 0\n (t mathrmDiag(Δ)) in GeometricMeanCone\nendalign*\n\nSource node\n\nRootDetBridge supports:\n\nI in MOI.RootDetConeTriangle\n\nTarget nodes\n\nRootDetBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\nG in MOI.GeometricMeanCone\n\n[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.LogDetBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.LogDetBridge","text":"LogDetBridge{T,F,G,H,I} <: Bridges.Constraint.AbstractBridge\n\nThe MOI.LogDetConeTriangle is representable by MOI.PositiveSemidefiniteConeTriangle and MOI.ExponentialCone constraints.\n\nIndeed, logdet(X) = sumlimits_i=1^n log(delta_i) where delta_i are the eigenvalues of X.\n\nAdapting the method from [1, p. 149], we see that t le u log(det(Xu)) for u 0 if and only if there exists a lower triangular matrix Δ such that\n\nbeginalign*\n beginpmatrix\n X Δ\n Δ^top mathrmDiag(Δ)\n endpmatrix succeq 0\n t - sum_i=1^n u logleft(fracΔ_iiuright) le 0\nendalign*\n\nWhich we reformulate further into\n\nbeginalign*\n beginpmatrix\n X Δ\n Δ^top mathrmDiag(Δ)\n endpmatrix succeq 0\n (l_i u Δ_ii) in ExponentialConequad forall i \n t - sum_i=1^n l_i le 0\nendalign*\n\nSource node\n\nLogDetBridge supports:\n\nI in MOI.LogDetConeTriangle\n\nTarget nodes\n\nLogDetBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\nG in MOI.ExponentialCone\nH in MOI.LessThan{T}\n\n[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorActiveOnFalseBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorActiveOnFalseBridge","text":"IndicatorActiveOnFalseBridge{T,F,S} <: Bridges.Constraint.AbstractBridge\n\nIndicatorActiveOnFalseBridge implements the following reformulation:\n\nneg z implies f(x) in S into y implies f(x) in S, z + y = 1, and y in 0 1\n\nSource node\n\nIndicatorActiveOnFalseBridge supports:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{MOI.ACTIVATE_ON_ZERO,S}\n\nTarget nodes\n\nIndicatorActiveOnFalseBridge creates:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{MOI.ACTIVATE_ON_ONE,S}\nMOI.ScalarAffineFunction{T} in MOI.EqualTo\nMOI.VariableIndex in MOI.ZeroOne\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorGreaterToLessThanBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorGreaterToLessThanBridge","text":"IndicatorGreaterToLessThanBridge{T,A} <: Bridges.Constraint.AbstractBridge\n\nIndicatorGreaterToLessThanBridge implements the following reformulation:\n\nz implies f(x) ge l into z implies -f(x) le -l\n\nSource node\n\nIndicatorGreaterToLessThanBridge supports:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{A,MOI.GreaterThan{T}}\n\nTarget nodes\n\nIndicatorGreaterToLessThanBridge creates:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{A,MOI.LessThan{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorLessToGreaterThanBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorLessToGreaterThanBridge","text":"IndicatorLessToGreaterThanBridge{T,A} <: Bridges.Constraint.AbstractBridge\n\nIndicatorLessToGreaterThanBridge implements the following reformulations:\n\nz implies f(x) le u into z implies -f(x) ge -u\n\nSource node\n\nIndicatorLessToGreaterThanBridge supports:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{A,MOI.LessThan{T}}\n\nTarget nodes\n\nIndicatorLessToGreaterThanBridge creates:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{A,MOI.GreaterThan{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorSOS1Bridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorSOS1Bridge","text":"IndicatorSOS1Bridge{T,S} <: Bridges.Constraint.AbstractBridge\n\nIndicatorSOS1Bridge implements the following reformulation:\n\nz implies f(x) in S into f(x) + y in S, SOS1(y z)\n\nwarning: Warning\nThis bridge assumes that the solver supports MOI.SOS1{T} constraints in which one of the variables (y) is continuous.\n\nSource node\n\nIndicatorSOS1Bridge supports:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{MOI.ACTIVATE_ON_ONE,S}\n\nTarget nodes\n\nIndicatorSOS1Bridge creates:\n\nMOI.ScalarAffineFunction{T} in S\nMOI.VectorOfVariables in MOI.SOS1{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SemiToBinaryBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SemiToBinaryBridge","text":"SemiToBinaryBridge{T,S} <: Bridges.Constraint.AbstractBridge\n\nSemiToBinaryBridge implements the following reformulations:\n\nx in 0 cup l u into\nbeginaligned\nx leq z u \nx geq z l \nz in 0 1\nendaligned\nx in 0 cup l ldots u into\nbeginaligned\nx leq z u \nx geq z l \nz in 0 1 \nx in mathbbZ\nendaligned\n\nSource node\n\nSemiToBinaryBridge supports:\n\nMOI.VariableIndex in MOI.Semicontinuous{T}\nMOI.VariableIndex in MOI.Semiinteger{T}\n\nTarget nodes\n\nSemiToBinaryBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\nMOI.VariableIndex{T} in MOI.Integer (if S is MOI.Semiinteger{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ZeroOneBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ZeroOneBridge","text":"ZeroOneBridge{T} <: Bridges.Constraint.AbstractBridge\n\nZeroOneBridge implements the following reformulation:\n\nx in 0 1 into x in mathbbZ, 1x in 0 1.\n\nnote: Note\nZeroOneBridge adds a linear constraint instead of adding variable bounds to avoid conflicting with bounds set by the user.\n\nSource node\n\nZeroOneBridge supports:\n\nMOI.VariableIndex in MOI.ZeroOne\n\nTarget nodes\n\nZeroOneBridge creates:\n\nMOI.VariableIndex in MOI.Integer\nMOI.ScalarAffineFunction{T} in MOI.Interval{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IntegerToZeroOneBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IntegerToZeroOneBridge","text":"IntegerToZeroOneBridge{T} <: Bridges.Constraint.AbstractBridge\n\nIntegerToZeroOneBridge implements the following reformulation:\n\nx in mathbfZ into y_i in 0 1, x == lb + sum 2^i-1 y_i.\n\nSource node\n\nIntegerToZeroOneBridge supports:\n\nVariableIndex in MOI.Integer\n\nTarget nodes\n\nIntegerToZeroOneBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\n\nDeveloper note\n\nThis bridge is implemented as a constraint bridge instead of a variable bridge because we don't want to substitute the linear combination of y for every instance of x. Doing so would be expensive and greatly reduce the sparsity of the constraints.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NumberConversionBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NumberConversionBridge","text":"NumberConversionBridge{T,F1,S1,F2,S2} <: Bridges.Constraint.AbstractBridge\n\nNumberConversionBridge implements the following reformulation:\n\nf1(x) in S1 to f2(x) in S2\n\nwhere f and S are the same functional form, but differ in their coefficient type.\n\nSource node\n\nNumberConversionBridge supports:\n\nF1 in S1\n\nTarget node\n\nNumberConversionBridge creates:\n\nF2 in S2\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.AllDifferentToCountDistinctBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.AllDifferentToCountDistinctBridge","text":"AllDifferentToCountDistinctBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nAllDifferentToCountDistinctBridge implements the following reformulations:\n\nx in textsfAllDifferent(d) to (n x) in textsfCountDistinct(1+d) and n = d\nf(x) in textsfAllDifferent(d) to (d f(x)) in textsfCountDistinct(1+d)\n\nSource node\n\nAllDifferentToCountDistinctBridge supports:\n\nF in MOI.AllDifferent\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nAllDifferentToCountDistinctBridge creates:\n\nF in MOI.CountDistinct\nMOI.VariableIndex in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ReifiedAllDifferentToCountDistinctBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ReifiedAllDifferentToCountDistinctBridge","text":"ReifiedAllDifferentToCountDistinctBridge{T,F} <:\nBridges.Constraint.AbstractBridge\n\nReifiedAllDifferentToCountDistinctBridge implements the following reformulations:\n\nr iff x in textsfAllDifferent(d) to r iff (n x) in textsfCountDistinct(1+d) and n = d\nr iff f(x) in textsfAllDifferent(d) to r iff (d f(x)) in textsfCountDistinct(1+d)\n\nSource node\n\nReifiedAllDifferentToCountDistinctBridge supports:\n\nF in MOI.Reified{MOI.AllDifferent}\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nReifiedAllDifferentToCountDistinctBridge creates:\n\nF in MOI.Reified{MOI.CountDistinct}\nMOI.VariableIndex in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.BinPackingToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.BinPackingToMILPBridge","text":"BinPackingToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nBinPackingToMILPBridge implements the following reformulation:\n\nx in BinPacking(c w) into a mixed-integer linear program.\n\nReformulation\n\nThe reformulation is non-trivial, and it depends on the finite domain of each variable x_i, which we as define S_i = l_ildotsu_i.\n\nFirst, we introduce new binary variables z_ij, which are 1 if variable x_i takes the value j in the optimal solution and 0 otherwise:\n\nbeginaligned\nz_ij in 0 1 forall i in 1ldots d j in S_i \nx_i - sumlimits_jin S_i j cdot z_ij = 0 forall i in 1ldots d \nsumlimits_jin S_i z_ij = 1 forall i in 1ldots d \nendaligned\n\nThen, we add the capacity constraint for all possible bins j:\n\nsumlimits_i w_i z_ij le c forall j in bigcup_i=1ldotsd S_i\n\nSource node\n\nBinPackingToMILPBridge supports:\n\nF in MOI.BinPacking{T}\n\nTarget nodes\n\nBinPackingToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CircuitToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CircuitToMILPBridge","text":"CircuitToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCircuitToMILPBridge implements the following reformulation:\n\nx in textsfCircuit(d) to the Miller-Tucker-Zemlin formulation of the Traveling Salesperson Problem.\n\nSource node\n\nCircuitToMILPBridge supports:\n\nF in MOI.Circuit\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nCircuitToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.VariableIndex in MOI.Integer\nMOI.VariableIndex in MOI.Interval{T}\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CountAtLeastToCountBelongsBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CountAtLeastToCountBelongsBridge","text":"CountAtLeastToCountBelongsBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCountAtLeastToCountBelongsBridge implements the following reformulation:\n\nx in textsfCountAtLeast(n d mathcalS) to (n_i x_d_i) in textsfCountBelongs(1+d mathcalS) and n_i ge n for all i.\n\nSource node\n\nCountAtLeastToCountBelongsBridge supports:\n\nF in MOI.CountAtLeast\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nCountAtLeastToCountBelongsBridge creates:\n\nF in MOI.CountBelongs\nMOI.VariableIndex in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CountBelongsToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CountBelongsToMILPBridge","text":"CountBelongsToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCountBelongsToMILPBridge implements the following reformulation:\n\n(n x) in textsfCountBelongs(1+d mathcalS) into a mixed-integer linear program.\n\nReformulation\n\nThe reformulation is non-trivial, and it depends on the finite domain of each variable x_i, which we as define S_i = l_ildotsu_i.\n\nFirst, we introduce new binary variables z_ij, which are 1 if variable x_i takes the value j in the optimal solution and 0 otherwise:\n\nbeginaligned\nz_ij in 0 1 forall i in 1ldots d j in S_i \nx_i - sumlimits_jin S_i j cdot z_ij = 0 forall i in 1ldots d \nsumlimits_jin S_i z_ij = 1 forall i in 1ldots d \nendaligned\n\nFinally, n is constrained to be the number of z_ij elements that are in mathcalS:\n\nn - sumlimits_iin 1ldots d j in mathcalS z_ij = 0\n\nSource node\n\nCountBelongsToMILPBridge supports:\n\nF in MOI.CountBelongs\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nCountBelongsToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CountDistinctToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CountDistinctToMILPBridge","text":"CountDistinctToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCountDistinctToMILPBridge implements the following reformulation:\n\n(n x) in textsfCountDistinct(1+d) into a mixed-integer linear program.\n\nReformulation\n\nThe reformulation is non-trivial, and it depends on the finite domain of each variable x_i, which we as define S_i = l_ildotsu_i.\n\nFirst, we introduce new binary variables z_ij, which are 1 if variable x_i takes the value j in the optimal solution and 0 otherwise:\n\nbeginaligned\nz_ij in 0 1 forall i in 1ldots d j in S_i \nx_i - sumlimits_jin S_i j cdot z_ij = 0 forall i in 1ldots d \nsumlimits_jin S_i z_ij = 1 forall i in 1ldots d \nendaligned\n\nThen, we introduce new binary variables y_j, which are 1 if a variable takes the value j in the optimal solution and 0 otherwise.\n\nbeginaligned\ny_j in 0 1 forall j in bigcup_i=1ldotsd S_i \ny_j le sumlimits_i in 1ldots d j in S_i z_ij le M y_j forall j in bigcup_i=1ldotsd S_i\nendaligned\n\nFinally, n is constrained to be the number of y_j elements that are non-zero:\n\nn - sumlimits_j in bigcup_i=1ldotsd S_i y_j = 0\n\nSource node\n\nCountDistinctToMILPBridge supports:\n\nF in MOI.CountDistinct\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nCountDistinctToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ReifiedCountDistinctToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ReifiedCountDistinctToMILPBridge","text":"ReifiedCountDistinctToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nReifiedCountDistinctToMILPBridge implements the following reformulation:\n\nr iff (n x) in textsfCountDistinct(1+d) into a mixed-integer linear program.\n\nReformulation\n\nThe reformulation is non-trivial, and it depends on the finite domain of each variable x_i, which we as define S_i = l_ildotsu_i.\n\nFirst, we introduce new binary variables z_ij, which are 1 if variable x_i takes the value j in the optimal solution and 0 otherwise:\n\nbeginaligned\nz_ij in 0 1 forall i in 1ldots d j in S_i \nx_i - sumlimits_jin S_i j cdot z_ij = 0 forall i in 1ldots d \nsumlimits_jin S_i z_ij = 1 forall i in 1ldots d \nendaligned\n\nThen, we introduce new binary variables y_j, which are 1 if a variable takes the value j in the optimal solution and 0 otherwise.\n\nbeginaligned\ny_j in 0 1 forall j in bigcup_i=1ldotsd S_i \ny_j le sumlimits_i in 1ldots d j in S_i z_ij le M y_j forall j in bigcup_i=1ldotsd S_i\nendaligned\n\nFinally, n is constrained to be the number of y_j elements that are non-zero, with some slack:\n\nn - sumlimits_j in bigcup_i=1ldotsd S_i y_j = delta^+ - delta^-\n\nAnd then the slack is constrained to respect the reif variable r:\n\nbeginaligned\nd_1 le delta^+ le M d_1 \nd_2 le delta^- le M d_s \nd_1 + d_2 + r = 1 \nd_1 d_2 in 0 1\nendaligned\n\nSource node\n\nReifiedCountDistinctToMILPBridge supports:\n\nF in MOI.Reified{MOI.CountDistinct}\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nReifiedCountDistinctToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CountGreaterThanToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CountGreaterThanToMILPBridge","text":"CountGreaterThanToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCountGreaterThanToMILPBridge implements the following reformulation:\n\n(c y x) in CountGreaterThan() into a mixed-integer linear program.\n\nSource node\n\nCountGreaterThanToMILPBridge supports:\n\nF in MOI.CountGreaterThan\n\nTarget nodes\n\nCountGreaterThanToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.TableToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.TableToMILPBridge","text":"TableToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nTableToMILPBridge implements the following reformulation:\n\nx in Table(t) into\nbeginaligned\nz_j in 0 1 quad forall i j \nsumlimits_j=1^n z_j = 1 \nsumlimits_j=1^n t_ij z_j = x_i quad forall i\nendaligned\n\nSource node\n\nTableToMILPBridge supports:\n\nF in MOI.Table{T}\n\nTarget nodes\n\nTableToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#objective_bridges_ref","page":"List of bridges","title":"Objective bridges","text":"","category":"section"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"These bridges are subtypes of Bridges.Objective.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"Bridges.Objective.FunctionizeBridge\nBridges.Objective.QuadratizeBridge\nBridges.Objective.SlackBridge\nBridges.Objective.VectorFunctionizeBridge\nBridges.Objective.VectorSlackBridge","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.FunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.FunctionizeBridge","text":"FunctionizeBridge{T}\n\nFunctionizeBridge implements the following reformulations:\n\nmin x into min1x + 0\nmax x into max1x + 0\n\nwhere T is the coefficient type of 1 and 0.\n\nSource node\n\nFunctionizeBridge supports:\n\nMOI.ObjectiveFunction{MOI.VariableIndex}\n\nTarget nodes\n\nFunctionizeBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{MOI.ScalarAffineFunction{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.QuadratizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.QuadratizeBridge","text":"QuadratizeBridge{T}\n\nQuadratizeBridge implements the following reformulations:\n\nmin a^top x + b into minx^top mathbf0 x + a^top x + b\nmax a^top x + b into maxx^top mathbf0 x + a^top x + b\n\nwhere T is the coefficient type of 0.\n\nSource node\n\nQuadratizeBridge supports:\n\nMOI.ObjectiveFunction{MOI.ScalarAffineFunction{T}}\n\nTarget nodes\n\nQuadratizeBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.SlackBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.SlackBridge","text":"SlackBridge{T,F,G}\n\nSlackBridge implements the following reformulations:\n\nminf(x) into miny f(x) - y le 0\nmaxf(x) into maxy f(x) - y ge 0\n\nwhere F is the type of f(x) - y, G is the type of f(x), and T is the coefficient type of f(x).\n\nSource node\n\nSlackBridge supports:\n\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nSlackBridge creates:\n\nOne variable node: MOI.VariableIndex in MOI.Reals\nOne objective node: MOI.ObjectiveFunction{MOI.VariableIndex}\nOne constraint node, that depends on the MOI.ObjectiveSense:\nF-in-MOI.LessThan if MIN_SENSE\nF-in-MOI.GreaterThan if MAX_SENSE\n\nwarning: Warning\nWhen using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge, then set MOI.ObjectiveSense and re-add the objective.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.VectorFunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.VectorFunctionizeBridge","text":"VectorFunctionizeBridge{T}\n\nVectorFunctionizeBridge implements the following reformulations:\n\nmin x into min1x + 0\nmax x into max1x + 0\n\nwhere T is the coefficient type of 1 and 0.\n\nSource node\n\nVectorFunctionizeBridge supports:\n\nMOI.ObjectiveFunction{MOI.VectorOfVariables}\n\nTarget nodes\n\nVectorFunctionizeBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{MOI.VectorAffineFunction{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.VectorSlackBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.VectorSlackBridge","text":"VectorSlackBridge{T,F,G}\n\nVectorSlackBridge implements the following reformulations:\n\nminf(x) into miny y - f(x) in mathbbR_+ \nmaxf(x) into maxy f(x) - y in mathbbR_+ \n\nwhere F is the type of f(x) - y, G is the type of f(x), and T is the coefficient type of f(x).\n\nSource node\n\nVectorSlackBridge supports:\n\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nVectorSlackBridge creates:\n\nOne variable node: MOI.VectorOfVariables in MOI.Reals\nOne objective node: MOI.ObjectiveFunction{MOI.VectorOfVariables}\nOne constraint node: F-in-MOI.Nonnegatives\n\nwarning: Warning\nWhen using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge, then set MOI.ObjectiveSense and re-add the objective.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#variable_bridges_ref","page":"List of bridges","title":"Variable bridges","text":"","category":"section"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"These bridges are subtypes of Bridges.Variable.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"Bridges.Variable.FreeBridge\nBridges.Variable.NonposToNonnegBridge\nBridges.Variable.RSOCtoPSDBridge\nBridges.Variable.RSOCtoSOCBridge\nBridges.Variable.SOCtoRSOCBridge\nBridges.Variable.VectorizeBridge\nBridges.Variable.ZerosBridge\nBridges.Variable.HermitianToSymmetricPSDBridge","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.FreeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.FreeBridge","text":"FreeBridge{T} <: Bridges.Variable.AbstractBridge\n\nFreeBridge implements the following reformulation:\n\nx in mathbbR into y z ge 0 with the substitution rule x = y - z,\n\nwhere T is the coefficient type of y - z.\n\nSource node\n\nFreeBridge supports:\n\nMOI.VectorOfVariables in MOI.Reals\n\nTarget nodes\n\nFreeBridge creates:\n\nOne variable node: MOI.VectorOfVariables in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.NonposToNonnegBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.NonposToNonnegBridge","text":"NonposToNonnegBridge{T} <: Bridges.Variable.AbstractBridge\n\nNonposToNonnegBridge implements the following reformulation:\n\nx in mathbbR_- into y in mathbbR_+ with the substitution rule x = -y,\n\nwhere T is the coefficient type of -y.\n\nSource node\n\nNonposToNonnegBridge supports:\n\nMOI.VectorOfVariables in MOI.Nonpositives\n\nTarget nodes\n\nNonposToNonnegBridge creates:\n\nOne variable node: MOI.VectorOfVariables in MOI.Nonnegatives,\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.RSOCtoPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.RSOCtoPSDBridge","text":"RSOCtoPSDBridge{T} <: Bridges.Variable.AbstractBridge\n\nRSOCtoPSDBridge implements the following reformulation:\n\nx_2^2 le 2tu where t u ge 0 into Y succeq 0, with the substitution rule: Y = leftbeginarrayc ct x^top x 2u mathbfIendarrayright\n\nAdditional bounds are added to ensure the off-diagonals of the 2uI submatrix are 0, and linear constraints are added to ennsure the diagonal of 2uI takes the same values.\n\nAs a special case, if x = 0, then RSOCtoPSDBridge reformulates into (t u) in mathbbR_+.\n\nSource node\n\nRSOCtoPSDBridge supports:\n\nMOI.VectorOfVariables in MOI.RotatedSecondOrderCone\n\nTarget nodes\n\nRSOCtoPSDBridge creates:\n\nOne variable node that depends on the input dimension:\nMOI.VectorOfVariables in MOI.Nonnegatives if dimension is 1 or 2\nMOI.VectorOfVariables in\nMOI.PositiveSemidefiniteConeTriangle otherwise\nThe constraint node MOI.VariableIndex in MOI.EqualTo\nThe constrant node MOI.ScalarAffineFunction in MOI.EqualTo\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.RSOCtoSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.RSOCtoSOCBridge","text":"RSOCtoSOCBridge{T} <: Bridges.Variable.AbstractBridge\n\nRSOCtoSOCBridge implements the following reformulation:\n\nx_2^2 le 2tu into v_2 le w, with the substitution rules t = fracwsqrt 2 + fracv_1sqrt 2, u = fracwsqrt 2 - fracv_1sqrt 2, and x = (v_2ldotsv_N).\n\nSource node\n\nRSOCtoSOCBridge supports:\n\nMOI.VectorOfVariables in MOI.RotatedSecondOrderCone\n\nTarget node\n\nRSOCtoSOCBridge creates:\n\nMOI.VectorOfVariables in MOI.SecondOrderCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.SOCtoRSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.SOCtoRSOCBridge","text":"SOCtoRSOCBridge{T} <: Bridges.Variable.AbstractBridge\n\nSOCtoRSOCBridge implements the following reformulation:\n\nx_2 le t into 2uv ge w_2^2, with the substitution rules t = fracusqrt 2 + fracvsqrt 2, x = (fracusqrt 2 - fracvsqrt 2 w).\n\nAssumptions\n\nSOCtoRSOCBridge assumes that x ge 1.\n\nSource node\n\nSOCtoRSOCBridge supports:\n\nMOI.VectorOfVariables in MOI.SecondOrderCone\n\nTarget node\n\nSOCtoRSOCBridge creates:\n\nMOI.VectorOfVariables in MOI.RotatedSecondOrderCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.VectorizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.VectorizeBridge","text":"VectorizeBridge{T,S} <: Bridges.Variable.AbstractBridge\n\nVectorizeBridge implements the following reformulations:\n\nx ge a into y in mathbbR_+ with the substitution rule x = a + y\nx le a into y in mathbbR_- with the substitution rule x = a + y\nx == a into y in 0 with the substitution rule x = a + y\n\nwhere T is the coefficient type of a + y.\n\nSource node\n\nVectorizeBridge supports:\n\nMOI.VariableIndex in MOI.GreaterThan{T}\nMOI.VariableIndex in MOI.LessThan{T}\nMOI.VariableIndex in MOI.EqualTo{T}\n\nTarget nodes\n\nVectorizeBridge creates:\n\nOne variable node: MOI.VectorOfVariables in S, where S is one of MOI.Nonnegatives, MOI.Nonpositives, MOI.Zeros depending on the type of S.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.ZerosBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.ZerosBridge","text":"ZerosBridge{T} <: Bridges.Variable.AbstractBridge\n\nZerosBridge implements the following reformulation:\n\nx in 0 into the substitution rule x = 0,\n\nwhere T is the coefficient type of 0.\n\nSource node\n\nZerosBridge supports:\n\nMOI.VectorOfVariables in MOI.Zeros\n\nTarget nodes\n\nZerosBridge does not create target nodes. It replaces all instances of x with 0 via substitution. This means that no variables are created in the underlying model.\n\nCaveats\n\nThe bridged variables are similar to parameters with zero values. Parameters with non-zero values can be created with constrained variables in MOI.EqualTo by combining a VectorizeBridge and this bridge.\n\nHowever, functions modified by ZerosBridge cannot be unbridged. That is, for a given function, we cannot determine if the bridged variables were used.\n\nA related implication is that this bridge does not support MOI.ConstraintDual. However, if a MOI.Utilities.CachingOptimizer is used, the dual can be determined by the bridged optimizer using MOI.Utilities.get_fallback because the caching optimizer records the unbridged function.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.HermitianToSymmetricPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.HermitianToSymmetricPSDBridge","text":"HermitianToSymmetricPSDBridge{T} <: Bridges.Variable.AbstractBridge\n\nHermitianToSymmetricPSDBridge implements the following reformulation:\n\nHermitian positive semidefinite n x n complex matrix to a symmetric positive semidefinite 2n x 2n real matrix satisfying equality constraints described below.\n\nSource node\n\nHermitianToSymmetricPSDBridge supports:\n\nMOI.VectorOfVariables in MOI.HermitianPositiveSemidefiniteConeTriangle\n\nTarget node\n\nHermitianToSymmetricPSDBridge creates:\n\nMOI.VectorOfVariables in MOI.PositiveSemidefiniteConeTriangle\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\n\nReformulation\n\nThe reformulation is best described by example.\n\nThe Hermitian matrix:\n\nbeginbmatrix\n x_11 x_12 + y_12im x_13 + y_13im\n x_12 - y_12im x_22 x_23 + y_23im\n x_13 - y_13im x_23 - y_23im x_33\nendbmatrix\n\nis positive semidefinite if and only if the symmetric matrix:\n\nbeginbmatrix\n x_11 x_12 x_13 0 y_12 y_13 \n x_22 x_23 -y_12 0 y_23 \n x_33 -y_13 -y_23 0 \n x_11 x_12 x_13 \n x_22 x_23 \n x_33\nendbmatrix\n\nis positive semidefinite.\n\nThe bridge achieves this reformulation by adding a new set of variables in MOI.PositiveSemidefiniteConeTriangle(6), and then adding three groups of equality constraints to:\n\nconstrain the two x blocks to be equal\nforce the diagonal of the y blocks to be 0\nforce the lower triangular of the y block to be the negative of the upper triangle.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Bridges/overview/#The-Bridges-submodule","page":"Overview","title":"The Bridges submodule","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"The Bridges module simplifies the process of converting models between equivalent formulations.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nRead our paper for more details on how bridges are implemented.","category":"page"},{"location":"submodules/Bridges/overview/#Why-bridges?","page":"Overview","title":"Why bridges?","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"A constraint can often be written in a number of equivalent formulations. For example, the constraint l le a^top x le u (ScalarAffineFunction-in-Interval) could be re-formulated as two constraints: a^top x ge l (ScalarAffineFunction-in-GreaterThan) and a^top x le u (ScalarAffineFunction-in-LessThan). An alternative re-formulation is to add a dummy variable y with the constraints l le y le u (VariableIndex-in-Interval) and a^top x - y = 0 (ScalarAffineFunction-in-EqualTo).","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"To avoid each solver having to code these transformations manually, MathOptInterface provides bridges.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"A bridge is a small transformation from one constraint type to another (potentially collection of) constraint type.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Because these bridges are included in MathOptInterface, they can be re-used by any optimizer. Some bridges also implement constraint modifications and constraint primal and dual translations.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Several bridges can be used in combination to transform a single constraint into a form that the solver may understand. Choosing the bridges to use takes the form of finding a shortest path in the hyper-graph of bridges. The methodology is detailed in the MOI paper.","category":"page"},{"location":"submodules/Bridges/overview/#The-three-types-of-bridges","page":"Overview","title":"The three types of bridges","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"There are three types of bridges in MathOptInterface:","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Constraint bridges\nVariable bridges\nObjective bridges","category":"page"},{"location":"submodules/Bridges/overview/#Constraint-bridges","page":"Overview","title":"Constraint bridges","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Constraint bridges convert constraints formulated by the user into an equivalent form supported by the solver. Constraint bridges are subtypes of Bridges.Constraint.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"The equivalent formulation may add constraints (and possibly also variables) in the underlying model.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"In particular, constraint bridges can focus on rewriting the function of a constraint, and do not change the set. Function bridges are subtypes of Bridges.Constraint.AbstractFunctionConversionBridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Read the list of implemented constraint bridges for more details on the types of transformations that are available. Function bridges are Bridges.Constraint.ScalarFunctionizeBridge and Bridges.Constraint.VectorFunctionizeBridge.","category":"page"},{"location":"submodules/Bridges/overview/#variable_bridges","page":"Overview","title":"Variable bridges","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Variable bridges convert variables added by the user, either free with add_variable/add_variables, or constrained with add_constrained_variable/add_constrained_variables, into an equivalent form supported by the solver. Variable bridges are subtypes of Bridges.Variable.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"The equivalent formulation may add constraints (and possibly also variables) in the underlying model.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Read the list of implemented variable bridges for more details on the types of transformations that are available.","category":"page"},{"location":"submodules/Bridges/overview/#Objective-bridges","page":"Overview","title":"Objective bridges","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Objective bridges convert the ObjectiveFunction set by the user into an equivalent form supported by the solver. Objective bridges are subtypes of Bridges.Objective.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"The equivalent formulation may add constraints (and possibly also variables) in the underlying model.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Read the list of implemented objective bridges for more details on the types of transformations that are available.","category":"page"},{"location":"submodules/Bridges/overview/#Bridges.full_bridge_optimizer","page":"Overview","title":"Bridges.full_bridge_optimizer","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nUnless you have an advanced use-case, this is probably the only function you need to care about.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"To enable the full power of MathOptInterface's bridges, wrap an optimizer in a Bridges.full_bridge_optimizer.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> inner_optimizer = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> optimizer = MOI.Bridges.full_bridge_optimizer(inner_optimizer, Float64)\nMOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}\nwith 0 variable bridges\nwith 0 constraint bridges\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Now, use optimizer as normal, and bridging will happen lazily behind the scenes. By lazily, we mean that bridging will happen if and only if the constraint is not supported by the inner_optimizer.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"info: Info\nMost bridges are added by default in Bridges.full_bridge_optimizer. However, for technical reasons, some bridges are not added by default. Three examples include Bridges.Constraint.SOCtoPSDBridge, Bridges.Constraint.SOCtoNonConvexQuadBridge and Bridges.Constraint.RSOCtoNonConvexQuadBridge. See the docs of those bridges for more information.","category":"page"},{"location":"submodules/Bridges/overview/#Add-a-single-bridge","page":"Overview","title":"Add a single bridge","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"If you don't want to use Bridges.full_bridge_optimizer, you can wrap an optimizer in a single bridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"However, this will force the constraint to be bridged, even if the inner_optimizer supports it.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> inner_optimizer = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> optimizer = MOI.Bridges.Constraint.SplitInterval{Float64}(inner_optimizer)\nMOIB.Constraint.SingleBridgeOptimizer{MOIB.Constraint.SplitIntervalBridge{Float64}, MOIU.Model{Float64}}\nwith 0 constraint bridges\nwith inner model MOIU.Model{Float64}\n\njulia> x = MOI.add_variable(optimizer)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(optimizer, x, MOI.Interval(0.0, 1.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)\n\njulia> MOI.get(optimizer, MOI.ListOfConstraintTypesPresent())\n1-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})\n\njulia> MOI.get(inner_optimizer, MOI.ListOfConstraintTypesPresent())\n2-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64})\n (MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64})","category":"page"},{"location":"submodules/Bridges/overview/#Bridges.LazyBridgeOptimizer","page":"Overview","title":"Bridges.LazyBridgeOptimizer","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"If you don't want to use Bridges.full_bridge_optimizer, but you need more than a single bridge (or you want the bridging to happen lazily), you can manually construct a Bridges.LazyBridgeOptimizer.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"First, wrap an inner optimizer:","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> inner_optimizer = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> optimizer = MOI.Bridges.LazyBridgeOptimizer(inner_optimizer)\nMOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}\nwith 0 variable bridges\nwith 0 constraint bridges\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Then use Bridges.add_bridge to add individual bridges:","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Constraint.SplitIntervalBridge{Float64})\n\njulia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Objective.FunctionizeBridge{Float64})","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Now the constraints will be bridged only if needed:","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> x = MOI.add_variable(optimizer)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(optimizer, x, MOI.Interval(0.0, 1.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)\n\njulia> MOI.get(optimizer, MOI.ListOfConstraintTypesPresent())\n1-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})\n\njulia> MOI.get(inner_optimizer, MOI.ListOfConstraintTypesPresent())\n1-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})","category":"page"},{"location":"developer/checklists/#Checklists","page":"Checklists","title":"Checklists","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"The purpose of this page is to collate a series of checklists for commonly performed changes to the source code of MathOptInterface.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"In each case, copy the checklist into the description of the pull request.","category":"page"},{"location":"developer/checklists/#Making-a-release","page":"Checklists","title":"Making a release","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"Use this checklist when making a release of the MathOptInterface repository.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"## Basic\n\n - [ ] `version` field of `Project.toml` has been updated\n - If a breaking change, increment the MAJOR field and reset others to 0\n - If adding new features, increment the MINOR field and reset PATCH to 0\n - If adding bug fixes or documentation changes, increment the PATCH field\n\n## Documentation\n\n - [ ] Add a new entry to `docs/src/changelog.md`, following existing style\n\n## Tests\n\n - [ ] The `solver-tests.yml` GitHub action does not have unexpected failures.\n To run the action, go to:\n https://github.com/jump-dev/MathOptInterface.jl/actions/workflows/solver-tests.yml\n and click \"Run workflow\"","category":"page"},{"location":"developer/checklists/#Adding-a-new-set","page":"Checklists","title":"Adding a new set","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"Use this checklist when adding a new set to the MathOptInterface repository.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"## Basic\n\n - [ ] Add a new `AbstractScalarSet` or `AbstractVectorSet` to `src/sets.jl`\n - [ ] If `isbitstype(S) == false`, implement `Base.copy(set::S)`\n - [ ] If `isbitstype(S) == false`, implement `Base.:(==)(x::S, y::S)`\n - [ ] If an `AbstractVectorSet`, implement `dimension(set::S)`, unless the\n dimension is given by `set.dimension`.\n\n## Utilities\n\n - [ ] If an `AbstractVectorSet`, implement `Utilities.set_dot`,\n unless the dot product between two vectors in the set is equivalent to\n `LinearAlgebra.dot`\n - [ ] If an `AbstractVectorSet`, implement `Utilities.set_with_dimension` in\n `src/Utilities/matrix_of_constraints.jl`\n - [ ] Add the set to the `@model` macro at the bottom of `src/Utilities.model.jl`\n\n## Documentation\n\n - [ ] Add a docstring, which gives the mathematical definition of the set,\n along with an `## Example` block containing a `jldoctest`\n - [ ] Add the docstring to `docs/src/reference/standard_form.md`\n - [ ] Add the set to the relevant table in `docs/src/manual/standard_form.md`\n\n## Tests\n\n - [ ] Define a new `_set(::Type{S})` method in `src/Test/test_basic_constraint.jl`\n and add the name of the set to the list at the bottom of that files\n - [ ] If the set has any checks in its constructor, add tests to `test/sets.jl`\n\n## MathOptFormat\n\n - [ ] Open an issue at `https://github.com/jump-dev/MathOptFormat` to add\n support for the new set {{ replace with link to the issue }}\n\n## Optional\n\n - [ ] Implement `dual_set(::S)` and `dual_set_type(::Type{S})`\n - [ ] Add new tests to the `Test` submodule exercising your new set\n - [ ] Add new bridges to convert your set into more commonly used sets","category":"page"},{"location":"developer/checklists/#Adding-a-new-bridge","page":"Checklists","title":"Adding a new bridge","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"Use this checklist when adding a new bridge to the MathOptInterface repository.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"The steps are mostly the same, but locations depend on whether the bridge is a Constraint, Objective, or Variable bridge. In each case below, replace XXX with the appropriate type of bridge.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"## Basic\n\n - [ ] Create a new file in `src/Bridges/XXX/bridges`\n - [ ] Define the bridge, following existing examples. The name of the bridge\n struct must end in `Bridge`\n - [ ] Check if your bridge can be a subtype of [`MOI.Bridges.Constraint.SetMapBridge`](@ref)\n - [ ] Define a new `const` that is a `SingleBridgeOptimizer` wrapping the\n new bridge. The name of the const must be the name of the bridge, less\n the `Bridge` suffix\n - [ ] `include` the file in `src/Bridges/XXX/bridges/XXX.jl`\n - [ ] If the bridge should be enabled by default, add the bridge to\n `add_all_bridges` at the bottom of `src/Bridges/XXX/XXX.jl`\n\n## Tests\n\n - [ ] Create a new file in the appropriate subdirectory of `tests/Bridges/XXX`\n - [ ] Use `MOI.Bridges.runtests` to test various inputs and outputs of the\n bridge\n - [ ] If, after opening the pull request to add the bridge, some lines are not\n covered by the tests, add additional bridge-specific tests to cover the\n untested lines.\n\n## Documentation\n\n - [ ] Add a docstring which uses the same template as existing bridges.\n - [ ] Add the docstring to `docs/src/submodules/Bridges/list_of_bridges.md`\n\n## Final touch\n\nIf the bridge depends on run-time values of other variables and constraints in\nthe model:\n\n - [ ] Implement `MOI.Utilities.needs_final_touch(::Bridge)`\n - [ ] Implement `MOI.Utilities.final_touch(::Bridge, ::MOI.ModelLike)`\n - [ ] Ensure that `final_touch` can be called multiple times in a row","category":"page"},{"location":"developer/checklists/#Updating-MathOptFormat","page":"Checklists","title":"Updating MathOptFormat","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"Use this checklist when updating the version of MathOptFormat.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"## Basic\n\n - [ ] The file at `src/FileFormats/MOF/mof.X.Y.schema.json` is updated\n - [ ] The constants `SCHEMA_PATH`, `VERSION`, and `SUPPORTED_VERSIONS` are\n updated in `src/FileFormats/MOF/MOF.jl`\n\n## New sets\n\n - [ ] New sets are added to the `@model` in `src/FileFormats/MOF/MOF.jl`\n - [ ] New sets are added to the `@enum` in `src/FileFormats/MOF/read.jl`\n - [ ] `set_to_moi` is defined for each set in `src/FileFormats/MOF/read.jl`\n - [ ] `head_name` is defined for each set in `src/FileFormats/MOF/write.jl`\n - [ ] A new unit test calling `_test_model_equality` is aded to\n `test/FileFormats/MOF/MOF.jl`\n\n## Tests\n\n - [ ] The version field in `test/FileFormats/MOF/nlp.mof.json` is updated\n\n## Documentation\n\n - [ ] The version fields are updated in `docs/src/submodules/FileFormats/overview.md`","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/standard_form/#Standard-form-problem","page":"Standard form problem","title":"Standard form problem","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"MathOptInterface represents optimization problems in the standard form:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"beginalign\n min_x in mathbbR^n f_0(x)\n \n textst f_i(x) in mathcalS_i i = 1 ldots m\nendalign","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"where:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"the functions f_0 f_1 ldots f_m are specified by AbstractFunction objects\nthe sets mathcalS_1 ldots mathcalS_m are specified by AbstractSet objects","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"tip: Tip\nFor more information on this standard form, read our paper.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"MOI defines some commonly used functions and sets, but the interface is extensible to other sets recognized by the solver.","category":"page"},{"location":"manual/standard_form/#Functions","page":"Standard form problem","title":"Functions","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"The function types implemented in MathOptInterface.jl are:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Function Description\nVariableIndex x_j, the projection onto a single coordinate defined by a variable index j.\nVectorOfVariables The projection onto multiple coordinates (that is, extracting a sub-vector).\nScalarAffineFunction a^T x + b, where a is a vector and b scalar.\nScalarNonlinearFunction f(x), where f is a nonlinear function.\nVectorAffineFunction A x + b, where A is a matrix and b is a vector.\nScalarQuadraticFunction frac12 x^T Q x + a^T x + b, where Q is a symmetric matrix, a is a vector, and b is a constant.\nVectorQuadraticFunction A vector of scalar-valued quadratic functions.\nVectorNonlinearFunction f(x), where f is a vector-valued nonlinear function.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Extensions for nonlinear programming are present but not yet well documented.","category":"page"},{"location":"manual/standard_form/#One-dimensional-sets","page":"Standard form problem","title":"One-dimensional sets","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"The one-dimensional set types implemented in MathOptInterface.jl are:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Set Description\nLessThan(u) (-infty u\nGreaterThan(l) l infty)\nEqualTo(v) v\nInterval(l, u) l u\nInteger() mathbbZ\nZeroOne() 0 1 \nSemicontinuous(l, u) 0 cup l u\nSemiinteger(l, u) 0 cup ll+1ldotsu-1u","category":"page"},{"location":"manual/standard_form/#Vector-cones","page":"Standard form problem","title":"Vector cones","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"The vector-valued set types implemented in MathOptInterface.jl are:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Set Description\nReals(d) mathbbR^d\nZeros(d) 0^d\nNonnegatives(d) x in mathbbR^d x ge 0 \nNonpositives(d) x in mathbbR^d x le 0 \nSecondOrderCone(d) (tx) in mathbbR^d t ge lVert x rVert_2 \nRotatedSecondOrderCone(d) (tux) in mathbbR^d 2tu ge lVert x rVert_2^2 t ge 0u ge 0 \nExponentialCone() (xyz) in mathbbR^3 y exp (xy) le z y 0 \nDualExponentialCone() (uvw) in mathbbR^3 -u exp (vu) le exp(1) w u 0 \nGeometricMeanCone(d) (tx) in mathbbR^1+n x ge 0 t le sqrtnx_1 x_2 cdots x_n where n is d - 1\nPowerCone(α) (xyz) in mathbbR^3 x^alpha y^1-alpha ge z x ge 0y ge 0 \nDualPowerCone(α) (uvw) in mathbbR^3 left(fracualpharight(^alphaleft(fracv1-alpharight)^1-alpha ge w uv ge 0 \nNormOneCone(d) (tx) in mathbbR^d t ge sum_i lvert x_i rvert \nNormInfinityCone(d) (tx) in mathbbR^d t ge max_i lvert x_i rvert \nRelativeEntropyCone(d) (u v w) in mathbbR^d u ge sum_i w_i log (fracw_iv_i) v_i ge 0 w_i ge 0 \nHyperRectangle(l, u) x in barmathbbR^d x_i in l_i u_i forall i=1ldotsd\nNormCone(p, d) ``{ (t,x) \\in \\mathbb{R}^{d} : t \\ge \\left(\\sum\\limits_i","category":"page"},{"location":"manual/standard_form/#Matrix-cones","page":"Standard form problem","title":"Matrix cones","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"The matrix-valued set types implemented in MathOptInterface.jl are:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Set Description\nRootDetConeTriangle(d) (tX) in mathbbR^1+d(1+d)2 t le det(X)^1d X mbox is the upper triangle of a PSD matrix \nRootDetConeSquare(d) (tX) in mathbbR^1+d^2 t le det(X)^1d X mbox is a PSD matrix \nPositiveSemidefiniteConeTriangle(d) X in mathbbR^d(d+1)2 X mbox is the upper triangle of a PSD matrix \nPositiveSemidefiniteConeSquare(d) X in mathbbR^d^2 X mbox is a PSD matrix \nLogDetConeTriangle(d) (tuX) in mathbbR^2+d(1+d)2 t le ulog(det(Xu)) X mbox is the upper triangle of a PSD matrix u 0 \nLogDetConeSquare(d) (tuX) in mathbbR^2+d^2 t le u log(det(Xu)) X mbox is a PSD matrix u 0 \nNormSpectralCone(r, c) (t X) in mathbbR^1 + r times c t ge sigma_1(X) X mbox is a rtimes cmbox matrix \nNormNuclearCone(r, c) (t X) in mathbbR^1 + r times c t ge sum_i sigma_i(X) X mbox is a rtimes cmbox matrix \nHermitianPositiveSemidefiniteConeTriangle(d) The cone of Hermitian positive semidefinite matrices, with\nside_dimension rows and columns. \nScaled(S) The set S scaled so that Utilities.set_dot corresponds to LinearAlgebra.dot","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Some of these cones can take two forms: XXXConeTriangle and XXXConeSquare.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"In XXXConeTriangle sets, the matrix is assumed to be symmetric, and the elements are provided by a vector, in which the entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row).","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"In XXXConeSquare sets, the entries of the matrix are given column by column (or equivalently, row by row), and the matrix is constrained to be symmetric. As an example, given a 2-by-2 matrix of variables X and a one-dimensional variable t, we can specify a root-det constraint as [t, X11, X12, X22] ∈ RootDetConeTriangle or [t, X11, X12, X21, X22] ∈ RootDetConeSquare.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"We provide both forms to enable flexibility for solvers who may natively support one or the other. Transformations between XXXConeTriangle and XXXConeSquare are handled by bridges, which removes the chance of conversion mistakes by users or solver developers.","category":"page"},{"location":"manual/standard_form/#Multi-dimensional-sets-with-combinatorial-structure","page":"Standard form problem","title":"Multi-dimensional sets with combinatorial structure","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Other sets are vector-valued, with a particular combinatorial structure. Read their docstrings for more information on how to interpret them.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Set Description\nSOS1 A Special Ordered Set (SOS) of Type I\nSOS2 A Special Ordered Set (SOS) of Type II\nIndicator A set to specify an indicator constraint\nComplements A set to specify a mixed complementarity constraint\nAllDifferent The all_different global constraint\nBinPacking The bin_packing global constraint\nCircuit The circuit global constraint\nCountAtLeast The at_least global constraint\nCountBelongs The nvalue global constraint\nCountDistinct The distinct global constraint\nCountGreaterThan The count_gt global constraint\nCumulative The cumulative global constraint\nPath The path global constraint\nTable The table global constraint","category":"page"},{"location":"reference/modification/","page":"Modifications","title":"Modifications","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/modification/#Modifications","page":"Modifications","title":"Modifications","text":"","category":"section"},{"location":"reference/modification/","page":"Modifications","title":"Modifications","text":"modify\nAbstractFunctionModification\nScalarConstantChange\nVectorConstantChange\nScalarCoefficientChange\nMultirowChange","category":"page"},{"location":"reference/modification/#MathOptInterface.modify","page":"Modifications","title":"MathOptInterface.modify","text":"Constraint Function\n\nmodify(model::ModelLike, ci::ConstraintIndex, change::AbstractFunctionModification)\n\nApply the modification specified by change to the function of constraint ci.\n\nAn ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by the model model.\n\nExamples\n\nmodify(model, ci, ScalarConstantChange(10.0))\n\nObjective Function\n\nmodify(model::ModelLike, ::ObjectiveFunction, change::AbstractFunctionModification)\n\nApply the modification specified by change to the objective function of model. To change the function completely, call set instead.\n\nAn ModifyObjectiveNotAllowed error is thrown if modifying objectives is not supported by the model model.\n\nExamples\n\nmodify(model, ObjectiveFunction{ScalarAffineFunction{Float64}}(), ScalarConstantChange(10.0))\n\nMultiple modifications in Constraint Functions\n\nmodify(\n model::ModelLike,\n cis::AbstractVector{<:ConstraintIndex},\n changes::AbstractVector{<:AbstractFunctionModification},\n)\n\nApply multiple modifications specified by changes to the functions of constraints cis.\n\nA ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by model.\n\nExamples\n\nmodify(\n model,\n [ci, ci],\n [\n ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),\n ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),\n ],\n)\n\nMultiple modifications in the Objective Function\n\nmodify(\n model::ModelLike,\n attr::ObjectiveFunction,\n changes::AbstractVector{<:AbstractFunctionModification},\n)\n\nApply multiple modifications specified by changes to the functions of constraints cis.\n\nA ModifyObjectiveNotAllowed error is thrown if modifying objective coefficients is not supported by model.\n\nExamples\n\nmodify(\n model,\n ObjectiveFunction{ScalarAffineFunction{Float64}}(),\n [\n ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),\n ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),\n ],\n)\n\n\n\n\n\n","category":"function"},{"location":"reference/modification/#MathOptInterface.AbstractFunctionModification","page":"Modifications","title":"MathOptInterface.AbstractFunctionModification","text":"AbstractFunctionModification\n\nAn abstract supertype for structs which specify partial modifications to functions, to be used for making small modifications instead of replacing the functions entirely.\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.ScalarConstantChange","page":"Modifications","title":"MathOptInterface.ScalarConstantChange","text":"ScalarConstantChange{T}(new_constant::T)\n\nA struct used to request a change in the constant term of a scalar-valued function.\n\nApplicable to ScalarAffineFunction and ScalarQuadraticFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.VectorConstantChange","page":"Modifications","title":"MathOptInterface.VectorConstantChange","text":"VectorConstantChange{T}(new_constant::Vector{T})\n\nA struct used to request a change in the constant vector of a vector-valued function.\n\nApplicable to VectorAffineFunction and VectorQuadraticFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.ScalarCoefficientChange","page":"Modifications","title":"MathOptInterface.ScalarCoefficientChange","text":"ScalarCoefficientChange{T}(variable::VariableIndex, new_coefficient::T)\n\nA struct used to request a change in the linear coefficient of a single variable in a scalar-valued function.\n\nApplicable to ScalarAffineFunction and ScalarQuadraticFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.MultirowChange","page":"Modifications","title":"MathOptInterface.MultirowChange","text":"MultirowChange{T}(\n variable::VariableIndex,\n new_coefficients::Vector{Tuple{Int64,T}},\n) where {T}\n\nA struct used to request a change in the linear coefficients of a single variable in a vector-valued function.\n\nNew coefficients are specified by (output_index, coefficient) tuples.\n\nApplicable to VectorAffineFunction and VectorQuadraticFunction.\n\n\n\n\n\n","category":"type"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"CurrentModule = MathOptInterface","category":"page"},{"location":"changelog/#Release-notes","page":"Release notes","title":"Release notes","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.","category":"page"},{"location":"changelog/#v1.20.0-(September-7,-2023)","page":"Release notes","title":"v1.20.0 (September 7, 2023)","text":"","category":"section"},{"location":"changelog/#Added","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Scaled set (#2237) (#2263) (#2264)\nAdded ObjectiveLimit attribute (#2257)","category":"page"},{"location":"changelog/#Other","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Updated dependencies (#2258)\nImproved performance of ScalarNonlinearFunction utilities (#2259)\nFixed docstrings (#2261)","category":"page"},{"location":"changelog/#v1.19.0-(August-15,-2023)","page":"Release notes","title":"v1.19.0 (August 15, 2023)","text":"","category":"section"},{"location":"changelog/#Added-2","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added VectorNonlinearFunction (#2201)\nAdded new bridges\nBridges.Constraint.IntegerToZeroOneBridge (#2205)\nBridges.Constraint.ToScalarQuadraticBridge (#2235)\nBridges.Constraint.ToVectorQuadraticBridge (#2235)\nBridges.Constraint.ToScalarNonlinearBridge (#2233) (#2235)\nBridges.Constraint.FunctionConversionBridge (#2235)\nAdded Bridges.bridging_cost for setting a bridge-specific cost in the bridging graph (#2235)\nAdded Utilities.eval_variables support for ScalarNonlinearFunction (#2218) (#2219)\nAdded support for ScalarNonlinearFunction in FileFormats.NL (#2228) (#2231)\nAdded support for writing non-Float64 functions in FileFormats.MOF\nAdded Utilities.lazy_map (#2254)","category":"page"},{"location":"changelog/#Fixed","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed method ambiguities in operate (#2224)\nFixed reading LP file with a -infinity <= x <= +infinity variable (#2225)\nFixed missing require in Test.test_nonlinear_duals (#2230)\nFixed bug in ConstraintPrimal of Bridges.Constraint.QuadtoSOCBridge (#2240)","category":"page"},{"location":"changelog/#Other-2","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added extensions to solver-tests.yml (#2229)\nRefactored test/Benchmarks (#2234)\nFixed warnings in tests (#2241) (#2243)\nSmall refactoring of bridges for upcoming VectorNonlinearFunction (#2244) (#2245)\nFixed various typos (#2251) (#2255)\nPartitioned how we run the tests on GitHub actions (#2252) (#2253)","category":"page"},{"location":"changelog/#v1.18.0-(June-23,-2023)","page":"Release notes","title":"v1.18.0 (June 23, 2023)","text":"","category":"section"},{"location":"changelog/#Added-3","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Bridges.Objective.SlackBridgePrimalDualStart (#2194)\nAdded constraint_gradient_structure and eval_constraint_gradient (#2200)","category":"page"},{"location":"changelog/#Fixed-2","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a missing @require in MOI.Test (#2195) (#2196)\nFixed incorrect usage of Utilities.operate! in bridges (#2207) (#2216)\nFixed splatting nonlinear expression with univariate operator (#2221)","category":"page"},{"location":"changelog/#Other-3","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Removed unused argument names (#2199)\nReduced memory requirement for tests (#2204)\nRefactored Utilities.promote_operation (#2206)\nImproved code style in Utilities/mutable_arithmetics.jl (#2209)\nRefactored various methods in Utilities/functions.jl (#2208) (#2212) (#2213) (#2214) (#2215)","category":"page"},{"location":"changelog/#v1.17.1-(June-6,-2023)","page":"Release notes","title":"v1.17.1 (June 6, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-3","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed comparison of ScalarFunctionConstantNotZero (#2190)","category":"page"},{"location":"changelog/#Other-4","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added documentation for enum instances (#2186)\nUpdated chatroom links in documentation (#2188)\nChanged the documentation to build on Julia v1.9 (#2191)","category":"page"},{"location":"changelog/#v1.17.0-(June-1,-2023)","page":"Release notes","title":"v1.17.0 (June 1, 2023)","text":"","category":"section"},{"location":"changelog/#Added-4","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added ScalarNonlinearFunction (#2059)\nAdded a variety of tests for NormSpectralCone, NormNuclearCone, and HermitianPositiveSemidefiniteConeTriangle (#2174)\nAdded Utilities.value_type for computing the value type of a function (#2176)","category":"page"},{"location":"changelog/#Fixed-4","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed support for external sets in Utilities.loadfromstring! (#2177)\nFixed promote_operation for ScalarNonlinearFunction (#2179)\nFixed two issues in FileFormats.LP when reading files with quadratic functions (#2182) (#2184)","category":"page"},{"location":"changelog/#v1.16.0-(May-16,-2023)","page":"Release notes","title":"v1.16.0 (May 16, 2023)","text":"","category":"section"},{"location":"changelog/#Added-5","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added support for MathOptFormat v1.3 and v1.4 (#2158) (#2169)\nAdded new method to the nonlinear API (#2162) (#2164)\neval_hessian_constraint\neval_hessian_objective\nhessian_constraint_structure\nhessian_objective_structure\nAdded new sets\nNormCone (#2119)\nScaledPositiveSemidefiniteConeTriangle (#2154)","category":"page"},{"location":"changelog/#Fixed-5","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed support for Julia v1.9 to work around a bug in the upstream Julia compiler (#2161) (#2163)\nFixed a correctness bug in Bridges.Constraint.HermitianToSymmetricPSDBridge (#2171)\nFixed convert(::VariableIndex, ::ScalarAffineFunction) when the function has terms with 0coefficients (#2173)","category":"page"},{"location":"changelog/#Other-5","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed solver-tests.yml (#2157)\nUpdated documentation links to developer chatroom (#2160)\nAdded various tests for bridges (#2156)\nAdded checklists to the developer documentation (#2167) (#2168)","category":"page"},{"location":"changelog/#v1.15.1-(April-25,-2023)","page":"Release notes","title":"v1.15.1 (April 25, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-6","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed deleting a variable in a bridged objective (#2150)","category":"page"},{"location":"changelog/#v1.15.0-(April-19,-2023)","page":"Release notes","title":"v1.15.0 (April 19, 2023)","text":"","category":"section"},{"location":"changelog/#Added-6","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Bridges.Objective.VectorFunctionizeBridge (#2139)","category":"page"},{"location":"changelog/#Fixed-7","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed support for Rational in Bridges.Constraint.SplitIntervalBridge (#2137)\nFixed printing of LaTeX models (#2141)\nFixed modify in Bridges.Objective.VectorSlackBridge (#2144)\nFixed NAME record with spaces in FileFormats.MPS (#2146)\nFixed deleting a variable in a bridged objective (#2147)","category":"page"},{"location":"changelog/#Other-6","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add a test for variables in one-sided open Interval sets (#2133)\nMinor style fixes in the source code (#2148)","category":"page"},{"location":"changelog/#v1.14.1-(April-6,-2023)","page":"Release notes","title":"v1.14.1 (April 6, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-8","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in Bridges.print_active_bridges (#2135)","category":"page"},{"location":"changelog/#Other-7","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added a warning when an ambiguous string is passed to exclude in Test.runtests (#2136)","category":"page"},{"location":"changelog/#v1.14.0-(April-4,-2023)","page":"Release notes","title":"v1.14.0 (April 4, 2023)","text":"","category":"section"},{"location":"changelog/#Added-7","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added support for starting values in Bridges.Constraint.QuadtoSOCBridge (#2115)\nAdded support for Regex in the include and exclude arguments to Test.runtests (#2129)\nAdded Bridges.print_active_bridges methods for individual objectives and constraints (#2128)","category":"page"},{"location":"changelog/#Fixed-9","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed ResultCount when parsing .sol files in FileFormats.NL (#2130)","category":"page"},{"location":"changelog/#v1.13.2-(March-21,-2023)","page":"Release notes","title":"v1.13.2 (March 21, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-10","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed splatting of containers in MOI.Nonlinear (#2120)\nFixed a bug reading LP files with default bounds (#2121)\nFixed a bug in which Bridges.Constraint.HermitianToSymmetricPSDBridge was not enabled by default (#2123)","category":"page"},{"location":"changelog/#Other-8","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed typos in the documentation (#2114)\nFunctions now print to the REPL in algebraic form. This is potentially breaking if you have tests which rely on a specific String form of MOI functions. (#2112) (#2126)","category":"page"},{"location":"changelog/#v1.13.1-(March-3,-2023)","page":"Release notes","title":"v1.13.1 (March 3, 2023)","text":"","category":"section"},{"location":"changelog/#Other-9","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added the Google style guide to the documentation linter Vale, and fixed the resulting warnings (#2110)\nImproved the docstrings in src/functions.jl (#2108)","category":"page"},{"location":"changelog/#v1.13.0-(February-28,-2023)","page":"Release notes","title":"v1.13.0 (February 28, 2023)","text":"","category":"section"},{"location":"changelog/#Added-8","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Bridges.Constraint.NumberConversionBridge (#2091)\nAdded Parameter set (#2095) (#2105) (#2106) (#2109)\nAdded with_cache_type argument to instantiate (#2097)\nAdded support for HermitianPositiveSemidefiniteConeTriangle in Utilities.Model (#2100)","category":"page"},{"location":"changelog/#Fixed-11","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed bug when Utilities.@product_of_sets is empty (#2101)\nFixed Bridges.print_active_bridges when variable bridge is an AbstractScalarSet (#2107)","category":"page"},{"location":"changelog/#Other-10","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added tests for vector-valued objective functions in FileFormats.MOF (#2093)\nUsed and documented preference for import MathOptInterface as MOI (#2096)\nFix and test links in the documentation with linkcheck = true (#2098)\nImproved docstrings of sets in src/sets.jl (#2099)\nSkip checking flakey links in documentation with linkcheck_ignore (#2103)","category":"page"},{"location":"changelog/#v1.12.0-(February-10,-2023)","page":"Release notes","title":"v1.12.0 (February 10, 2023)","text":"","category":"section"},{"location":"changelog/#Added-9","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added support for vector-valued objective functions (#2070)\nAdded a Utilities.distance_to_set method for SecondOrderCone (#2060)","category":"page"},{"location":"changelog/#Fixed-12","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a number of constraint bridges so that Bridges.final_touch can be called multiple times without forcing a rebuild of the reformulation (#2089)","category":"page"},{"location":"changelog/#Other-11","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new tests that a set ObjectiveFunction appears in ListOfModelAttributesSet (#2085)\nImproved the docstrings of a number of constraint-programming related sets (#2087)","category":"page"},{"location":"changelog/#v1.11.5-(January-24,-2023)","page":"Release notes","title":"v1.11.5 (January 24, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-13","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug writing .lp files with an off-diagonal quadratic objective (#2082)","category":"page"},{"location":"changelog/#Other-12","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added SnoopPrecompile directives for reduced time-to-first-X in Julia v1.9 (#2080)","category":"page"},{"location":"changelog/#v1.11.4-(January-12,-2023)","page":"Release notes","title":"v1.11.4 (January 12, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-14","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .lp files with an Integer section (#2078)","category":"page"},{"location":"changelog/#v1.11.3-(January-12,-2023)","page":"Release notes","title":"v1.11.3 (January 12, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-15","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a performance bug when deleting a vector of constraints (#2072)\nFixed a bug reading .lp files with terms like x -1 y (#2076)","category":"page"},{"location":"changelog/#Other-13","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Documented the two-argument method of optimize! (#2074)","category":"page"},{"location":"changelog/#v1.11.2-(January-2,-2023)","page":"Release notes","title":"v1.11.2 (January 2, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-16","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .mof.json files with ConstraintName set for VariableIndex constraints (#2066)\nFixed a bug reading .mof.json files with nonlinear objectives and no constraints (#2068)","category":"page"},{"location":"changelog/#v1.11.1-(December-22,-2022)","page":"Release notes","title":"v1.11.1 (December 22, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-17","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .mof.json files with integer coefficients for affine and quadratic functions (#2063)","category":"page"},{"location":"changelog/#v1.11.0-(December-2,-2022)","page":"Release notes","title":"v1.11.0 (December 2, 2022)","text":"","category":"section"},{"location":"changelog/#Added-10","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Utilities.PenaltyRelaxation and Utilities.ScalarPenaltyRelaxation (#1995)\nAdded Utilities.distance_to_set (#2048)\nAdded support for ConstraintPrimalStart and ConstraintDualStart in FileFormats.MOF (#2056)","category":"page"},{"location":"changelog/#Other-14","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Tidied these release notes (#2055)","category":"page"},{"location":"changelog/#v1.10.0-(November-22,-2022)","page":"Release notes","title":"v1.10.0 (November 22, 2022)","text":"","category":"section"},{"location":"changelog/#Added-11","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new methods set(::OptimizerWithAttributes, ::RawOptimizerAttribute, value) and get(::OptimizerWithAttributes, ::RawOptimizerAttribute) (#2049)\nAdded new methods Utilities.DoubleDicts.outer_keys and Utilities.DoubleDicts.nonempty_outer_keys (#2052)","category":"page"},{"location":"changelog/#Fixed-18","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed Bridges.Objective.SlackBridge when the objective function is complex-valued (#2036) (#2038)\nFixed docstring of Test.runtests to clarify the warn_unsupported argument (#2037)\nFixed reading of free variables in FileFormats.LP (#2044)\nFixed numerous edge cases reading files from QPLIB using FileFormats.LP (#2042) (#2044)\nFixed situations in which x^y returns a complex value in Nonlinear (#2050)","category":"page"},{"location":"changelog/#Other-15","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved the error message thrown when a user-defined nonlinear function does not accept splatted input (#2032)\nRemoved specialized iterators for keys and values in Utilities.CleverDicts (#2051)","category":"page"},{"location":"changelog/#v1.9.0-(October-29,-2022)","page":"Release notes","title":"v1.9.0 (October 29, 2022)","text":"","category":"section"},{"location":"changelog/#Added-12","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added default fallback for getting ListOfConstraintIndices and NumberOfConstraints when the constraint type is unsupported by the model (#2021)\nAdded support for min and max in nonlinear expressions (#2023)\nAdded support for Indicator{EqualTo{T}} constraints in FileFormats.MPS (#2022)\nAdded default fallback for write_to_file and read_from_file (#2029)","category":"page"},{"location":"changelog/#Fixed-19","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed Constraint.ZeroOneBridge by adding new bounds as affine constraints instead of variable bounds (#1879)\nFixed reading free rows in FileFormats.MPS files (#2009)\nFixed parsing of OBJSENSE blocks in FileFormats.MPS files (#2016) (#2019)\nFixed the parsing of deeply nested nonlinear expressions by removing the use of recursion (#2020)\nFixed the requirements check in Test.test_constrainnt_get_ConstraintIndex (#2024)","category":"page"},{"location":"changelog/#v1.8.2-(September-20,-2022)","page":"Release notes","title":"v1.8.2 (September 20, 2022)","text":"","category":"section"},{"location":"changelog/#Documentation","page":"Release notes","title":"Documentation","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added vale as a documentation linter (#2002)\nImproved styling of code blocks in the PDF (#1999) (#2000)\nFixed a number of typos in the documentation (#2001) (#2003)","category":"page"},{"location":"changelog/#v1.8.1-(September-12,-2022)","page":"Release notes","title":"v1.8.1 (September 12, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-20","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in supports(::AbstractBridgeOptimizer for constraint attributes (#1991) (#1992)","category":"page"},{"location":"changelog/#v1.8.0-(September-1,-2022)","page":"Release notes","title":"v1.8.0 (September 1, 2022)","text":"","category":"section"},{"location":"changelog/#Added-13","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new sets\nHyperRectangle (#1961)\nReified (#1955)\nAdded new bridges (#1955)\nBridges.Constraint.ReifiedAllDifferentToCountDistinctBridge\nBridges.Constraint.ReifiedCountDistinctToMILPBridge\nBridges.Constraint.SplitHyperRectangleBridge\nAdded support for atan(y, x) in Nonlinear (#1987)","category":"page"},{"location":"changelog/#Fixed-21","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Lazily construct expressions in Nonlinear so that expressions are updated when Nonlinear.Parameter values are updated (#1984)\nAllow NORM_LIMIT as a TerminationStatus for unbounded problems in Test (#1990)","category":"page"},{"location":"changelog/#v1.7.0-(August-16,-2022)","page":"Release notes","title":"v1.7.0 (August 16, 2022)","text":"","category":"section"},{"location":"changelog/#Added-14","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new sets\nHermitianPositiveSemidefiniteConeTriangle\nAdded new optimizer-independent options\nRelativeGapTolerance\nAbsoluteGapTolerance\nAdded new bridges\nBridges.Constraint.GeoMeanToPowerBridge\nBridges.Constraint.HermitianToSymmetricPSDBridge\nBridges.Constraint.IndicatorGreaterToLessThanBridge\nBridges.Constraint.IndicatorLessToGreaterThanBridge\nBridges.Constraint.SplitComplexZerosBridge\nBridges.Constraint.SplitComplexEqualToBridge\nBridges.Objective.QuadratizeBridge\nAdded support for generic number types in Utilities.loadfromstring!\nUpdated FileFormats.MOF to MathOptFormat v1.1, enabling support for constraint programming sets in the MOF file format\nAdded support in various FileFormats for\nindicator constraints in FileFormats.MPS\nquadratic constraints and an objective in FileFormats.LP\nquadratic constraints and an objective in FileFormats.MPS","category":"page"},{"location":"changelog/#Fixed-22","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed some missing promotion rules","category":"page"},{"location":"changelog/#Other-16","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved the performance of Jacobian products in Nonlinear\nRemoved an un-needed copy in Utilities.modify_function\nVarious clean-ups in Bridges/bridge_optimizer.jl","category":"page"},{"location":"changelog/#v1.6.1-(July-23,-2022)","page":"Release notes","title":"v1.6.1 (July 23, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-23","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added support for ExponentialCone in MatrixOfConstraints\nFix PSDSquare_3 test to reflect a previously fixed bug getting the ConstraintDual of a PositiveSemidefiniteConeSquare constraint","category":"page"},{"location":"changelog/#v1.6.0-(July-2,-2022)","page":"Release notes","title":"v1.6.0 (July 2, 2022)","text":"","category":"section"},{"location":"changelog/#Added-15","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Bridges.needs_final_touch and Bridges.final_touch\nAdded new bridges from constraint programming sets to mixed-integer linear programs:\nAllDifferentToCountDistinctBridge\nCountAtLeastToCountBelongsBridge\nCountBelongsToMILPBridge\nCountDistinctToMILPBridge\nCountGreaterThanToMILPBridge\nCircuitToMILPBridge","category":"page"},{"location":"changelog/#Fixed-24","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Relax an instance of ::Vector to ::AbstractVector in MOI.Nonlinear\nFix BinPackingToMILPBridge to respect variable bounds\nFix SemiToBinaryBridge to throw error if other bounds are set","category":"page"},{"location":"changelog/#v1.5.0-(June-27,-2022)","page":"Release notes","title":"v1.5.0 (June 27, 2022)","text":"","category":"section"},{"location":"changelog/#Added-16","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added GetAttributeNotAllowed for solvers to indicate when getting an attribute encounters an error\nAdded Utilities.get_fallback support for ObjectiveValue and DualObjectiveValue\nAdded new bridges:\nRootDetConeSquare to RootDetConeTriangle\nLogDetConeSquare to LogDetConeTriangle\nBinPacking to a mixed-integer linear program\nTable to a mixed-integer linear program\nAdded Bridges.print_active_bridges to display the current optimal hyper-path in a Bridges.LazyBridgeOptimizer","category":"page"},{"location":"changelog/#Fixed-25","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed ZeroOne tests with lower and upper bounds\nFixed error in FileFormats.LP when reading a malformed file\nFixed reading of nonlinear programs in FileFormats.MOF\nFixed bug in ConstraintDual when using SquareBridge","category":"page"},{"location":"changelog/#Other-17","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved documentation of nonlinear API\nDocumented duality convention for PositiveSemidefiniteConeSquare sets\nFixed typo in Bridges.Constraint.QuadToSOCBridge docstring","category":"page"},{"location":"changelog/#v1.4.0-(June-9,-2022)","page":"Release notes","title":"v1.4.0 (June 9, 2022)","text":"","category":"section"},{"location":"changelog/#Added-17","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added a number of sets for constraint programming:\nAllDifferent\nBinPacking\nCircuit\nCountAtLeast\nCountBelongs\nCountDistinct\nCountGreaterThan\nCumulative\nPath\nTable\nAdded support for user-defined hessians in Nonlinear\nAdded Bridges.runtests to simplify the testing of bridge implementations","category":"page"},{"location":"changelog/#Fixed-26","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in FileFormats.NL when writing univariate *","category":"page"},{"location":"changelog/#Other-18","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Began a large refactoring of the Bridges submodule, with greatly improved documentation.","category":"page"},{"location":"changelog/#v1.3.0-(May-27,-2022)","page":"Release notes","title":"v1.3.0 (May 27, 2022)","text":"","category":"section"},{"location":"changelog/#Added-18","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add MOI.Nonlinear submodule. This is a large new submodule that has been refactored from code that was in JuMP. For now, it should be considered experimental.\nAdd FileFormats.NL.SolFileResults(::IO, ::Model)\nAdd FileFormats.NL.read!(::IO, ::Model)\nAdd MOI.modify that accepts a vector of modifications","category":"page"},{"location":"changelog/#Fixed-27","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in Test which attempted to include non-.jl files\nFixed a bug in FileFormats for models with open interval constraints","category":"page"},{"location":"changelog/#Other-19","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a performance issue in Utilities.DoubleDict\nVarious minor improvements to the documentation","category":"page"},{"location":"changelog/#v1.2.0-(April-25,-2022)","page":"Release notes","title":"v1.2.0 (April 25, 2022)","text":"","category":"section"},{"location":"changelog/#Added-19","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add support for the FORMAT_REW/.rew file format in FileFormats.","category":"page"},{"location":"changelog/#Fixed-28","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix bug handling of default variable bounds in FileFormats.LP\nFix FileFormats.MPS to not write OBJSENSE by default since this is only supported by some readers.","category":"page"},{"location":"changelog/#v1.1.2-(March-31,-2022)","page":"Release notes","title":"v1.1.2 (March 31, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-29","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix a range of bugs in FileFormats.LP\nFix reading of problem dimensions in FileFormats.SDPA","category":"page"},{"location":"changelog/#v1.1.1-(March-23,-2022)","page":"Release notes","title":"v1.1.1 (March 23, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-30","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix bug in test_model_UpperBoundAlreadySet\nFix bug in test_infeasible_ tests\nFix bug in test_objective_ObjectiveFunction_blank\nRelax restriction of MOI.AbstractOptimizer to MOI.ModelLike in Utilities.CachingOptimizer and instantiate.","category":"page"},{"location":"changelog/#New-tests","page":"Release notes","title":"New tests","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add test_conic_empty_matrix that checks conic solvers support problems with no variables.","category":"page"},{"location":"changelog/#v1.1.0-(March-2,-2022)","page":"Release notes","title":"v1.1.0 (March 2, 2022)","text":"","category":"section"},{"location":"changelog/#Added-20","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added MOI.Utilities.throw_unsupported(::UniversalFallback) for simplifying solver wrappers which copy from a UniversalFallback.","category":"page"},{"location":"changelog/#v1.0.2-(March-1,-2022)","page":"Release notes","title":"v1.0.2 (March 1, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-31","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in the test_model_ScalarFunctionConstantNotZero test\nFixed the error type when an AbstractFunctionConversionBridge cannot get or set an attribute\nIdentified a correctness bug in RSOCtoPSDBridge. We now thrown an error instead of returning an incorrect result.","category":"page"},{"location":"changelog/#v1.0.1-(February-25,-2022)","page":"Release notes","title":"v1.0.1 (February 25, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-32","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in which OptimizerAttributes were not copied in CachingOptimizer\nFixed a bug in which shift_constant did not promote mixed types of coefficients\nFixed a bug in which deleting a constraint of a bridged variable threw ErrorException instead of MOI.DeleteNotAllowed\nFixed a bug in which add_constraint in MatrixOfConstraints did not canonicalize the function\nFixed a bug when modifying scalar constants of a function containing a bridged variable\nFixed a bug in which final_touch was not always called with a CachingOptimizer","category":"page"},{"location":"changelog/#v1.0.0-(February-17,-2022)","page":"Release notes","title":"v1.0.0 (February 17, 2022)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Although tagged as a breaking release, v1.0.0 is v0.10.9 with deprecations removed, similar to how Julia 1.0 was Julia 0.7 with deprecations removed.","category":"page"},{"location":"changelog/#Breaking","page":"Release notes","title":"Breaking","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Julia 1.6 is now the minimum supported version\nAll deprecations have been removed","category":"page"},{"location":"changelog/#Troubleshooting-problems-when-updating","page":"Release notes","title":"Troubleshooting problems when updating","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"If you experience problems when updating, you are likely using previously deprecated features. (By default, Julia does not warn when you use deprecated features.)","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"To find the deprecated features you are using, start Julia with --depwarn=yes:","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"$ julia --depwarn=yes","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Then install MathOptInterface v0.10.9:","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"julia> using Pkg\njulia> pkg\"add MathOptInterface@0.10\"","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"And then run your code. Apply any suggestions, or search the release notes below for advice on updating a specific deprecated feature.","category":"page"},{"location":"changelog/#v0.10.9-(February-16,-2022)","page":"Release notes","title":"v0.10.9 (February 16, 2022)","text":"","category":"section"},{"location":"changelog/#Added-21","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added MOI.Utilities.FreeVariables as a new VariablesConstrainer for conic solvers\nAdded MOI.default_cache for specifying the model used in CachingOptimizer","category":"page"},{"location":"changelog/#Fixed-33","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed LaTeX printing of MOI.Interval sets","category":"page"},{"location":"changelog/#Other-20","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Aqua.jl as a CI check, and fixed suggested issues\nThe constructors of GeoMeanBridge, StructOfConstraints, and CachingOptimizer were changed from outer to inner constructors. This change is technically breaking, but does not impact users who followed the documented API.","category":"page"},{"location":"changelog/#v0.10.8-(February-3,-2022)","page":"Release notes","title":"v0.10.8 (February 3, 2022)","text":"","category":"section"},{"location":"changelog/#Added-22","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added a Base.read! for FileFormats.LP.","category":"page"},{"location":"changelog/#Fixed-34","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in MutableSparseMatrix\nFixed a bug when calling operate!(vcat, ...) with Number arguments\nRemoved unintended export of deprecated symbols\nFixed a bug with PowerCone and DualPowerCone in MatrixOfConstraints.","category":"page"},{"location":"changelog/#v0.10.7-(January-5,-2022)","page":"Release notes","title":"v0.10.7 (January 5, 2022)","text":"","category":"section"},{"location":"changelog/#Added-23","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added test for modifying the constant vector in a VectorAffineFunction-in-Zeros constraint.","category":"page"},{"location":"changelog/#Fixed-35","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed the order in which sets are added to a LazyBridgeOptimizer. Compared to v0.10.6, this may result in bridged models being created with a different number (and order) of variables and constraints. However, it was necessary to fix cases which were previously rejected as unsupported, even though there was a valid bridge transformation.\nFixed an error message in FileFormats.CBF\nFixed comparison in test_linear_integration_Interval\nFixed errors for ConstraintPrimal in a CachingOptimizer\nFixed printing of models with non-Float64 coefficients.","category":"page"},{"location":"changelog/#Other-21","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Various improvements to reduce time-to-first-solve latency\nImproved error message when an optimizer does not support compute_conflict!","category":"page"},{"location":"changelog/#v0.10.6-(November-30,-2021)","page":"Release notes","title":"v0.10.6 (November 30, 2021)","text":"","category":"section"},{"location":"changelog/#Added-24","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new documentation and tests for infeasibility certificates\nAdded a version control system for the tests in MOI.Test.runtests. Pass exclude_tests_after = v\"0.10.5\" to run tests added in v0.10.5 and earlier.\nMOI.Test.runtests now supports generic number types. To specify the number type T, pass MOI.Test.Config(T).\nAdded infeasible_status to MOI.Test.Config for solvers which return LOCALLY_INFEASIBLE\nCachingOptimizers now use a fallback for ConstraintPrimal. This should enable solvers using a CachingOptimizer to pass tests requiring ConstraintPrimal.","category":"page"},{"location":"changelog/#Fixed-36","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a StackOverflow bug in copy_to\nFixed error thrown when nonconvex quadratic constraints cannot be bridged\nFixed a bug in copy_to for FileFormats.NL.Model\nFixed a bug in FileFormats.NL when printing large integers\nRemove a common test failure for LowerBoundAlreadySet tests\nUtilities.num_rows is now exported\nRemove parts of failing test_model_copy_to_xxx tests due to bridges","category":"page"},{"location":"changelog/#v0.10.5-(November-7,-2021)","page":"Release notes","title":"v0.10.5 (November 7, 2021)","text":"","category":"section"},{"location":"changelog/#Fixed-37","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed getter in UniversalFallback\nFixed test_solve_conflict_zeroone_ii","category":"page"},{"location":"changelog/#Other-22","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Make normalize_and_add_constraint more flexible\nUpdate paper BibTeX","category":"page"},{"location":"changelog/#v0.10.4-(October-26,-2021)","page":"Release notes","title":"v0.10.4 (October 26, 2021)","text":"","category":"section"},{"location":"changelog/#Added-25","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add SolverVersion attribute\nAdd new tests:\ntest_solve_conflict_zeroone_ii\ntest_nonlinear_objective\nUtilities.VariablesContainer now supports ConstraintFunction and ConstraintSet\nThe documentation is now available as a PDF","category":"page"},{"location":"changelog/#Other-23","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Update to MutableArithmetics 0.3\nVarious improvements to the documentation","category":"page"},{"location":"changelog/#v0.10.3-(September-18,-2021)","page":"Release notes","title":"v0.10.3 (September 18, 2021)","text":"","category":"section"},{"location":"changelog/#Fixed-38","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed bug which prevented callbacks from working through a CachingOptimizer\nFixed bug in Test submodule","category":"page"},{"location":"changelog/#v0.10.2-(September-16,-2021)","page":"Release notes","title":"v0.10.2 (September 16, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Updated MathOptFormat to v1.0\nUpdated JSONSchema to v1.0\nAdded Utilities.set_with_dimension\nAdded two-argument optimize!(::AbstractOptimizer, ::ModelLike)\nThe experimental feature copy_to_and_optimize! has been removed\nDet bridges now support getting ConstraintFunction and ConstraintSet\nVarious minor bug fixes identified by improved testing","category":"page"},{"location":"changelog/#v0.10.1-(September-8,-2021)","page":"Release notes","title":"v0.10.1 (September 8, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Various fixes to MOI.Test","category":"page"},{"location":"changelog/#v0.10.0-(September-6,-2021)","page":"Release notes","title":"v0.10.0 (September 6, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"MOI v0.10 is a significant breaking release. There are a large number of user-visible breaking changes and code refactors, as well as a substantial number of new features.","category":"page"},{"location":"changelog/#Breaking-in-MOI","page":"Release notes","title":"Breaking in MOI","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"SingleVariable has been removed; use VariableIndex instead\nSingleVariableConstraintNameError has been renamed to VariableIndexConstraintNameError\nSettingSingleVariableFunctionNotAllowed has been renamed to SettingVariableIndexFunctionNotAllowed\nVariableIndex constraints should not support ConstraintName\nVariableIndex constraints should not support ConstraintBasisStatus; implement VariableBasisStatus instead\nListOfConstraints has been renamed to ListOfConstraintTypesPresent\nListOfConstraintTypesPresent should now return Tuple{Type,Type} instead of Tuple{DataType,DataType}\nSolveTime has been renamed to SolveTimeSec\nIndicatorSet has been renamed to Indicator\nRawParameter has been renamed to RawOptimizerAttribute and now takes String instead of Any as the only argument\nThe .N field in result attributes has been renamed to .result_index\nThe .variable_index field in ScalarAffineTerm has been renamed to .variable\nThe .variable_index_1 field in ScalarQuadraticTerm has been renamed to .variable_1\nThe .variable_index_2 field in ScalarQuadraticTerm has been renamed to .variable_2\nThe order of affine_terms and quadratic_terms in ScalarQuadraticFunction and VectorQuadraticFunction have been reversed. Both functions now accept quadratic, affine, and constant terms in that order.\nThe index_value function has been removed. Use .value instead.\nisapprox has been removed for SOS1 and SOS2.\nThe dimension argument to Complements(dimension::Int) should now be the length of the corresponding function, instead of half the length. An ArgumentError is thrown if dimension is not even.\ncopy_to no longer takes keyword arguments:\ncopy_names: now copy names if they are supported by the destination solver\nfilter_constraints: use Utilities.ModelFilter instead\nwarn_attributes: never warn about optimizer attributes","category":"page"},{"location":"changelog/#Breaking-in-Bridges","page":"Release notes","title":"Breaking in Bridges","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Constraint.RSOCBridge has been renamed to Constraint.RSOCtoSOCBridge\nConstraint.SOCRBridge has been renamed to Constraint.SOCtoRSOCBridge\nBridges now return vectors that can be modified by the user. Previously, some bridges returned views instead of copies.\nBridges.IndexInVector has been unified into a single type. Previously, there was a different type for each submodule within Bridges\nThe signature of indicator bridges has been fixed. Use MOI.Bridges.Constraint.IndicatortoSOS1{Float64}(model).","category":"page"},{"location":"changelog/#Breaking-in-FileFormats","page":"Release notes","title":"Breaking in FileFormats","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"FileFormats.MOF.Model no longer accepts validate argument. Use the JSONSchema package to validate the MOF file. See the documentation for more information.","category":"page"},{"location":"changelog/#Breaking-in-Utilities","page":"Release notes","title":"Breaking in Utilities","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"The datastructure of Utilities.Model (and models created with Utilities.@model) has been significantly refactored in a breaking way. This includes the way that objective functions and variable-related information is stored.\nUtilities.supports_default_copy has been renamed to supports_incremental_interface\nUtilities.automatic_copy_to has been renamed to Utilities.default_copy_to\nThe allocate-load API has been removed\nCachingOptimizers are now initialized as EMPTY_OPTIMIZER instead of ATTACHED_OPTIMIZER. If your code relies on the optimizer being attached, call MOIU.attach_optimizer(model) after creation.\nThe field names of Utilities.IndexMap have been renamed to var_map and con_map. Accessing these fields directly is considered a private detail that may change. Use the public getindex and setindex! API instead.\nThe size argument to Utilities.CleverDicts.CleverDict(::Integer) has been removed.\nThe size argument to Utilities.IndexMap(::Integer) has been removed.\nUtilities.DoubleDicts have been significantly refactored. Consult the source code for details.\nUtilities.test_models_equal has been moved to MOI.Test","category":"page"},{"location":"changelog/#Breaking-in-Test","page":"Release notes","title":"Breaking in Test","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"MOI.Test has been renamed to MOI.DeprecatedTest\nAn entirely new MOI.Test submodule has been written. See the documentation for details. The new MOI.Test submodule may find many bugs in the implementations of existing solvers that were previously untested.","category":"page"},{"location":"changelog/#Other-changes:","page":"Release notes","title":"Other changes:","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"attribute_value_type has been added\ncopy_to_and_optimize! has been added\nVariableBasisStatus has been added\nprint(model) now prints a human-readable description of the model\nVarious improvements to the FileFormats submodule\nFileFormats.CBF was refactored and received bugfixes\nSupport for MathOptFormat v0.6 was added in FileFormats.MOF\nFileFormats.MPS has had bugfixes and support for more features such as OBJSENSE and objective constants.\nFileFormats.NL has been added to support nonlinear files\nImproved type inference throughout to reduce latency","category":"page"},{"location":"changelog/#Updating","page":"Release notes","title":"Updating","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"A helpful script when updating is:","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"for (root, dirs, files) in walkdir(\".\")\n for file in files\n if !endswith(file, \".jl\")\n continue\n end\n path = joinpath(root, file)\n s = read(path, String)\n for pair in [\n \".variable_index\" => \".variable\",\n \"RawParameter\" => \"RawOptimizerAttribute\",\n \"ListOfConstraints\" => \"ListOfConstraintTypesPresent\",\n \"TestConfig\" => \"Config\",\n \"attr.N\" => \"attr.result_index\",\n \"SolveTime\" => \"SolveTimeSec\",\n \"DataType\" => \"Type\",\n \"Utilities.supports_default_copy_to\" =>\n \"supports_incremental_interface\",\n \"SingleVariableConstraintNameError\" =>\n \"VariableIndexConstraintNameError\",\n \"SettingSingleVariableFunctionNotAllowed\" =>\n \"SettingVariableIndexFunctionNotAllowed\",\n \"automatic_copy_to\" => \"default_copy_to\",\n ]\n s = replace(s, pair)\n end\n write(path, s)\n end\nend","category":"page"},{"location":"changelog/#v0.9.22-(May-22,-2021)","page":"Release notes","title":"v0.9.22 (May 22, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"This release contains backports from the ongoing development of the v0.10 release.","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved type inference in Utilities, Bridges and FileFormats submodules to reduce latency.\nImproved performance of Utilities.is_canonical.\nFixed Utilities.pass_nonvariable_constraints with bridged variables.\nFixed performance regression of Utilities.Model.\nFixed ordering of objective setting in parser.","category":"page"},{"location":"changelog/#v0.9.21-(April-23,-2021)","page":"Release notes","title":"v0.9.21 (April 23, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added supports_shift_constant.\nImprove performance of bridging quadratic constraints.\nAdd precompilation statements.\nLarge improvements to the documentation.\nFix a variety of inference issues, benefiting precompilation and reducing initial latency.\nRawParameters are now ignored when resetting a CachingOptimizer. Previously, changing the underlying optimizer after RawParameters were set would throw an error.\nUtilities.AbstractModel is being refactored. This may break users interacting with private fields of a model generated using @model.","category":"page"},{"location":"changelog/#v0.9.20-(February-20,-2021)","page":"Release notes","title":"v0.9.20 (February 20, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved performance of Utilities.ScalarFunctionIterator\nAdded support for compute_conflict to MOI layers\nAdded test with zero off-diagonal quadratic term in objective\nFixed double deletion of nested bridged SingleVariable/VectorOfVariables constraints\nFixed modification of un-set objective\nFixed function modification with duplicate terms\nMade unit tests abort without failing if the problem class is not supported\nFormatted code with JuliaFormatter\nClarified BasisStatusCode's docstring","category":"page"},{"location":"changelog/#v0.9.19-(December-1,-2020)","page":"Release notes","title":"v0.9.19 (December 1, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added CallbackNodeStatus attribute\nAdded bridge from GreaterThan or LessThan to Interval\nAdded tests for infeasibility certificates and double optimize\nFixed support for Julia v1.6\nRe-organized MOI docs and added documentation for adding a test","category":"page"},{"location":"changelog/#v0.9.18-(November-3,-2020)","page":"Release notes","title":"v0.9.18 (November 3, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Various improvements for working with complex numbers\nAdded GeoMeantoRelEntrBridge to bridge a GeometricMeanCone constraint to a relative entropy constraint","category":"page"},{"location":"changelog/#v0.9.17-(September-21,-2020)","page":"Release notes","title":"v0.9.17 (September 21, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed CleverDict with variable of negative index value\nImplement supports_add_constrained_variable for MockOptimizer","category":"page"},{"location":"changelog/#v0.9.16-(September-17,-2020)","page":"Release notes","title":"v0.9.16 (September 17, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Various fixes:\n32-bit support\nCleverDict with abstract value type\nChecks in test suite","category":"page"},{"location":"changelog/#v0.9.15-(September-14,-2020)","page":"Release notes","title":"v0.9.15 (September 14, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Bridges improvements:\n(R)SOCtoNonConvexQuad bridge\nZeroOne bridge\nUse supports_add_constrained_variable in LazyBridgeOptimizer\nExposed VariableBridgeCost and ConstraintBridgeCost attributes\nPrioritize constraining variables on creation according to these costs\nRefactor bridge debugging\nLarge performance improvements across all submodules\nLots of documentation improvements\nFileFormats improvements:\nUpdate MathOptFormat to v0.5\nFix supported objectives in FileFormats\nTesting improvements:\nAdd name option for basic_constraint_test\nBug fixes and missing methods\nAdd length for iterators\nFix bug with duplicate terms\nFix order of LinearOfConstraintIndices","category":"page"},{"location":"changelog/#v0.9.14-(May-30,-2020)","page":"Release notes","title":"v0.9.14 (May 30, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add a solver-independent interface for accessing the set of conflicting constraints an Irreducible Inconsistent Subsystem (#1056).\nBump JSONSchema dependency from v0.2 to v0.3 (#1090).\nDocumentation improvements:\nFix typos (#1054, #1060, #1061, #1064, #1069, #1070).\nRemove the outdated recommendation for a package implementing MOI for a solver XXX to be called MathOptInterfaceXXX (#1087).\nUtilities improvements:\nFix is_canonical for quadratic functions (#1081, #1089).\nImplement add_constrained_variable[s] for CachingOptimizer so that it is added as constrained variables to the underlying optimizer (#1084).\nAdd support for custom objective functions for UniversalFallback (#1086).\nDeterministic ordering of constraints in UniversalFallback (#1088).\nTesting improvements:\nAdd NormOneCone/NormInfinityCone tests (#1045).\nBridges improvements:\nAdd bridges from Semiinteger and Semicontinuous (#1059).\nImplement getting ConstraintSet for Variable.FlipSignBridge (#1066).\nFix setting ConstraintFunction for Constraint.ScalarizeBridge (#1093).\nFix NormOne/NormInf bridges with nonzero constants (#1045).\nFix StackOverflow in debug (#1063).\nFileFormats improvements:\n[SDPA] Implement the extension for integer variables (#1079).\n[SDPA] Ignore comments after m and nblocks and detect dat-s extension (#1077).\n[SDPA] No scaling of off-diagonal coefficient (#1076).\n[SDPA] Add missing negation of constant (#1075).","category":"page"},{"location":"changelog/#v0.9.13-(March-24,-2020)","page":"Release notes","title":"v0.9.13 (March 24, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added tests for Semicontinuous and Semiinteger variables (#1033).\nAdded tests for using ExprGraphs from NLP evaluators (#1043).\nUpdate version compatibilities of dependencies (#1034, #1051, #1052).\nFixed typos in documentation (#1044).","category":"page"},{"location":"changelog/#v0.9.12-(February-28,-2020)","page":"Release notes","title":"v0.9.12 (February 28, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed writing NLPBlock in MathOptFormat (#1037).\nFixed MockOptimizer for result attributes with non-one result index (#1039).\nUpdated test template with instantiate (#1032).","category":"page"},{"location":"changelog/#v0.9.11-(February-21,-2020)","page":"Release notes","title":"v0.9.11 (February 21, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add an option for the model created by Utilities.@model to be a subtype of AbstractOptimizer (#1031).\nDescribed dual cone in docstrings of GeoMeanCone and RelativeEntropyCone (#1018, #1028).\nFixed typos in documentation (#1022, #1024).\nFixed warning of unsupported attribute (#1027).\nAdded more rootdet/logdet conic tests (#1026).\nImplemented ConstraintDual for Constraint.GeoMeanBridge, Constraint.RootDetBridge and Constraint.LogDetBridge and test duals in tests with GeoMeanCone and RootDetConeTriangle and LogDetConeTriangle cones (#1025, #1026).","category":"page"},{"location":"changelog/#v0.9.10-(January-31,-2020)","page":"Release notes","title":"v0.9.10 (January 31, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added OptimizerWithAttributes grouping an optimizer constructor and a list of optimizer attributes (#1008).\nAdded RelativeEntropyCone with corresponding bridge into exponential cone constraints (#993).\nAdded NormSpectralCone and NormNuclearCone with corresponding bridges into positive semidefinite constraints (#976).\nAdded supports_constrained_variable(s) (#1004).\nAdded dual_set_type (#1002).\nAdded tests for vector specialized version of delete (#989, #1011).\nAdded PSD3 test (#1007).\nClarified dual solution of Tests.pow1v and Tests.pow1f (#1013).\nAdded support for EqualTo and Zero in Bridges.Constraint.SplitIntervalBridge (#1005).\nFixed Utilities.vectorize for empty vector (#1003).\nFixed free variables in LP writer (#1006).","category":"page"},{"location":"changelog/#v0.9.9-(December-29,-2019)","page":"Release notes","title":"v0.9.9 (December 29, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Incorporated MathOptFormat.jl as the FileFormats submodule. FileFormats provides readers and writers for a number of standard file formats and MOF, a file format specialized for MOI (#969).\nImproved performance of deletion of vector of variables in MOI.Utilities.Model (#983).\nUpdated to MutableArithmetics v0.2 (#981).\nAdded MutableArithmetics.promote_operation allocation tests (#975).\nFixed inference issue on Julia v1.1 (#982).","category":"page"},{"location":"changelog/#v0.9.8-(December-19,-2019)","page":"Release notes","title":"v0.9.8 (December 19, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Implemented MutableArithmetics API (#924).\nFixed callbacks with CachingOptimizer (#959).\nFixed MOI.dimension for MOI.Complements (#948).\nAdded fallback for add_variables (#972).\nAdded is_diagonal_vectorized_index utility (#965).\nImproved linear constraints display in manual (#963, #964).\nBridges improvements:\nAdded IndicatorSet to SOS1 bridge (#877).\nAdded support for starting values for Variable.VectorizeBridge (#944).\nFixed MOI.add_constraints with non-bridged variable constraint on bridged variable (#951).\nFixed corner cases and docstring of GeoMeanBridge (#961, #962, #966).\nFixed choice between variable or constraint bridges for constrained variables (#973).\nImprove performance of bridge shortest path (#945, #946, #956).\nAdded docstring for test_delete_bridge (#954).\nAdded Variable bridge tests (#952).","category":"page"},{"location":"changelog/#v0.9.7-(October-30,-2019)","page":"Release notes","title":"v0.9.7 (October 30, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Implemented _result_index_field for NLPBlockDual (#934).\nFixed copy of model with starting values for vector constraints (#941).\nBridges improvements:\nImproved performance of add_bridge and added has_bridge (#935).\nAdded AbstractSetMapBridge for bridges between sets S1, S2 such that there is a linear map A such that A*S1 = S2 (#933).\nAdded support for starting values for FlipSignBridge, VectorizeBridge, ScalarizeBridge, SlackBridge, SplitIntervalBridge, RSOCBridge, SOCRBridge NormInfinityBridge, SOCtoPSDBridge and RSOCtoPSDBridge (#933, #936, #937, #938, #939).","category":"page"},{"location":"changelog/#v0.9.6-(October-25,-2019)","page":"Release notes","title":"v0.9.6 (October 25, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added complementarity constraints (#913).\nAllowed ModelLike objects as value of attributes (#928).\nTesting improvements:\nAdded dual_objective_value option to MOI.Test.TestConfig (#922).\nAdded InvalidIndex tests in basic_constraint_tests (#921).\nAdded tests for the constant term in indicator constraint (#929).\nBridges improvements:\nAdded support for starting values for Functionize bridges (#923).\nAdded variable indices context to variable bridges (#920).\nFixed a typo in printing o debug_supports (#927).","category":"page"},{"location":"changelog/#v0.9.5-(October-9,-2019)","page":"Release notes","title":"v0.9.5 (October 9, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Clarified PrimalStatus/DualStatus to be NO_SOLUTION if result_index is out of bounds (#912).\nAdded tolerance for checks and use ResultCount + 1 for the result_index in MOI.Test.solve_result_status (#910, #917).\nUse 0.5 instead of 2.0 for power in PowerCone in basic_constraint_test (#916).\nBridges improvements:\nAdded debug utilities for unsupported variable/constraint/objective (#861).\nFixed deletion of variables in bridged VectorOfVariables constraints (#909).\nFixed result_index with objective bridges (#911).","category":"page"},{"location":"changelog/#v0.9.4-(October-2,-2019)","page":"Release notes","title":"v0.9.4 (October 2, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added solver-independent MIP callbacks (#782).\nImplements submit for Utilities.CachingOptimizer and Bridges.AbstractBridgeOptimizer (#906).\nAdded tests for result count of solution attributes (#901, #904).\nAdded NumberOfThreads attribute (#892).\nAdded Utilities.get_bounds to get the bounds on a variable (#890).\nAdded a note on duplicate coefficients in documentation (#581).\nAdded result index in ConstraintBasisStatus (#898).\nAdded extension dictionary to Utilities.Model (#884, #895).\nFixed deletion of constrained variables for CachingOptimizer (#905).\nImplemented Utilities.shift_constraint for Test.UnknownScalarSet (#896).\nBridges improvements:\nAdded Variable.RSOCtoSOCBridge (#907).\nImplemented MOI.get for ConstraintFunction/ConstraintSet for Bridges.Constraint.SquareBridge (#899).","category":"page"},{"location":"changelog/#v0.9.3-(September-20,-2019)","page":"Release notes","title":"v0.9.3 (September 20, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed ambiguity detected in Julia v1.3 (#891, #893).\nFixed missing sets from ListOfSupportedConstraints (#880).\nFixed copy of VectorOfVariables constraints with duplicate indices (#886).\nAdded extension dictionary to MOIU.Model (#884).\nImplemented MOI.get for function and set for GeoMeanBridge (#888).\nUpdated documentation for SingleVariable indices and bridges (#885).\nTesting improvements:\nAdded more comprehensive tests for names (#882).\nAdded tests for SingleVariable duals (#883).\nAdded tests for DualExponentialCone and DualPowerCone (#873).\nImprovements for arbitrary coefficient type:\nFixed == for sets with mutable fields (#887).\nRemoved some Float64 assumptions in bridges (#878).\nAutomatic selection of Constraint.[Scalar|Vector]FunctionizeBridge (#889).","category":"page"},{"location":"changelog/#v0.9.2-(September-5,-2019)","page":"Release notes","title":"v0.9.2 (September 5, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Implemented model printing for MOI.ModelLike and specialized it for models defined in MOI (864).\nGeneralized contlinear tests for arbitrary coefficient type (#855).\nFixed supports_constraint for Semiinteger and Semicontinuous and supports for ObjectiveFunction (#859).\nFixed Allocate-Load copy for single variable constraints (#856).\nBridges improvements:\nAdd objective bridges (#789).\nFixed Variable.RSOCtoPSDBridge for dimension 2 (#869).\nAdded Variable.SOCtoRSOCBridge (#865).\nAdded Constraint.SOCRBridge and disable MOI.Bridges.Constraint.SOCtoPSDBridge (#751).\nFixed added_constraint_types for Contraint.LogDetBridge and Constraint.RootDetBridge (#870).","category":"page"},{"location":"changelog/#v0.9.1-(August-22,-2019)","page":"Release notes","title":"v0.9.1 (August 22, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix support for Julia v1.2 (#834).\nL1 and L∞ norm epigraph cones and corresponding bridges to LP were added (#818).\nAdded tests to MOI.Test.nametest (#833).\nFix MOI.Test.soc3test for solvers not supporting infeasibility certificates (#839).\nImplements operate for operators * and / between vector function and constant (#837).\nImplements show for MOI.Utilities.IndexMap (#847).\nFix corner cases for mapping of variables in MOI.Utilities.CachingOptimizer and substitution of variables in MOI.Bridges.AbstractBridgeOptimizer (#848).\nFix transformation of constant terms for MOI.Bridges.Constraint.SOCtoPSDBridge and MOI.Bridges.Constraint.RSOCtoPSDBridge (#840).","category":"page"},{"location":"changelog/#v0.9.0-(August-13,-2019)","page":"Release notes","title":"v0.9.0 (August 13, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Support for Julia v0.6 and v0.7 was dropped (#714, #717).\nA MOI.Utilities.Model implementation of ModelLike, this should replace most use cases of MOI.Utilities.@model (#781).\nadd_constrained_variable and add_constrained_variables were added (#759).\nSupport for indicator constraints was added (#709, #712).\nDualObjectiveValue attribute was added (#473).\nRawParameter attribute was added (#733).\nA dual_set function was added (#804).\nA Benchmarks submodule was added to facilitate solver benchmarking (#769).\nA submit function was added, this may for instance allow the user to submit solutions or cuts to the solver from a callback (#775).\nThe field of ObjectiveValue was renamed to result_index (#729).\nThe _constant and Utilities.getconstant function were renamed to constant\nREDUCTION_CERTIFICATE result status was added (#734).\nAbstract matrix sets were added (#731).\nTesting improvements:\nThe testing guideline was updated (#728).\nQuadratic tests were added (#697).\nUnit tests for RawStatusString, SolveTime, Silent and SolverName were added (#726, #741).\nA rotated second-order cone test was added (#759).\nA power cone test was added (#768).\nTests for ZeroOne variables with variable bounds were added (#772).\nAn unbounded test was added (#773).\nExisting tests had a few updates (#702, #703, #763).\nDocumentation improvements:\nAdded a section on CachingOptimizer (#777).\nAdded a section on UniversalFallback, Model and @model (#762).\nTransition the knapsack example to a doctest with MockOptimizer (#786).\nUtilities improvements:\nA CleverDict utility was added for a vector that automatically transform into a dictionary once a first index is removed (#767).\nThe Utilities.constant function was renamed to Utilities.constant_vector (#740).\nImplement optimizer attributes for CachingOptimizer (#745).\nRename Utilities.add_scalar_constraint to Utilities.normalize_and_add_constraint (#801).\noperate with vcat, SingleVariable and VectorOfVariables now returns a VectorOfVariables (#616).\nFix a type piracy of operate (#784).\nThe load_constraint fallback signature was fixed (#760).\nThe set_dot function was extended to work with sparse arrays (#805).\nBridges improvements:\nThe bridges no longer store the constraint function and set before it is bridged, the bridges now have to implement ConstraintFunction and ConstraintSet if the user wants to recover them. As a consequence, the @bridge macro was removed (#722).\nBridge are now instantiated with a bridge_constraint function instead of using a constructor (#730).\nFix constraint attributes for bridges (#699).\nConstraint bridges were moved to the Bridges/Constraint submodule so they should now inherit from MOI.Bridges.Constraint.Abstract and should implement MOI.Bridges.Constraint.concrete_bridge_type instead of MOI.Bridges.concrete_bridge_type (#756).\nVariable bridges were added in (#759).\nVarious improvements (#746, #747).","category":"page"},{"location":"changelog/#v0.8.4-(March-13,-2019)","page":"Release notes","title":"v0.8.4 (March 13, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Performance improvement in default_copy_to and bridge optimizer (#696).\nAdd Silent and implement setting optimizer attributes in caching and mock optimizers (#695).\nAdd Functionize bridges (SingleVariable and VectorOfVariables) (#659).\nMinor typo fixes (#694).","category":"page"},{"location":"changelog/#v0.8.3-(March-6,-2019)","page":"Release notes","title":"v0.8.3 (March 6, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Use zero constant in scalar constraint function of MOI.Test.copytest (#691).\nFix variable deletion with SingleVariable objective function (#690).\nFix LazyBridgeOptimizer with bridges that add no constraints (#689).\nError message improvements (#673, #685, #686, #688).\nDocumentation improvements (#682, #683, #687).\nBasis status:\nRemove VariableBasisStatus (#679).\nTest ConstraintBasisStatus and implement it in bridges (#678).\nFix inference of NumberOfVariables and NumberOfConstraints (#677).\nImplement division between a quadratic function and a number (#675).","category":"page"},{"location":"changelog/#v0.8.2-(February-7,-2019)","page":"Release notes","title":"v0.8.2 (February 7, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add RawStatusString attribute (#629).\nDo not set names to the optimizer but only to the cache in CachingOptimizer (#638).\nMake scalar MOI functions act as scalars in broadcast (#646).\nAdd function utilities:\nImplement Base.zero (#634), Base.iszero (#643), add missing arithmetic operations (#644, #645) and fix division (#648).\nAdd a vectorize function that turns a vector of ScalarAffineFunction into a VectorAffineFunction (#642).\nImprove support for starting values:\nShow a warning in copy when starting values are not supported instead of throwing an error (#630).\nFix UniversalFallback for getting an variable or constraint attribute set to no indices (#623).\nAdd a test in contlineartest with partially set VariablePrimalStart.\nBridges improvements:\nFix StackOverFlow in LazyBridgeOptimizer when there is a cycle in the graph of bridges.\nAdd Slack bridges (#610, #650).\nAdd FlipSign bridges (#658).\nAdd tests with duplicate coefficients in ScalarAffineFunction and VectorAffineFunction (#639).\nUse tolerance to compare VariablePrimal in rotatedsoc1 test (#632).\nUse a zero constant in ScalarAffineFunction of constraints in psdt2 (#622).","category":"page"},{"location":"changelog/#v0.8.1-(January-7,-2019)","page":"Release notes","title":"v0.8.1 (January 7, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Adding an NLP objective now overrides any objective set using the ObjectiveFunction attribute (#619).\nRename fullbridgeoptimizer into full_bridge_optimizer (#621).\nAllow custom constraint types with full_bridge_optimizer (#617).\nAdd Vectorize bridge which transforms scalar linear constraints into vector linear constraints (#615).","category":"page"},{"location":"changelog/#v0.8.0-(December-18,-2018)","page":"Release notes","title":"v0.8.0 (December 18, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Rename all enum values to follow the JuMP naming guidelines for constants, for example, Optimal becomes OPTIMAL, and DualInfeasible becomes DUAL_INFEASIBLE.\nRename CachingOptimizer methods for style compliance.\nAdd an MOI.TerminationStatusCode called ALMOST_DUAL_INFEASIBLE.","category":"page"},{"location":"changelog/#v0.7.0-(December-13,-2018)","page":"Release notes","title":"v0.7.0 (December 13, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Test that MOI.TerminationStatus is MOI.OptimizeNotCalled before MOI.optimize! is called.\nCheck supports_default_copy_to in tests (#594).\nKey pieces of information like optimality, infeasibility, etc., are now reported through TerminationStatusCode. It is typically no longer necessary to check the result statuses in addition to the termination status.\nAdd perspective dimension to log-det cone (#593).","category":"page"},{"location":"changelog/#v0.6.4-(November-27,-2018)","page":"Release notes","title":"v0.6.4 (November 27, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add OptimizeNotCalled termination status (#577) and improve documentation of other statuses (#575).\nAdd a solver naming guideline (#578).\nMake FeasibilitySense the default ObjectiveSense (#579).\nFix Utilities.@model and Bridges.@bridge macros for functions and sets defined outside MOI (#582).\nDocument solver-specific attributes (#580) and implement them in Utilities.CachingOptimizer (#565).","category":"page"},{"location":"changelog/#v0.6.3-(November-16,-2018)","page":"Release notes","title":"v0.6.3 (November 16, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Variables and constraints are now allowed to have duplicate names. An error is thrown only on lookup. This change breaks some existing tests. (#549)\nAttributes may now be partially set (some values could be nothing). (#563)\nPerformance improvements in Utilities.Model (#549, #567, #568)\nFix bug in QuadtoSOC (#558).\nNew supports_default_copy_to method that optimizers should implement to control caching behavior.\nDocumentation improvements.","category":"page"},{"location":"changelog/#v0.6.2-(October-26,-2018)","page":"Release notes","title":"v0.6.2 (October 26, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improve hygiene of @model macro (#544).\nFix bug in copy tests (#543).\nFix bug in UniversalFallback attribute getter (#540).\nAllow all correct solutions for solve_blank_obj unit test (#537).\nAdd errors for Allocate-Load and bad constraints (#534).\n[performance] Add specialized implementation of hash for VariableIndex (#533).\n[performance] Construct the name to object dictionaries lazily in model (#535).\nAdd the QuadtoSOC bridge which transforms ScalarQuadraticFunction constraints into RotatedSecondOrderCone (#483).","category":"page"},{"location":"changelog/#v0.6.1-(September-22,-2018)","page":"Release notes","title":"v0.6.1 (September 22, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Enable PositiveSemidefiniteConeSquare set and quadratic functions in MOIB.fullbridgeoptimizer (#524).\nAdd warning in the bridge between PositiveSemidefiniteConeSquare and PositiveSemidefiniteConeTriangle when the matrix is almost symmetric (#522).\nModify MOIT.copytest to not add multiples constraints on the same variable (#521).\nAdd missing keyword argument in one of MOIU.add_scalar_constraint methods (#520).","category":"page"},{"location":"changelog/#v0.6.0-(August-30,-2018)","page":"Release notes","title":"v0.6.0 (August 30, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"The MOIU.@model and MOIB.@bridge macros now support functions and sets defined in external modules. As a consequence, function and set names in the macro arguments need to be prefixed by module name.\nRename functions according to the JuMP style guide:\ncopy! with keyword arguments copynames and warnattributes -> copy_to with keyword arguments copy_names and warn_attributes;\nset! -> set;\naddvariable[s]! -> add_variable[s];\nsupportsconstraint -> supports_constraint;\naddconstraint[s]! -> add_constraint[s];\nisvalid -> is_valid;\nisempty -> is_empty;\nBase.delete! -> delete;\nmodify! -> modify;\ntransform! -> transform;\ninitialize! -> initialize;\nwrite -> write_to_file; and\nread! -> read_from_file.\nRemove free! (use Base.finalize instead).\nAdd the SquarePSD bridge which transforms PositiveSemidefiniteConeTriangle constraints into PositiveSemidefiniteConeTriangle.\nAdd result fallback for ConstraintDual of variable-wise constraint, ConstraintPrimal and ObjectiveValue.\nAdd tests for ObjectiveBound.\nAdd test for empty rows in vector linear constraint.\nRework errors: CannotError has been renamed NotAllowedError and the distinction between UnsupportedError and NotAllowedError is now about whether the element is not supported (for example, it cannot be copied a model containing this element) or the operation is not allowed (either because it is not implemented, because it cannot be performed in the current state of the model, or because it cannot be performed for a specific index)\ncanget is removed. NoSolution is added as a result status to indicate that the solver does not have either a primal or dual solution available (See #479).","category":"page"},{"location":"changelog/#v0.5.0-(August-5,-2018)","page":"Release notes","title":"v0.5.0 (August 5, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix names with CachingOptimizer.\nCleanup thanks to @mohamed82008.\nAdded a universal fallback for constraints.\nFast utilities for function canonicalization thanks to @rdeits.\nRenamed dimension field to side_dimension in the context of matrix-like sets.\nNew and improved tests for cases like duplicate terms and ObjectiveBound.\nRemoved cantransform, canaddconstraint, canaddvariable, canset, canmodify, and candelete functions from the API. They are replaced by a new set of errors that are thrown: Subtypes of UnsupportedError indicate unsupported operations, while subtypes of CannotError indicate operations that cannot be performed in the current state.\nThe API for copy! is updated to remove the CopyResult type.\nUpdates for the new JuMP style guide.","category":"page"},{"location":"changelog/#v0.4.1-(June-28,-2018)","page":"Release notes","title":"v0.4.1 (June 28, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixes vector function modification on 32 bits.\nFixes Bellman-Ford algorithm for bridges.\nAdded an NLP test with FeasibilitySense.\nUpdate modification documentation.","category":"page"},{"location":"changelog/#v0.4.0-(June-23,-2018)","page":"Release notes","title":"v0.4.0 (June 23, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Helper constructors for VectorAffineTerm and VectorQuadraticTerm.\nAdded modify_lhs to TestConfig.\nAdditional unit tests for optimizers.\nAdded a type parameter to CachingOptimizer for the optimizer field.\nNew API for problem modification (#388)\nTests pass without deprecation warnings on Julia 0.7.\nSmall fixes and documentation updates.","category":"page"},{"location":"changelog/#v0.3.0-(May-25,-2018)","page":"Release notes","title":"v0.3.0 (May 25, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Functions have been redefined to use arrays-of-structs instead of structs-of-arrays.\nImprovements to MockOptimizer.\nSignificant changes to Bridges.\nNew and improved unit tests.\nFixes for Julia 0.7.","category":"page"},{"location":"changelog/#v0.2.0-(April-24,-2018)","page":"Release notes","title":"v0.2.0 (April 24, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improvements to and better coverage of Tests.\nDocumentation fixes.\nSolverName attribute.\nChanges to the NLP interface (new definition of variable order and arrays of structs for bound pairs and sparsity patterns).\nAddition of NLP tests.\nIntroduction of UniversalFallback.\ncopynames keyword argument to MOI.copy!.\nAdd Bridges submodule.","category":"page"},{"location":"changelog/#v0.1.0-(February-28,-2018)","page":"Release notes","title":"v0.1.0 (February 28, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Initial public release.\nThe framework for MOI was developed at the JuMP-dev workshop at MIT in June 2017 as a sorely needed replacement for MathProgBase.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"background/duality/#Duality","page":"Duality","title":"Duality","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Conic duality is the starting point for MOI's duality conventions. When all functions are affine (or coordinate projections), and all constraint sets are closed convex cones, the model may be called a conic optimization problem.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For a minimization problem in geometric conic form, the primal is:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min_x in mathbbR^n a_0^T x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"and the dual is a maximization problem in standard conic form:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max_y_1 ldots y_m -sum_i=1^m b_i^T y_i + b_0\n\n textst a_0 - sum_i=1^m A_i^T y_i = 0\n\n y_i in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"where each mathcalC_i is a closed convex cone and mathcalC_i^* is its dual cone.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For a maximization problem in geometric conic form, the primal is:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max_x in mathbbR^n a_0^T x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"and the dual is a minimization problem in standard conic form:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min_y_1 ldots y_m sum_i=1^m b_i^T y_i + b_0\n\n textst a_0 + sum_i=1^m A_i^T y_i = 0\n\n y_i in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"A linear inequality constraint a^T x + b ge c is equivalent to a^T x + b - c in mathbbR_+, and a^T x + b le c is equivalent to a^T x + b - c in mathbbR_-. Variable-wise constraints are affine constraints with the appropriate identity mapping in place of A_i.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For the special case of minimization LPs, the MOI primal form can be stated as:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min_x in mathbbR^n a_0^T x + b_0\n\n textst\nA_1 x ge b_1\n A_2 x le b_2\n A_3 x = b_3\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"By applying the stated transformations to conic form, taking the dual, and transforming back into linear inequality form, one obtains the following dual:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max_y_1y_2y_3 b_1^Ty_1 + b_2^Ty_2 + b_3^Ty_3 + b_0\n\n textst\nA_1^Ty_1 + A_2^Ty_2 + A_3^Ty_3 = a_0\n y_1 ge 0\n y_2 le 0\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For maximization LPs, the MOI primal form can be stated as:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max_x in mathbbR^n a_0^T x + b_0\n\n textst\nA_1 x ge b_1\n A_2 x le b_2\n A_3 x = b_3\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"and similarly, the dual is:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min_y_1y_2y_3 -b_1^Ty_1 - b_2^Ty_2 - b_3^Ty_3 + b_0\n\n textst\nA_1^Ty_1 + A_2^Ty_2 + A_3^Ty_3 = -a_0\n y_1 ge 0\n y_2 le 0\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"warning: Warning\nFor the LP case, the signs of the feasible dual variables depend only on the sense of the corresponding primal inequality and not on the objective sense.","category":"page"},{"location":"background/duality/#Duality-and-scalar-product","page":"Duality","title":"Duality and scalar product","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"The scalar product is different from the canonical one for the sets PositiveSemidefiniteConeTriangle, LogDetConeTriangle, RootDetConeTriangle.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If the set C_i of the section Duality is one of these three cones, then the rows of the matrix A_i corresponding to off-diagonal entries are twice the value of the coefficients field in the VectorAffineFunction for the corresponding rows. See PositiveSemidefiniteConeTriangle for details.","category":"page"},{"location":"background/duality/#Dual-for-problems-with-quadratic-functions","page":"Duality","title":"Dual for problems with quadratic functions","text":"","category":"section"},{"location":"background/duality/#Quadratic-Programs-(QPs)","page":"Duality","title":"Quadratic Programs (QPs)","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For quadratic programs with only affine conic constraints,","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign*\n min_x in mathbbR^n frac12x^TQ_0x + a_0^T x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign*","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with cones mathcalC_i subseteq mathbbR^m_i for i = 1 ldots m, consider the Lagrangian function","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"L(x y) = frac12x^TQ_0x + a_0^T x + b_0 - sum_i = 1^m y_i^T (A_i x + b_i)","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Let z(y) denote sum_i = 1^m A_i^T y_i - a_0, the Lagrangian can be rewritten as","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"L(x y) = frac12x^TQ_0x - z(y)^T x + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"The condition nabla_x L(x y) = 0 gives","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"0 = nabla_x L(x y) = Q_0x + a_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"which gives Q_0x = z(y). This allows to obtain that","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"min_x in mathbbR^n L(x y) = -frac12x^TQ_0x + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"so the dual problem is","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"max_y_i in mathcalC_i^* min_x in mathbbR^n -frac12x^TQ_0x + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If Q_0 is invertible, we have x = Q_0^-1z(y) hence","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"min_x in mathbbR^n L(x y) = -frac12z(y)^TQ_0^-1z(y) + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"so the dual problem is","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"max_y_i in mathcalC_i^* -frac12z(y)^TQ_0^-1z(y) + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/#Quadratically-Constrained-Quadratic-Programs-(QCQPs)","page":"Duality","title":"Quadratically Constrained Quadratic Programs (QCQPs)","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Given a problem with both quadratic function and quadratic objectives:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign*\n min_x in mathbbR^n frac12x^TQ_0x + a_0^T x + b_0\n\n textst frac12x^TQ_ix + a_i^T x + b_i in mathcalC_i i = 1 ldots m\nendalign*","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with cones mathcalC_i subseteq mathbbR for i = 1 ldots m, consider the Lagrangian function","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"L(x y) = frac12x^TQ_0x + a_0^T x + b_0 - sum_i = 1^m y_i (frac12x^TQ_ix + a_i^T x + b_i)","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"A pair of primal-dual variables (x^star y^star) is optimal if","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"x^star is a minimizer of\nmin_x in mathbbR^n L(x y^star)\nThat is,\n0 = nabla_x L(x y^star) = Q_0x + a_0 - sum_i = 1^m y_i^star (Q_ix + a_i)\nand y^star is a maximizer of\nmax_y_i in mathcalC_i^* L(x^star y)\nThat is, for all i = 1 ldots m, frac12x^TQ_ix + a_i^T x + b_i is either zero or in the normal cone of mathcalC_i^* at y^star. For instance, if mathcalC_i is z in mathbbR z le 0 , this means that if frac12x^TQ_ix + a_i^T x + b_i is nonzero at x^star then y_i^star = 0. This is the classical complementary slackness condition.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If mathcalC_i is a vector set, the discussion remains valid with y_i(frac12x^TQ_ix + a_i^T x + b_i) replaced with the scalar product between y_i and the vector of scalar-valued quadratic functions.","category":"page"},{"location":"background/duality/#Dual-for-square-semidefinite-matrices","page":"Duality","title":"Dual for square semidefinite matrices","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"The set PositiveSemidefiniteConeTriangle is a self-dual. That is, querying ConstraintDual of a PositiveSemidefiniteConeTriangle constraint returns a vector that is itself a member of PositiveSemidefiniteConeTriangle.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"However, the dual of PositiveSemidefiniteConeSquare is not so straight forward. This section explains the duality convention we use, and how it is derived.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"info: Info\nIf you have a PositiveSemidefiniteConeSquare constraint, the result matrix A from ConstraintDual is not positive semidefinite. However, A + A^top is positive semidefinite.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Let mathcalS_+ be the cone of symmetric semidefinite matrices in the fracn(n+1)2 dimensional space of symmetric mathbbR^n times n matrices. That is, mathcalS_+ is the set PositiveSemidefiniteConeTriangle. It is well known that mathcalS_+ is a self-dual proper cone.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Let mathcalP_+ be the cone of symmetric semidefinite matrices in the n^2 dimensional space of mathbbR^n times n matrices. That is mathcalP_+ is the set PositiveSemidefiniteConeSquare.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"In addition, let mathcalD_+ be the cone of matrices A such that A+A^top in mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"mathcalP_+ is not proper because it is not solid (it is not n^2 dimensional), so it is not necessarily true that mathcalP_+^** = mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"However, this is the case, because we will show that mathcalP_+^* = mathcalD_+ and mathcalD_+^* = mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"First, let us see why mathcalP_+^* = mathcalD_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If B is symmetric, then","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"langle AB rangle = langle A^top B^top rangle = langle A^top Brangle","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"so","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"2langle A B rangle = langle A B rangle + langle A^top B rangle = langle A + A^top B rangle","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Therefore, langle ABrangle ge 0 for all B in mathcalP_+ if and only if langle A+A^topBrangle ge 0 for all B in mathcalP_+. Since A+A^top is symmetric, and we know that mathcalS_+ is self-dual, we have shown that mathcalP_+^* is the set of matrices A such that A+A^top in mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Second, let us see why mathcalD_+^* = mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Since A in mathcalD_+ implies that A^top in mathcalD_+, B in mathcalD_+^* means that langle A+A^topBrangle ge 0 for all A in mathcalD_+, and hence B in mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"To see why it should be symmetric, simply notice that if B_ij B_ji, then langle ABrangle can be made arbitrarily small by setting A_ij = A_ij + s and A_ji = A_ji - s, with s arbitrarily large, and A stays in mathcalD_+ because A+A^top does not change.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Typically, the primal/dual pair for semidefinite programs is presented as:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min langle C X rangle \ntextst langle A_k Xrangle = b_k forall k \n X in mathcalS_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with the dual","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max sum_k b_k y_k \ntextst C - sum A_k y_k in mathcalS_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If we allow A_k to be non-symmetric, we should instead use:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min langle C X rangle \ntextst langle A_k Xrangle = b_k forall k \n X in mathcalD_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with the dual","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max sum b_k y_k \ntextst C - sum A_k y_k in mathcalP_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"This is implemented as:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min langle C Z rangle + langle C - C^top S rangle \ntextst langle A_k Z rangle + langle A_k - A_k^top S rangle = b_k forall k \n Z in mathcalS_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with the dual","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max sum b_k y_k \ntextst C+C^top - sum (A_k+A_k^top) y_k in mathcalS_+ \n C-C^top - sum(A_k-A_k^top) y_k = 0\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"and we recover Z = X + X^top.","category":"page"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/callbacks/#Callbacks","page":"Callbacks","title":"Callbacks","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"AbstractCallback\nAbstractSubmittable\nsubmit","category":"page"},{"location":"reference/callbacks/#MathOptInterface.AbstractCallback","page":"Callbacks","title":"MathOptInterface.AbstractCallback","text":"abstract type AbstractCallback <: AbstractModelAttribute end\n\nAbstract type for a model attribute representing a callback function. The value set to subtypes of AbstractCallback is a function that may be called during optimize!. As optimize! is in progress, the result attributes (i.e, the attributes attr such that is_set_by_optimize(attr)) may not be accessible from the callback, hence trying to get result attributes might throw a OptimizeInProgress error.\n\nAt most one callback of each type can be registered. If an optimizer already has a function for a callback type, and the user registers a new function, then the old one is replaced.\n\nThe value of the attribute should be a function taking only one argument, commonly called callback_data, that can be used for instance in LazyConstraintCallback, HeuristicCallback and UserCutCallback.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.AbstractSubmittable","page":"Callbacks","title":"MathOptInterface.AbstractSubmittable","text":"AbstractSubmittable\n\nAbstract supertype for objects that can be submitted to the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.submit","page":"Callbacks","title":"MathOptInterface.submit","text":"submit(\n optimizer::AbstractOptimizer,\n sub::AbstractSubmittable,\n values...,\n)::Nothing\n\nSubmit values to the submittable sub of the optimizer optimizer.\n\nAn UnsupportedSubmittable error is thrown if model does not support the attribute attr (see supports) and a SubmitNotAllowed error is thrown if it supports the submittable sub but it cannot be submitted.\n\n\n\n\n\n","category":"function"},{"location":"reference/callbacks/#Attributes","page":"Callbacks","title":"Attributes","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"CallbackNodeStatus\nCallbackVariablePrimal\nCallbackNodeStatusCode\nCALLBACK_NODE_STATUS_INTEGER\nCALLBACK_NODE_STATUS_FRACTIONAL\nCALLBACK_NODE_STATUS_UNKNOWN","category":"page"},{"location":"reference/callbacks/#MathOptInterface.CallbackNodeStatus","page":"Callbacks","title":"MathOptInterface.CallbackNodeStatus","text":"CallbackNodeStatus(callback_data)\n\nAn optimizer attribute describing the (in)feasibility of the primal solution available from CallbackVariablePrimal during a callback identified by callback_data.\n\nReturns a CallbackNodeStatusCode Enum.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.CallbackVariablePrimal","page":"Callbacks","title":"MathOptInterface.CallbackVariablePrimal","text":"CallbackVariablePrimal(callback_data)\n\nA variable attribute for the assignment to some primal variable's value during the callback identified by callback_data.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.CallbackNodeStatusCode","page":"Callbacks","title":"MathOptInterface.CallbackNodeStatusCode","text":"CallbackNodeStatusCode\n\nAn Enum of possible return values from calling get with CallbackNodeStatus.\n\nValues\n\nPossible values are:\n\nCALLBACK_NODE_STATUS_INTEGER: the primal solution available from CallbackVariablePrimal is integer feasible.\nCALLBACK_NODE_STATUS_FRACTIONAL: the primal solution available from CallbackVariablePrimal is integer infeasible.\nCALLBACK_NODE_STATUS_UNKNOWN: the primal solution available from CallbackVariablePrimal might be integer feasible or infeasible.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.CALLBACK_NODE_STATUS_INTEGER","page":"Callbacks","title":"MathOptInterface.CALLBACK_NODE_STATUS_INTEGER","text":"CALLBACK_NODE_STATUS_INTEGER::CallbackNodeStatusCode\n\nAn instance of the CallbackNodeStatusCode enum.\n\nCALLBACK_NODE_STATUS_INTEGER: the primal solution available from CallbackVariablePrimal is integer feasible.\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#MathOptInterface.CALLBACK_NODE_STATUS_FRACTIONAL","page":"Callbacks","title":"MathOptInterface.CALLBACK_NODE_STATUS_FRACTIONAL","text":"CALLBACK_NODE_STATUS_FRACTIONAL::CallbackNodeStatusCode\n\nAn instance of the CallbackNodeStatusCode enum.\n\nCALLBACK_NODE_STATUS_FRACTIONAL: the primal solution available from CallbackVariablePrimal is integer infeasible.\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#MathOptInterface.CALLBACK_NODE_STATUS_UNKNOWN","page":"Callbacks","title":"MathOptInterface.CALLBACK_NODE_STATUS_UNKNOWN","text":"CALLBACK_NODE_STATUS_UNKNOWN::CallbackNodeStatusCode\n\nAn instance of the CallbackNodeStatusCode enum.\n\nCALLBACK_NODE_STATUS_UNKNOWN: the primal solution available from CallbackVariablePrimal might be integer feasible or infeasible.\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#Lazy-constraints","page":"Callbacks","title":"Lazy constraints","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"LazyConstraintCallback\nLazyConstraint","category":"page"},{"location":"reference/callbacks/#MathOptInterface.LazyConstraintCallback","page":"Callbacks","title":"MathOptInterface.LazyConstraintCallback","text":"LazyConstraintCallback() <: AbstractCallback\n\nThe callback can be used to reduce the feasible set given the current primal solution by submitting a LazyConstraint. For instance, it may be called at an incumbent of a mixed-integer problem. Note that there is no guarantee that the callback is called at every feasible primal solution.\n\nThe current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.\n\nExamples\n\nx = MOI.add_variables(optimizer, 8)\nMOI.set(optimizer, MOI.LazyConstraintCallback(), callback_data -> begin\n sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)\n if # should add a lazy constraint\n func = # computes function\n set = # computes set\n MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)\n end\nend)\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.LazyConstraint","page":"Callbacks","title":"MathOptInterface.LazyConstraint","text":"LazyConstraint(callback_data)\n\nLazy constraint func-in-set submitted as func, set. The optimal solution returned by VariablePrimal will satisfy all lazy constraints that have been submitted.\n\nThis can be submitted only from the LazyConstraintCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the feasible solution callback.\n\nExamples\n\nSuppose x and y are VariableIndexs of optimizer. To add a LazyConstraint for 2x + 3y <= 1, write\n\nfunc = 2.0x + 3.0y\nset = MOI.LessThan(1.0)\nMOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)\n\ninside a LazyConstraintCallback of data callback_data.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#User-cuts","page":"Callbacks","title":"User cuts","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"UserCutCallback\nUserCut","category":"page"},{"location":"reference/callbacks/#MathOptInterface.UserCutCallback","page":"Callbacks","title":"MathOptInterface.UserCutCallback","text":"UserCutCallback() <: AbstractCallback\n\nThe callback can be used to submit UserCut given the current primal solution. For instance, it may be called at fractional (i.e., non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is not guarantee that the callback is called everytime the solver has an infeasible solution.\n\nThe infeasible solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.\n\nExamples\n\nx = MOI.add_variables(optimizer, 8)\nMOI.set(optimizer, MOI.UserCutCallback(), callback_data -> begin\n sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)\n if # can find a user cut\n func = # computes function\n set = # computes set\n MOI.submit(optimizer, MOI.UserCut(callback_data), func, set)\n end\nend\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.UserCut","page":"Callbacks","title":"MathOptInterface.UserCut","text":"UserCut(callback_data)\n\nConstraint func-to-set suggested to help the solver detect the solution given by CallbackVariablePrimal as infeasible. The cut is submitted as func, set. Typically CallbackVariablePrimal will violate integrality constraints, and a cut would be of the form ScalarAffineFunction-in-LessThan or ScalarAffineFunction-in-GreaterThan. Note that, as opposed to LazyConstraint, the provided constraint cannot modify the feasible set, the constraint should be redundant, e.g., it may be a consequence of affine and integrality constraints.\n\nThis can be submitted only from the UserCutCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the infeasible solution callback.\n\nNote that the solver may silently ignore the provided constraint.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#Heuristic-solutions","page":"Callbacks","title":"Heuristic solutions","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"HeuristicCallback\nHeuristicSolution\nHeuristicSolutionStatus\nHEURISTIC_SOLUTION_ACCEPTED\nHEURISTIC_SOLUTION_REJECTED\nHEURISTIC_SOLUTION_UNKNOWN","category":"page"},{"location":"reference/callbacks/#MathOptInterface.HeuristicCallback","page":"Callbacks","title":"MathOptInterface.HeuristicCallback","text":"HeuristicCallback() <: AbstractCallback\n\nThe callback can be used to submit HeuristicSolution given the current primal solution. For example, it may be called at fractional (i.e., non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is no guarantee that the callback is called every time the solver has an infeasible solution.\n\nThe current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.\n\nExamples\n\nx = MOI.add_variables(optimizer, 8)\nMOI.set(optimizer, MOI.HeuristicCallback(), callback_data -> begin\n sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)\n if # can find a heuristic solution\n values = # computes heuristic solution\n MOI.submit(optimizer, MOI.HeuristicSolution(callback_data), x,\n values)\n end\nend\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.HeuristicSolution","page":"Callbacks","title":"MathOptInterface.HeuristicSolution","text":"HeuristicSolution(callback_data)\n\nHeuristically obtained feasible solution. The solution is submitted as variables, values where values[i] gives the value of variables[i], similarly to set. The submit call returns a HeuristicSolutionStatus indicating whether the provided solution was accepted or rejected.\n\nThis can be submitted only from the HeuristicCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the heuristic callback.\n\nSome solvers require a complete solution, others only partial solutions.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.HeuristicSolutionStatus","page":"Callbacks","title":"MathOptInterface.HeuristicSolutionStatus","text":"HeuristicSolutionStatus\n\nAn Enum of possible return values for submit with HeuristicSolution. This informs whether the heuristic solution was accepted or rejected.\n\nValues\n\nPossible values are:\n\nHEURISTIC_SOLUTION_ACCEPTED: The heuristic solution was accepted\nHEURISTIC_SOLUTION_REJECTED: The heuristic solution was rejected\nHEURISTIC_SOLUTION_UNKNOWN: No information available on the acceptance\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.HEURISTIC_SOLUTION_ACCEPTED","page":"Callbacks","title":"MathOptInterface.HEURISTIC_SOLUTION_ACCEPTED","text":"HEURISTIC_SOLUTION_ACCEPTED::HeuristicSolutionStatus\n\nAn instance of the HeuristicSolutionStatus enum.\n\nHEURISTIC_SOLUTION_ACCEPTED: The heuristic solution was accepted\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#MathOptInterface.HEURISTIC_SOLUTION_REJECTED","page":"Callbacks","title":"MathOptInterface.HEURISTIC_SOLUTION_REJECTED","text":"HEURISTIC_SOLUTION_REJECTED::HeuristicSolutionStatus\n\nAn instance of the HeuristicSolutionStatus enum.\n\nHEURISTIC_SOLUTION_REJECTED: The heuristic solution was rejected\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#MathOptInterface.HEURISTIC_SOLUTION_UNKNOWN","page":"Callbacks","title":"MathOptInterface.HEURISTIC_SOLUTION_UNKNOWN","text":"HEURISTIC_SOLUTION_UNKNOWN::HeuristicSolutionStatus\n\nAn instance of the HeuristicSolutionStatus enum.\n\nHEURISTIC_SOLUTION_UNKNOWN: No information available on the acceptance\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/","page":"Models","title":"Models","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/models/#Models","page":"Models","title":"Models","text":"","category":"section"},{"location":"reference/models/#Attribute-interface","page":"Models","title":"Attribute interface","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"is_set_by_optimize\nis_copyable\nget\nget!\nset\nsupports\nattribute_value_type","category":"page"},{"location":"reference/models/#MathOptInterface.is_set_by_optimize","page":"Models","title":"MathOptInterface.is_set_by_optimize","text":"is_set_by_optimize(::AnyAttribute)\n\nReturn a Bool indicating whether the value of the attribute is modified during an optimize! call, that is, the attribute is used to query the result of the optimization.\n\nImportant note when defining new attributes\n\nThis function returns false by default so it should be implemented for attributes that are modified by optimize!.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.is_copyable","page":"Models","title":"MathOptInterface.is_copyable","text":"is_copyable(::AnyAttribute)\n\nReturn a Bool indicating whether the value of the attribute may be copied during copy_to using set.\n\nImportant note when defining new attributes\n\nBy default is_copyable(attr) returns !is_set_by_optimize(attr). A specific method should be defined for attributes which are copied indirectly during copy_to. For instance, both is_copyable and is_set_by_optimize return false for the following attributes:\n\nListOfOptimizerAttributesSet, ListOfModelAttributesSet, ListOfConstraintAttributesSet and ListOfVariableAttributesSet.\nSolverName and RawSolver: these attributes cannot be set.\nNumberOfVariables and ListOfVariableIndices: these attributes are set indirectly by add_variable and add_variables.\nObjectiveFunctionType: this attribute is set indirectly when setting the ObjectiveFunction attribute.\nNumberOfConstraints, ListOfConstraintIndices, ListOfConstraintTypesPresent, CanonicalConstraintFunction, ConstraintFunction and ConstraintSet: these attributes are set indirectly by add_constraint and add_constraints.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.get","page":"Models","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64\n\nReturn the number of variables created by the bridge b in the model.\n\nSee also MOI.NumberOfConstraints.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this if the bridge adds new variables.\n\n\n\n\n\nMOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)\n\nReturn the list of variables created by the bridge b.\n\nSee also MOI.ListOfVariableIndices.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this if the bridge adds new variables.\n\n\n\n\n\nMOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}\n\nReturn the number of constraints of the type F-in-S created by the bridge b.\n\nSee also MOI.NumberOfConstraints.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.\n\n\n\n\n\nMOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}\n\nReturn a Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-in-S created by the bride b.\n\nSee also MOI.ListOfConstraintIndices.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.\n\n\n\n\n\nfunction MOI.get(\n model::MOI.ModelLike,\n attr::MOI.AbstractConstraintAttribute,\n bridge::AbstractBridge,\n)\n\nReturn the value of the attribute attr of the model model for the constraint bridged by bridge.\n\n\n\n\n\nget(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute)\n\nReturn an attribute attr of the optimizer optimizer.\n\nget(model::ModelLike, attr::AbstractModelAttribute)\n\nReturn an attribute attr of the model model.\n\nget(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex)\n\nIf the attribute attr is set for the variable v in the model model, return its value, return nothing otherwise. If the attribute attr is not supported by model then an error should be thrown instead of returning nothing.\n\nget(model::ModelLike, attr::AbstractVariableAttribute, v::Vector{VariableIndex})\n\nReturn a vector of attributes corresponding to each variable in the collection v in the model model.\n\nget(model::ModelLike, attr::AbstractConstraintAttribute, c::ConstraintIndex)\n\nIf the attribute attr is set for the constraint c in the model model, return its value, return nothing otherwise. If the attribute attr is not supported by model then an error should be thrown instead of returning nothing.\n\nget(\n model::ModelLike,\n attr::AbstractConstraintAttribute,\n c::Vector{ConstraintIndex{F,S}},\n) where {F,S}\n\nReturn a vector of attributes corresponding to each constraint in the collection c in the model model.\n\nget(model::ModelLike, ::Type{VariableIndex}, name::String)\n\nIf a variable with name name exists in the model model, return the corresponding index, otherwise return nothing. Errors if two variables have the same name.\n\nget(\n model::ModelLike,\n ::Type{ConstraintIndex{F,S}},\n name::String,\n) where {F,S}\n\nIf an F-in-S constraint with name name exists in the model model, return the corresponding index, otherwise return nothing. Errors if two constraints have the same name.\n\nget(model::ModelLike, ::Type{ConstraintIndex}, name::String)\n\nIf any constraint with name name exists in the model model, return the corresponding index, otherwise return nothing. This version is available for convenience but may incur a performance penalty because it is not type stable. Errors if two constraints have the same name.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.get!","page":"Models","title":"MathOptInterface.get!","text":"get!(output, model::ModelLike, args...)\n\nAn in-place version of get.\n\nThe signature matches that of get except that the the result is placed in the vector output.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.set","page":"Models","title":"MathOptInterface.set","text":"function MOI.set(\n model::MOI.ModelLike,\n attr::MOI.AbstractConstraintAttribute,\n bridge::AbstractBridge,\n value,\n)\n\nSet the value of the attribute attr of the model model for the constraint bridged by bridge.\n\n\n\n\n\nset(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute, value)\n\nAssign value to the attribute attr of the optimizer optimizer.\n\nset(model::ModelLike, attr::AbstractModelAttribute, value)\n\nAssign value to the attribute attr of the model model.\n\nset(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex, value)\n\nAssign value to the attribute attr of variable v in model model.\n\nset(\n model::ModelLike,\n attr::AbstractVariableAttribute,\n v::Vector{VariableIndex},\n vector_of_values,\n)\n\nAssign a value respectively to the attribute attr of each variable in the collection v in model model.\n\nset(\n model::ModelLike,\n attr::AbstractConstraintAttribute,\n c::ConstraintIndex,\n value,\n)\n\nAssign a value to the attribute attr of constraint c in model model.\n\nset(\n model::ModelLike,\n attr::AbstractConstraintAttribute,\n c::Vector{ConstraintIndex{F,S}},\n vector_of_values,\n) where {F,S}\n\nAssign a value respectively to the attribute attr of each constraint in the collection c in model model.\n\nAn UnsupportedAttribute error is thrown if model does not support the attribute attr (see supports) and a SetAttributeNotAllowed error is thrown if it supports the attribute attr but it cannot be set.\n\nset(\n model::ModelLike,\n ::ConstraintSet,\n c::ConstraintIndex{F,S},\n set::S,\n) where {F,S}\n\nChange the set of constraint c to the new set set which should be of the same type as the original set.\n\nset(\n model::ModelLike,\n ::ConstraintFunction,\n c::ConstraintIndex{F,S},\n func::F,\n) where {F,S}\n\nReplace the function in constraint c with func. F must match the original function type used to define the constraint.\n\nnote: Note\nSetting the constraint function is not allowed if F is VariableIndex; a SettingVariableIndexNotAllowed error is thrown instead. This is because, it would require changing the index c since the index of VariableIndex constraints must be the same as the index of the variable.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.supports","page":"Models","title":"MathOptInterface.supports","text":"MOI.supports(\n model::MOI.ModelLike,\n attr::MOI.AbstractConstraintAttribute,\n BT::Type{<:AbstractBridge},\n)\n\nReturn a Bool indicating whether BT supports setting attr to model.\n\n\n\n\n\nsupports(model::ModelLike, sub::AbstractSubmittable)::Bool\n\nReturn a Bool indicating whether model supports the submittable sub.\n\nsupports(model::ModelLike, attr::AbstractOptimizerAttribute)::Bool\n\nReturn a Bool indicating whether model supports the optimizer attribute attr. That is, it returns false if copy_to(model, src) shows a warning in case attr is in the ListOfOptimizerAttributesSet of src; see copy_to for more details on how unsupported optimizer attributes are handled in copy.\n\nsupports(model::ModelLike, attr::AbstractModelAttribute)::Bool\n\nReturn a Bool indicating whether model supports the model attribute attr. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfModelAttributesSet of src.\n\nsupports(\n model::ModelLike,\n attr::AbstractVariableAttribute,\n ::Type{VariableIndex},\n)::Bool\n\nReturn a Bool indicating whether model supports the variable attribute attr. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfVariableAttributesSet of src.\n\nsupports(\n model::ModelLike,\n attr::AbstractConstraintAttribute,\n ::Type{ConstraintIndex{F,S}},\n)::Bool where {F,S}\n\nReturn a Bool indicating whether model supports the constraint attribute attr applied to an F-in-S constraint. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfConstraintAttributesSet of src.\n\nFor all five methods, if the attribute is only not supported in specific circumstances, it should still return true.\n\nNote that supports is only defined for attributes for which is_copyable returns true as other attributes do not appear in the list of attributes set obtained by ListOf...AttributesSet.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.attribute_value_type","page":"Models","title":"MathOptInterface.attribute_value_type","text":"attribute_value_type(attr::AnyAttribute)\n\nGiven an attribute attr, return the type of value expected by get, or returned by set.\n\nNotes\n\nOnly implement this if it make sense to do so. If un-implemented, the default is Any.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#Model-interface","page":"Models","title":"Model interface","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"ModelLike\nis_empty\nempty!\nwrite_to_file\nread_from_file\nsupports_incremental_interface\ncopy_to\nIndexMap","category":"page"},{"location":"reference/models/#MathOptInterface.ModelLike","page":"Models","title":"MathOptInterface.ModelLike","text":"ModelLike\n\nAbstract supertype for objects that implement the \"Model\" interface for defining an optimization problem.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.is_empty","page":"Models","title":"MathOptInterface.is_empty","text":"is_empty(model::ModelLike)\n\nReturns false if the model has any model attribute set or has any variables or constraints.\n\nNote that an empty model can have optimizer attributes set.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.empty!","page":"Models","title":"MathOptInterface.empty!","text":"empty!(model::ModelLike)\n\nEmpty the model, that is, remove all variables, constraints and model attributes but not optimizer attributes.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.write_to_file","page":"Models","title":"MathOptInterface.write_to_file","text":"write_to_file(model::ModelLike, filename::String)\n\nWrite the current model to the file at filename.\n\nSupported file types depend on the model type.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.read_from_file","page":"Models","title":"MathOptInterface.read_from_file","text":"read_from_file(model::ModelLike, filename::String)\n\nRead the file filename into the model model. If model is non-empty, this may throw an error.\n\nSupported file types depend on the model type.\n\nNote\n\nOnce the contents of the file are loaded into the model, users can query the variables via get(model, ListOfVariableIndices()). However, some filetypes, such as LP files, do not maintain an explicit ordering of the variables. Therefore, the returned list may be in an arbitrary order.\n\nTo avoid depending on the order of the indices, look up each variable index by name using get(model, VariableIndex, \"name\").\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.supports_incremental_interface","page":"Models","title":"MathOptInterface.supports_incremental_interface","text":"supports_incremental_interface(model::ModelLike)\n\nReturn a Bool indicating whether model supports building incrementally via add_variable and add_constraint.\n\nThe main purpose of this function is to determine whether a model can be loaded into model incrementally or whether it should be cached and copied at once instead.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.copy_to","page":"Models","title":"MathOptInterface.copy_to","text":"copy_to(dest::ModelLike, src::ModelLike)::IndexMap\n\nCopy the model from src into dest.\n\nThe target dest is emptied, and all previous indices to variables and constraints in dest are invalidated.\n\nReturns an IndexMap object that translates variable and constraint indices from the src model to the corresponding indices in the dest model.\n\nNotes\n\nIf a constraint that in src is not supported by dest, then an UnsupportedConstraint error is thrown.\nIf an AbstractModelAttribute, AbstractVariableAttribute, or AbstractConstraintAttribute is set in src but not supported by dest, then an UnsupportedAttribute error is thrown.\n\nAbstractOptimizerAttributes are not copied to the dest model.\n\nIndexMap\n\nImplementations of copy_to must return an IndexMap. For technical reasons, this type is defined in the Utilities submodule as MOI.Utilities.IndexMap. However, since it is an integral part of the MOI API, we provide MOI.IndexMap as an alias.\n\nExample\n\n# Given empty `ModelLike` objects `src` and `dest`.\n\nx = add_variable(src)\n\nis_valid(src, x) # true\nis_valid(dest, x) # false (`dest` has no variables)\n\nindex_map = copy_to(dest, src)\nis_valid(dest, x) # false (unless index_map[x] == x)\nis_valid(dest, index_map[x]) # true\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.IndexMap","page":"Models","title":"MathOptInterface.IndexMap","text":"IndexMap()\n\nThe dictionary-like object returned by copy_to.\n\nIndexMap\n\nImplementations of copy_to must return an IndexMap. For technical reasons, the IndexMap type is defined in the Utilities submodule as MOI.Utilities.IndexMap. However, since it is an integral part of the MOI API, we provide this MOI.IndexMap as an alias.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#Model-attributes","page":"Models","title":"Model attributes","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"AbstractModelAttribute\nName\nObjectiveFunction\nObjectiveFunctionType\nObjectiveSense\nOptimizationSense\nMIN_SENSE\nMAX_SENSE\nFEASIBILITY_SENSE\nNumberOfVariables\nListOfVariableIndices\nListOfConstraintTypesPresent\nNumberOfConstraints\nListOfConstraintIndices\nListOfOptimizerAttributesSet\nListOfModelAttributesSet\nListOfVariableAttributesSet\nListOfConstraintAttributesSet\nUserDefinedFunction\nListOfSupportedNonlinearOperators","category":"page"},{"location":"reference/models/#MathOptInterface.AbstractModelAttribute","page":"Models","title":"MathOptInterface.AbstractModelAttribute","text":"AbstractModelAttribute\n\nAbstract supertype for attribute objects that can be used to set or get attributes (properties) of the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.Name","page":"Models","title":"MathOptInterface.Name","text":"Name()\n\nA model attribute for the string identifying the model. It has a default value of \"\" if not set`.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveFunction","page":"Models","title":"MathOptInterface.ObjectiveFunction","text":"ObjectiveFunction{F<:AbstractScalarFunction}()\n\nA model attribute for the objective function which has a type F<:AbstractScalarFunction.\n\nF should be guaranteed to be equivalent but not necessarily identical to the function type provided by the user.\n\nThrows an InexactError if the objective function cannot be converted to F, e.g., the objective function is quadratic and F is ScalarAffineFunction{Float64} or it has non-integer coefficient and F is ScalarAffineFunction{Int}.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveFunctionType","page":"Models","title":"MathOptInterface.ObjectiveFunctionType","text":"ObjectiveFunctionType()\n\nA model attribute for the type F of the objective function set using the ObjectiveFunction{F} attribute.\n\nExamples\n\nIn the following code, attr should be equal to MOI.VariableIndex:\n\nx = MOI.add_variable(model)\nMOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x)\nattr = MOI.get(model, MOI.ObjectiveFunctionType())\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveSense","page":"Models","title":"MathOptInterface.ObjectiveSense","text":"ObjectiveSense()\n\nA model attribute for the objective sense of the objective function, which must be an OptimizationSense: MIN_SENSE, MAX_SENSE, or FEASIBILITY_SENSE. The default is FEASIBILITY_SENSE.\n\nInteraction with ObjectiveFunction\n\nSetting the sense to FEASIBILITY_SENSE unsets the ObjectiveFunction attribute. That is, if you first set ObjectiveFunction and then set ObjectiveSense to be FEASIBILITY_SENSE, no objective function will be passed to the solver.\n\nIn addition, some reformulations of ObjectiveFunction via bridges rely on the value of ObjectiveSense. Therefore, you should set ObjectiveSense before setting ObjectiveFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.OptimizationSense","page":"Models","title":"MathOptInterface.OptimizationSense","text":"OptimizationSense\n\nAn enum for the value of the ObjectiveSense attribute.\n\nValues\n\nPossible values are:\n\nMIN_SENSE: the goal is to minimize the objective function\nMAX_SENSE: the goal is to maximize the objective function\nFEASIBILITY_SENSE: the model does not have an objective function\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.MIN_SENSE","page":"Models","title":"MathOptInterface.MIN_SENSE","text":"MIN_SENSE::OptimizationSense\n\nAn instance of the OptimizationSense enum.\n\nMIN_SENSE: the goal is to minimize the objective function\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.MAX_SENSE","page":"Models","title":"MathOptInterface.MAX_SENSE","text":"MAX_SENSE::OptimizationSense\n\nAn instance of the OptimizationSense enum.\n\nMAX_SENSE: the goal is to maximize the objective function\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.FEASIBILITY_SENSE","page":"Models","title":"MathOptInterface.FEASIBILITY_SENSE","text":"FEASIBILITY_SENSE::OptimizationSense\n\nAn instance of the OptimizationSense enum.\n\nFEASIBILITY_SENSE: the model does not have an objective function\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NumberOfVariables","page":"Models","title":"MathOptInterface.NumberOfVariables","text":"NumberOfVariables()\n\nA model attribute for the number of variables in the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfVariableIndices","page":"Models","title":"MathOptInterface.ListOfVariableIndices","text":"ListOfVariableIndices()\n\nA model attribute for the Vector{VariableIndex} of all variable indices present in the model (i.e., of length equal to the value of NumberOfVariables in the order in which they were added.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfConstraintTypesPresent","page":"Models","title":"MathOptInterface.ListOfConstraintTypesPresent","text":"ListOfConstraintTypesPresent()\n\nA model attribute for the list of tuples of the form (F,S), where F is a function type and S is a set type indicating that the attribute NumberOfConstraints{F,S} has a value greater than zero.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NumberOfConstraints","page":"Models","title":"MathOptInterface.NumberOfConstraints","text":"NumberOfConstraints{F,S}()\n\nA model attribute for the number of constraints of the type F-in-S present in the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfConstraintIndices","page":"Models","title":"MathOptInterface.ListOfConstraintIndices","text":"ListOfConstraintIndices{F,S}()\n\nA model attribute for the Vector{ConstraintIndex{F,S}} of all constraint indices of type F-in-S in the model (i.e., of length equal to the value of NumberOfConstraints{F,S}) in the order in which they were added.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfOptimizerAttributesSet","page":"Models","title":"MathOptInterface.ListOfOptimizerAttributesSet","text":"ListOfOptimizerAttributesSet()\n\nAn optimizer attribute for the Vector{AbstractOptimizerAttribute} of all optimizer attributes that were set.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfModelAttributesSet","page":"Models","title":"MathOptInterface.ListOfModelAttributesSet","text":"ListOfModelAttributesSet()\n\nA model attribute for the Vector{AbstractModelAttribute} of all model attributes attr such that:\n\nis_copyable(attr) returns true, and\nthe attribute was set to the model\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfVariableAttributesSet","page":"Models","title":"MathOptInterface.ListOfVariableAttributesSet","text":"ListOfVariableAttributesSet()\n\nA model attribute for the Vector{AbstractVariableAttribute} of all variable attributes attr such that 1) is_copyable(attr) returns true and 2) the attribute was set to variables.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfConstraintAttributesSet","page":"Models","title":"MathOptInterface.ListOfConstraintAttributesSet","text":"ListOfConstraintAttributesSet{F, S}()\n\nA model attribute for the Vector{AbstractConstraintAttribute} of all constraint attributes attr such that:\n\nis_copyable(attr) returns true and\nthe attribute was set to F-in-S constraints.\n\nNote\n\nThe attributes ConstraintFunction and ConstraintSet should not be included in the list even if then have been set with set.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.UserDefinedFunction","page":"Models","title":"MathOptInterface.UserDefinedFunction","text":"UserDefinedFunction(name::Symbol, arity::Int) <: AbstractModelAttribute\n\nSet this attribute to register a user-defined function by the name of name with arity arguments.\n\nOnce registered, name will appear in ListOfSupportedNonlinearOperators.\n\nYou cannot register multiple UserDefinedFunctions with the same name but different arity.\n\nValue type\n\nThe value to be set is a tuple containing one, two, or three functions to evaluate the function, the first-order derivative, and the second-order derivative respectively. Both derivatives are optional, but if you pass the second-order derivative you must also pass the first-order derivative.\n\nFor univariate functions with arity == 1, the functions in the tuple must have the form:\n\nf(x::T)::T: returns the value of the function at x\n∇f(x::T)::T: returns the first-order derivative of f with respect to x\n∇²f(x::T)::T: returns the second-order derivative of f with respect to x.\n\nFor multivariate functions with arity > 1, the functions in the tuple must have the form:\n\nf(x::T...)::T: returns the value of the function at x\n∇f(g::AbstractVector{T}, x::T...)::Nothing: fills the components of g, with g[i] being the first-order partial derivative of f with respect to x[i]\n∇²f(H::AbstractMatrix{T}, x::T...)::Nothing: fills the non-zero components of H, with H[i, j] being the second-order partial derivative of f with respect to x[i] and then x[j]. H is initialized to the zero matrix, so you do not need to set any zero elements.\n\nExamples\n\njulia> import MathOptInterface as MOI\n\njulia> f(x, y) = x^2 + y^2\nf (generic function with 1 method)\n\njulia> function ∇f(g, x, y)\n g .= 2 * x, 2 * y\n return\n end\n∇f (generic function with 1 method)\n\njulia> function ∇²f(H, x...)\n H[1, 1] = H[2, 2] = 2.0\n return\n end\n∇²f (generic function with 1 method)\n\njulia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())\nMOIU.UniversalFallback{MOIU.Model{Float64}}\nfallback for MOIU.Model{Float64}\n\njulia> MOI.set(model, MOI.UserDefinedFunction(:f, 2), (f,))\n\njulia> MOI.set(model, MOI.UserDefinedFunction(:g, 2), (f, ∇f))\n\njulia> MOI.set(model, MOI.UserDefinedFunction(:h, 2), (f, ∇f, ∇²f))\n\njulia> x = MOI.add_variables(model, 2)\n2-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n\njulia> MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)\n\njulia> obj_f = MOI.ScalarNonlinearFunction(:f, Any[x[1], x[2]])\nf(MOI.VariableIndex(1), MOI.VariableIndex(2))\n\njulia> MOI.set(model, MOI.ObjectiveFunction{typeof(obj_f)}(), obj_f)\n\njulia> print(model)\nMinimize ScalarNonlinearFunction:\n f(v[1], v[2])\n\nSubject to:\n\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfSupportedNonlinearOperators","page":"Models","title":"MathOptInterface.ListOfSupportedNonlinearOperators","text":"ListOfSupportedNonlinearOperators() <: AbstractModelAttribute\n\nWhen queried with get, return a Vector{Symbol} listing the operators supported by the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#Optimizer-interface","page":"Models","title":"Optimizer interface","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"AbstractOptimizer\nOptimizerWithAttributes\noptimize!\noptimize!(::ModelLike, ::ModelLike)\ninstantiate\ndefault_cache","category":"page"},{"location":"reference/models/#MathOptInterface.AbstractOptimizer","page":"Models","title":"MathOptInterface.AbstractOptimizer","text":"AbstractOptimizer <: ModelLike\n\nAbstract supertype for objects representing an instance of an optimization problem tied to a particular solver. This is typically a solver's in-memory representation. In addition to ModelLike, AbstractOptimizer objects let you solve the model and query the solution.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.OptimizerWithAttributes","page":"Models","title":"MathOptInterface.OptimizerWithAttributes","text":"struct OptimizerWithAttributes\n optimizer_constructor\n params::Vector{Pair{AbstractOptimizerAttribute,<:Any}}\nend\n\nObject grouping an optimizer constructor and a list of optimizer attributes. Instances are created with instantiate.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.optimize!","page":"Models","title":"MathOptInterface.optimize!","text":"optimize!(optimizer::AbstractOptimizer)\n\nOptimize the problem contained in optimizer.\n\nBefore calling optimize!, the problem should first be constructed using the incremental interface (see supports_incremental_interface) or copy_to.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.optimize!-Tuple{MathOptInterface.ModelLike, MathOptInterface.ModelLike}","page":"Models","title":"MathOptInterface.optimize!","text":"optimize!(dest::AbstractOptimizer, src::ModelLike)::Tuple{IndexMap,Bool}\n\nA \"one-shot\" call that copies the problem from src into dest and then uses dest to optimize the problem.\n\nReturns a tuple of an IndexMap and a Bool copied.\n\nThe IndexMap object translates variable and constraint indices from the src model to the corresponding indices in the dest optimizer. See copy_to for details.\nIf copied == true, src was copied to dest and then cached, allowing incremental modification if supported by the solver.\nIf copied == false, a cache of the model was not kept in dest. Therefore, only the solution information (attributes for which is_set_by_optimize is true) is available to query.\n\nnote: Note\nThe main purpose of optimize! method with two arguments is for use in Utilities.CachingOptimizer.\n\nRelationship to the single-argument optimize!\n\nThe default fallback of optimize!(dest::AbstractOptimizer, src::ModelLike) is\n\nfunction optimize!(dest::AbstractOptimizer, src::ModelLike)\n index_map = copy_to(dest, src)\n optimize!(dest)\n return index_map, true\nend\n\nTherefore, subtypes of AbstractOptimizer should either implement this two-argument method, or implement both copy_to(::Optimizer, ::ModelLike) and optimize!(::Optimizer).\n\n\n\n\n\n","category":"method"},{"location":"reference/models/#MathOptInterface.instantiate","page":"Models","title":"MathOptInterface.instantiate","text":"instantiate(\n optimizer_constructor,\n with_cache_type::Union{Nothing,Type} = nothing,\n with_bridge_type::Union{Nothing,Type} = nothing,\n)\n\nCreate an instance of an optimizer by either:\n\ncalling optimizer_constructor.optimizer_constructor() and setting the parameters in optimizer_constructor.params if optimizer_constructor is a OptimizerWithAttributes\ncalling optimizer_constructor() if optimizer_constructor is callable.\n\nwithcachetype\n\nIf with_cache_type is not nothing, then the optimizer is wrapped in a Utilities.CachingOptimizer to store a cache of the model. This is most useful if the optimizer you are constructing does not support the incremental interface (see supports_incremental_interface).\n\nwithbridgetype\n\nIf with_bridge_type is not nothing, the optimizer is wrapped in a Bridges.full_bridge_optimizer, enabling all the bridges defined in the MOI.Bridges submodule with coefficient type with_bridge_type.\n\nIn addition, if the optimizer created by optimizer_constructor does not support the incremental interface (see supports_incremental_interface), then, irrespective of with_cache_type, the optimizer is wrapped in a Utilities.CachingOptimizer to store a cache of the bridged model.\n\nIf with_cache_type and with_bridge_type are both not nothing, then they must be the same type.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.default_cache","page":"Models","title":"MathOptInterface.default_cache","text":"default_cache(optimizer::ModelLike, ::Type{T}) where {T}\n\nReturn a new instance of the default model type to be used as cache for optimizer in a Utilities.CachingOptimizer for holding constraints of coefficient type T. By default, this returns Utilities.UniversalFallback(Utilities.Model{T}()). If copying from a instance of a given model type is faster for optimizer then a new method returning an instance of this model type should be defined.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#Optimizer-attributes","page":"Models","title":"Optimizer attributes","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"AbstractOptimizerAttribute\nSolverName\nSolverVersion\nSilent\nTimeLimitSec\nObjectiveLimit\nRawOptimizerAttribute\nNumberOfThreads\nRawSolver\nAbsoluteGapTolerance\nRelativeGapTolerance","category":"page"},{"location":"reference/models/#MathOptInterface.AbstractOptimizerAttribute","page":"Models","title":"MathOptInterface.AbstractOptimizerAttribute","text":"AbstractOptimizerAttribute\n\nAbstract supertype for attribute objects that can be used to set or get attributes (properties) of the optimizer.\n\nNotes\n\nThe difference between AbstractOptimizerAttribute and AbstractModelAttribute lies in the behavior of is_empty, empty! and copy_to. Typically optimizer attributes affect only how the model is solved.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SolverName","page":"Models","title":"MathOptInterface.SolverName","text":"SolverName()\n\nAn optimizer attribute for the string identifying the solver/optimizer.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SolverVersion","page":"Models","title":"MathOptInterface.SolverVersion","text":"SolverVersion()\n\nAn optimizer attribute for the string identifying the version of the solver.\n\nnote: Note\nFor solvers supporting semantic versioning, the SolverVersion should be a string of the form \"vMAJOR.MINOR.PATCH\", so that it can be converted to a Julia VersionNumber (e.g., `VersionNumber(\"v1.2.3\")).We do not require Semantic Versioning because some solvers use alternate versioning systems. For example, CPLEX uses Calendar Versioning, so SolverVersion will return a string like \"202001\".\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.Silent","page":"Models","title":"MathOptInterface.Silent","text":"Silent()\n\nAn optimizer attribute for silencing the output of an optimizer. When set to true, it takes precedence over any other attribute controlling verbosity and requires the solver to produce no output. The default value is false which has no effect. In this case the verbosity is controlled by other attributes.\n\nNote\n\nEvery optimizer should have verbosity on by default. For instance, if a solver has a solver-specific log level attribute, the MOI implementation should set it to 1 by default. If the user sets Silent to true, then the log level should be set to 0, even if the user specifically sets a value of log level. If the value of Silent is false then the log level set to the solver is the value given by the user for this solver-specific parameter or 1 if none is given.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.TimeLimitSec","page":"Models","title":"MathOptInterface.TimeLimitSec","text":"TimeLimitSec()\n\nAn optimizer attribute for setting a time limit (in seconnds) for an optimization. When set to nothing, it deactivates the solver time limit. The default value is nothing.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveLimit","page":"Models","title":"MathOptInterface.ObjectiveLimit","text":"ObjectiveLimit()\n\nAn optimizer attribute for setting a limit on the objective value.\n\nThe provided limit must be a Union{Real,Nothing}.\n\nWhen set to nothing, the limit reverts to the solver's default.\n\nThe default value is nothing.\n\nThe solver may stop when the ObjectiveValue is better (lower for minimization, higher for maximization) than the ObjectiveLimit. If stopped, the TerminationStatus should be OBJECTIVE_LIMIT.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RawOptimizerAttribute","page":"Models","title":"MathOptInterface.RawOptimizerAttribute","text":"RawOptimizerAttribute(name::String)\n\nAn optimizer attribute for the solver-specific parameter identified by name.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NumberOfThreads","page":"Models","title":"MathOptInterface.NumberOfThreads","text":"NumberOfThreads()\n\nAn optimizer attribute for setting the number of threads used for an optimization. When set to nothing uses solver default. Values are positive integers. The default value is nothing.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RawSolver","page":"Models","title":"MathOptInterface.RawSolver","text":"RawSolver()\n\nA model attribute for the object that may be used to access a solver-specific API for this optimizer.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.AbsoluteGapTolerance","page":"Models","title":"MathOptInterface.AbsoluteGapTolerance","text":"AbsoluteGapTolerance()\n\nAn optimizer attribute for setting the absolute gap tolerance for an optimization. This is an optimizer attribute, and should be set before calling optimize!. When set to nothing (if supported), uses solver default.\n\nTo set a relative gap tolerance, see RelativeGapTolerance.\n\nwarning: Warning\nThe mathematical definition of \"absolute gap\", and its treatment during the optimization, are solver-dependent. However, assuming no other limit nor issue is encountered during the optimization, most solvers that implement this attribute will stop once f - b g_abs, where b is the best bound, f is the best feasible objective value, and g_abs is the absolute gap.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RelativeGapTolerance","page":"Models","title":"MathOptInterface.RelativeGapTolerance","text":"RelativeGapTolerance()\n\nAn optimizer attribute for setting the relative gap tolerance for an optimization. This is an optimizer attribute, and should be set before calling optimize!. When set to nothing (if supported), uses solver default.\n\nIf you are looking for the relative gap of the current best solution, see RelativeGap. If no limit nor issue is encountered during the optimization, the value of RelativeGap should be at most as large as RelativeGapTolerance.\n\n# Before optimizing: set relative gap tolerance\n# set 0.1% relative gap tolerance\nMOI.set(model, MOI.RelativeGapTolerance(), 1e-3)\nMOI.optimize!(model)\n\n# After optimizing (assuming all went well)\n# The relative gap tolerance has not changed...\nMOI.get(model, MOI.RelativeGapTolerance()) # returns 1e-3\n# ... and the relative gap of the obtained solution is smaller or equal to the\n# tolerance\nMOI.get(model, MOI.RelativeGap()) # should return something ≤ 1e-3\n\nwarning: Warning\nThe mathematical definition of \"relative gap\", and its allowed range, are solver-dependent. Typically, solvers expect a value between 0.0 and 1.0.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/","page":"Models","title":"Models","text":"List of attributes useful for optimizers","category":"page"},{"location":"reference/models/","page":"Models","title":"Models","text":"TerminationStatus\nTerminationStatusCode\nOPTIMIZE_NOT_CALLED\nOPTIMAL\nINFEASIBLE\nDUAL_INFEASIBLE\nLOCALLY_SOLVED\nLOCALLY_INFEASIBLE\nINFEASIBLE_OR_UNBOUNDED\nALMOST_OPTIMAL\nALMOST_INFEASIBLE\nALMOST_DUAL_INFEASIBLE\nALMOST_LOCALLY_SOLVED\nITERATION_LIMIT\nTIME_LIMIT\nNODE_LIMIT\nSOLUTION_LIMIT\nMEMORY_LIMIT\nOBJECTIVE_LIMIT\nNORM_LIMIT\nOTHER_LIMIT\nSLOW_PROGRESS\nNUMERICAL_ERROR\nINVALID_MODEL\nINVALID_OPTION\nINTERRUPTED\nOTHER_ERROR\nPrimalStatus\nDualStatus\nRawStatusString\nResultCount\nObjectiveValue\nDualObjectiveValue\nObjectiveBound\nRelativeGap\nSolveTimeSec\nSimplexIterations\nBarrierIterations\nNodeCount","category":"page"},{"location":"reference/models/#MathOptInterface.TerminationStatus","page":"Models","title":"MathOptInterface.TerminationStatus","text":"TerminationStatus()\n\nA model attribute for the TerminationStatusCode explaining why the optimizer stopped.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.TerminationStatusCode","page":"Models","title":"MathOptInterface.TerminationStatusCode","text":"TerminationStatusCode\n\nAn Enum of possible values for the TerminationStatus attribute. This attribute is meant to explain the reason why the optimizer stopped executing in the most recent call to optimize!.\n\nValues\n\nPossible values are:\n\nOPTIMIZE_NOT_CALLED: The algorithm has not started.\nOPTIMAL: The algorithm found a globally optimal solution.\nINFEASIBLE: The algorithm concluded that no feasible solution exists.\nDUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.\nLOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.\nLOCALLY_INFEASIBLE: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.\nINFEASIBLE_OR_UNBOUNDED: The algorithm stopped because it decided that the problem is infeasible or unbounded; this occasionally happens during MIP presolve.\nALMOST_OPTIMAL: The algorithm found a globally optimal solution to relaxed tolerances.\nALMOST_INFEASIBLE: The algorithm concluded that no feasible solution exists within relaxed tolerances.\nALMOST_DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem within relaxed tolerances.\nALMOST_LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, or could not find directions for improvement within relaxed tolerances.\nITERATION_LIMIT: An iterative algorithm stopped after conducting the maximum number of iterations.\nTIME_LIMIT: The algorithm stopped after a user-specified computation time.\nNODE_LIMIT: A branch-and-bound algorithm stopped because it explored a maximum number of nodes in the branch-and-bound tree.\nSOLUTION_LIMIT: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.\nMEMORY_LIMIT: The algorithm stopped because it ran out of memory.\nOBJECTIVE_LIMIT: The algorithm stopped because it found a solution better than a minimum limit set by the user.\nNORM_LIMIT: The algorithm stopped because the norm of an iterate became too large.\nOTHER_LIMIT: The algorithm stopped due to a limit not covered by one of the _LIMIT_ statuses above.\nSLOW_PROGRESS: The algorithm stopped because it was unable to continue making progress towards the solution.\nNUMERICAL_ERROR: The algorithm stopped because it encountered unrecoverable numerical error.\nINVALID_MODEL: The algorithm stopped because the model is invalid.\nINVALID_OPTION: The algorithm stopped because it was provided an invalid option.\nINTERRUPTED: The algorithm stopped because of an interrupt signal.\nOTHER_ERROR: The algorithm stopped because of an error not covered by one of the statuses defined above.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.OPTIMIZE_NOT_CALLED","page":"Models","title":"MathOptInterface.OPTIMIZE_NOT_CALLED","text":"OPTIMIZE_NOT_CALLED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOPTIMIZE_NOT_CALLED: The algorithm has not started.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OPTIMAL","page":"Models","title":"MathOptInterface.OPTIMAL","text":"OPTIMAL::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOPTIMAL: The algorithm found a globally optimal solution.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INFEASIBLE","page":"Models","title":"MathOptInterface.INFEASIBLE","text":"INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINFEASIBLE: The algorithm concluded that no feasible solution exists.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.DUAL_INFEASIBLE","page":"Models","title":"MathOptInterface.DUAL_INFEASIBLE","text":"DUAL_INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nDUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.LOCALLY_SOLVED","page":"Models","title":"MathOptInterface.LOCALLY_SOLVED","text":"LOCALLY_SOLVED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nLOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.LOCALLY_INFEASIBLE","page":"Models","title":"MathOptInterface.LOCALLY_INFEASIBLE","text":"LOCALLY_INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nLOCALLY_INFEASIBLE: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INFEASIBLE_OR_UNBOUNDED","page":"Models","title":"MathOptInterface.INFEASIBLE_OR_UNBOUNDED","text":"INFEASIBLE_OR_UNBOUNDED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINFEASIBLE_OR_UNBOUNDED: The algorithm stopped because it decided that the problem is infeasible or unbounded; this occasionally happens during MIP presolve.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ALMOST_OPTIMAL","page":"Models","title":"MathOptInterface.ALMOST_OPTIMAL","text":"ALMOST_OPTIMAL::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nALMOST_OPTIMAL: The algorithm found a globally optimal solution to relaxed tolerances.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ALMOST_INFEASIBLE","page":"Models","title":"MathOptInterface.ALMOST_INFEASIBLE","text":"ALMOST_INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nALMOST_INFEASIBLE: The algorithm concluded that no feasible solution exists within relaxed tolerances.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ALMOST_DUAL_INFEASIBLE","page":"Models","title":"MathOptInterface.ALMOST_DUAL_INFEASIBLE","text":"ALMOST_DUAL_INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nALMOST_DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem within relaxed tolerances.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ALMOST_LOCALLY_SOLVED","page":"Models","title":"MathOptInterface.ALMOST_LOCALLY_SOLVED","text":"ALMOST_LOCALLY_SOLVED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nALMOST_LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, or could not find directions for improvement within relaxed tolerances.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ITERATION_LIMIT","page":"Models","title":"MathOptInterface.ITERATION_LIMIT","text":"ITERATION_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nITERATION_LIMIT: An iterative algorithm stopped after conducting the maximum number of iterations.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.TIME_LIMIT","page":"Models","title":"MathOptInterface.TIME_LIMIT","text":"TIME_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nTIME_LIMIT: The algorithm stopped after a user-specified computation time.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NODE_LIMIT","page":"Models","title":"MathOptInterface.NODE_LIMIT","text":"NODE_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nNODE_LIMIT: A branch-and-bound algorithm stopped because it explored a maximum number of nodes in the branch-and-bound tree.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.SOLUTION_LIMIT","page":"Models","title":"MathOptInterface.SOLUTION_LIMIT","text":"SOLUTION_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nSOLUTION_LIMIT: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.MEMORY_LIMIT","page":"Models","title":"MathOptInterface.MEMORY_LIMIT","text":"MEMORY_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nMEMORY_LIMIT: The algorithm stopped because it ran out of memory.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OBJECTIVE_LIMIT","page":"Models","title":"MathOptInterface.OBJECTIVE_LIMIT","text":"OBJECTIVE_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOBJECTIVE_LIMIT: The algorithm stopped because it found a solution better than a minimum limit set by the user.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NORM_LIMIT","page":"Models","title":"MathOptInterface.NORM_LIMIT","text":"NORM_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nNORM_LIMIT: The algorithm stopped because the norm of an iterate became too large.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OTHER_LIMIT","page":"Models","title":"MathOptInterface.OTHER_LIMIT","text":"OTHER_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOTHER_LIMIT: The algorithm stopped due to a limit not covered by one of the _LIMIT_ statuses above.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.SLOW_PROGRESS","page":"Models","title":"MathOptInterface.SLOW_PROGRESS","text":"SLOW_PROGRESS::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nSLOW_PROGRESS: The algorithm stopped because it was unable to continue making progress towards the solution.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NUMERICAL_ERROR","page":"Models","title":"MathOptInterface.NUMERICAL_ERROR","text":"NUMERICAL_ERROR::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nNUMERICAL_ERROR: The algorithm stopped because it encountered unrecoverable numerical error.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INVALID_MODEL","page":"Models","title":"MathOptInterface.INVALID_MODEL","text":"INVALID_MODEL::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINVALID_MODEL: The algorithm stopped because the model is invalid.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INVALID_OPTION","page":"Models","title":"MathOptInterface.INVALID_OPTION","text":"INVALID_OPTION::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINVALID_OPTION: The algorithm stopped because it was provided an invalid option.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INTERRUPTED","page":"Models","title":"MathOptInterface.INTERRUPTED","text":"INTERRUPTED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINTERRUPTED: The algorithm stopped because of an interrupt signal.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OTHER_ERROR","page":"Models","title":"MathOptInterface.OTHER_ERROR","text":"OTHER_ERROR::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOTHER_ERROR: The algorithm stopped because of an error not covered by one of the statuses defined above.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.PrimalStatus","page":"Models","title":"MathOptInterface.PrimalStatus","text":"PrimalStatus(result_index::Int = 1)\n\nA model attribute for the ResultStatusCode of the primal result result_index. If result_index is omitted, it defaults to 1.\n\nSee ResultCount for information on how the results are ordered.\n\nIf result_index is larger than the value of ResultCount then NO_SOLUTION is returned.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.DualStatus","page":"Models","title":"MathOptInterface.DualStatus","text":"DualStatus(result_index::Int = 1)\n\nA model attribute for the ResultStatusCode of the dual result result_index. If result_index is omitted, it defaults to 1.\n\nSee ResultCount for information on how the results are ordered.\n\nIf result_index is larger than the value of ResultCount then NO_SOLUTION is returned.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RawStatusString","page":"Models","title":"MathOptInterface.RawStatusString","text":"RawStatusString()\n\nA model attribute for a solver specific string explaining why the optimizer stopped.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ResultCount","page":"Models","title":"MathOptInterface.ResultCount","text":"ResultCount()\n\nA model attribute for the number of results available.\n\nOrder of solutions\n\nA number of attributes contain an index, result_index, which is used to refer to one of the available results. Thus, result_index must be an integer between 1 and the number of available results.\n\nAs a general rule, the first result (result_index=1) is the most important result (e.g., an optimal solution or an infeasibility certificate). Other results will typically be alternate solutions that the solver found during the search for the first result.\n\nIf a (local) optimal solution is available, i.e., TerminationStatus is OPTIMAL or LOCALLY_SOLVED, the first result must correspond to the (locally) optimal solution. Other results may be alternative optimal solutions, or they may be other suboptimal solutions; use ObjectiveValue to distingiush between them.\n\nIf a primal or dual infeasibility certificate is available, i.e., TerminationStatus is INFEASIBLE or DUAL_INFEASIBLE and the corresponding PrimalStatus or DualStatus is INFEASIBILITY_CERTIFICATE, then the first result must be a certificate. Other results may be alternate certificates, or infeasible points.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveValue","page":"Models","title":"MathOptInterface.ObjectiveValue","text":"ObjectiveValue(result_index::Int = 1)\n\nA model attribute for the objective value of the primal solution result_index.\n\nIf the solver does not have a primal value for the objective because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ObjectiveValue attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.DualObjectiveValue","page":"Models","title":"MathOptInterface.DualObjectiveValue","text":"DualObjectiveValue(result_index::Int = 1)\n\nA model attribute for the value of the objective function of the dual problem for the result_indexth dual result.\n\nIf the solver does not have a dual value for the objective because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check DualStatus before accessing the DualObjectiveValue attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveBound","page":"Models","title":"MathOptInterface.ObjectiveBound","text":"ObjectiveBound()\n\nA model attribute for the best known bound on the optimal objective value.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RelativeGap","page":"Models","title":"MathOptInterface.RelativeGap","text":"RelativeGap()\n\nA model attribute for the final relative optimality gap.\n\nwarning: Warning\nThe definition of this gap is solver-dependent. However, most solvers implementing this attribute define the relative gap as some variation of fracb-ff, where b is the best bound and f is the best feasible objective value.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SolveTimeSec","page":"Models","title":"MathOptInterface.SolveTimeSec","text":"SolveTimeSec()\n\nA model attribute for the total elapsed solution time (in seconds) as reported by the optimizer.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SimplexIterations","page":"Models","title":"MathOptInterface.SimplexIterations","text":"SimplexIterations()\n\nA model attribute for the cumulative number of simplex iterations during the optimization process.\n\nFor a mixed-integer program (MIP), the return value is the total simplex iterations for all nodes.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.BarrierIterations","page":"Models","title":"MathOptInterface.BarrierIterations","text":"BarrierIterations()\n\nA model attribute for the cumulative number of barrier iterations while solving a problem.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NodeCount","page":"Models","title":"MathOptInterface.NodeCount","text":"NodeCount()\n\nA model attribute for the total number of branch-and-bound nodes explored while solving a mixed-integer program (MIP).\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#ResultStatusCode","page":"Models","title":"ResultStatusCode","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"ResultStatusCode\nNO_SOLUTION\nFEASIBLE_POINT\nNEARLY_FEASIBLE_POINT\nINFEASIBLE_POINT\nINFEASIBILITY_CERTIFICATE\nNEARLY_INFEASIBILITY_CERTIFICATE\nREDUCTION_CERTIFICATE\nNEARLY_REDUCTION_CERTIFICATE\nUNKNOWN_RESULT_STATUS\nOTHER_RESULT_STATUS","category":"page"},{"location":"reference/models/#MathOptInterface.ResultStatusCode","page":"Models","title":"MathOptInterface.ResultStatusCode","text":"ResultStatusCode\n\nAn Enum of possible values for the PrimalStatus and DualStatus attributes.\n\nThe values indicate how to interpret the result vector.\n\nValues\n\nPossible values are:\n\nNO_SOLUTION: the result vector is empty.\nFEASIBLE_POINT: the result vector is a feasible point.\nNEARLY_FEASIBLE_POINT: the result vector is feasible if some constraint tolerances are relaxed.\nINFEASIBLE_POINT: the result vector is an infeasible point.\nINFEASIBILITY_CERTIFICATE: the result vector is an infeasibility certificate. If the PrimalStatus is INFEASIBILITY_CERTIFICATE, then the primal result vector is a certificate of dual infeasibility. If the DualStatus is INFEASIBILITY_CERTIFICATE, then the dual result vector is a proof of primal infeasibility.\nNEARLY_INFEASIBILITY_CERTIFICATE: the result satisfies a relaxed criterion for a certificate of infeasibility.\nREDUCTION_CERTIFICATE: the result vector is an ill-posed certificate; see this article for details. If the PrimalStatus is REDUCTION_CERTIFICATE, then the primal result vector is a proof that the dual problem is ill-posed. If the DualStatus is REDUCTION_CERTIFICATE, then the dual result vector is a proof that the primal is ill-posed.\nNEARLY_REDUCTION_CERTIFICATE: the result satisfies a relaxed criterion for an ill-posed certificate.\nUNKNOWN_RESULT_STATUS: the result vector contains a solution with an unknown interpretation.\nOTHER_RESULT_STATUS: the result vector contains a solution with an interpretation not covered by one of the statuses defined above\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NO_SOLUTION","page":"Models","title":"MathOptInterface.NO_SOLUTION","text":"NO_SOLUTION::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nNO_SOLUTION: the result vector is empty.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.FEASIBLE_POINT","page":"Models","title":"MathOptInterface.FEASIBLE_POINT","text":"FEASIBLE_POINT::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nFEASIBLE_POINT: the result vector is a feasible point.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NEARLY_FEASIBLE_POINT","page":"Models","title":"MathOptInterface.NEARLY_FEASIBLE_POINT","text":"NEARLY_FEASIBLE_POINT::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nNEARLY_FEASIBLE_POINT: the result vector is feasible if some constraint tolerances are relaxed.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INFEASIBLE_POINT","page":"Models","title":"MathOptInterface.INFEASIBLE_POINT","text":"INFEASIBLE_POINT::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nINFEASIBLE_POINT: the result vector is an infeasible point.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INFEASIBILITY_CERTIFICATE","page":"Models","title":"MathOptInterface.INFEASIBILITY_CERTIFICATE","text":"INFEASIBILITY_CERTIFICATE::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nINFEASIBILITY_CERTIFICATE: the result vector is an infeasibility certificate. If the PrimalStatus is INFEASIBILITY_CERTIFICATE, then the primal result vector is a certificate of dual infeasibility. If the DualStatus is INFEASIBILITY_CERTIFICATE, then the dual result vector is a proof of primal infeasibility.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NEARLY_INFEASIBILITY_CERTIFICATE","page":"Models","title":"MathOptInterface.NEARLY_INFEASIBILITY_CERTIFICATE","text":"NEARLY_INFEASIBILITY_CERTIFICATE::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nNEARLY_INFEASIBILITY_CERTIFICATE: the result satisfies a relaxed criterion for a certificate of infeasibility.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.REDUCTION_CERTIFICATE","page":"Models","title":"MathOptInterface.REDUCTION_CERTIFICATE","text":"REDUCTION_CERTIFICATE::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nREDUCTION_CERTIFICATE: the result vector is an ill-posed certificate; see this article for details. If the PrimalStatus is REDUCTION_CERTIFICATE, then the primal result vector is a proof that the dual problem is ill-posed. If the DualStatus is REDUCTION_CERTIFICATE, then the dual result vector is a proof that the primal is ill-posed.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NEARLY_REDUCTION_CERTIFICATE","page":"Models","title":"MathOptInterface.NEARLY_REDUCTION_CERTIFICATE","text":"NEARLY_REDUCTION_CERTIFICATE::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nNEARLY_REDUCTION_CERTIFICATE: the result satisfies a relaxed criterion for an ill-posed certificate.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.UNKNOWN_RESULT_STATUS","page":"Models","title":"MathOptInterface.UNKNOWN_RESULT_STATUS","text":"UNKNOWN_RESULT_STATUS::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nUNKNOWN_RESULT_STATUS: the result vector contains a solution with an unknown interpretation.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OTHER_RESULT_STATUS","page":"Models","title":"MathOptInterface.OTHER_RESULT_STATUS","text":"OTHER_RESULT_STATUS::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nOTHER_RESULT_STATUS: the result vector contains a solution with an interpretation not covered by one of the statuses defined above\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#Conflict-Status","page":"Models","title":"Conflict Status","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"compute_conflict!\nConflictStatus\nConstraintConflictStatus\nConflictStatusCode\nConflictParticipationStatusCode\nNOT_IN_CONFLICT\nIN_CONFLICT\nMAYBE_IN_CONFLICT","category":"page"},{"location":"reference/models/#MathOptInterface.compute_conflict!","page":"Models","title":"MathOptInterface.compute_conflict!","text":"compute_conflict!(optimizer::AbstractOptimizer)\n\nComputes a minimal subset of constraints such that the model with the other constraint removed is still infeasible.\n\nSome solvers call a set of conflicting constraints an Irreducible Inconsistent Subsystem (IIS).\n\nSee also ConflictStatus and ConstraintConflictStatus.\n\nNote\n\nIf the model is modified after a call to compute_conflict!, the implementor is not obliged to purge the conflict. Any calls to the above attributes may return values for the original conflict without a warning. Similarly, when modifying the model, the conflict can be discarded.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.ConflictStatus","page":"Models","title":"MathOptInterface.ConflictStatus","text":"ConflictStatus()\n\nA model attribute for the ConflictStatusCode explaining why the conflict refiner stopped when computing the conflict.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ConstraintConflictStatus","page":"Models","title":"MathOptInterface.ConstraintConflictStatus","text":"ConstraintConflictStatus()\n\nA constraint attribute indicating whether the constraint participates in the conflict. Its type is ConflictParticipationStatusCode.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ConflictStatusCode","page":"Models","title":"MathOptInterface.ConflictStatusCode","text":"ConflictStatusCode\n\nAn Enum of possible values for the ConflictStatus attribute. This attribute is meant to explain the reason why the conflict finder stopped executing in the most recent call to compute_conflict!.\n\nPossible values are:\n\nCOMPUTE_CONFLICT_NOT_CALLED: the function compute_conflict! has not yet been called\nNO_CONFLICT_EXISTS: there is no conflict because the problem is feasible\nNO_CONFLICT_FOUND: the solver could not find a conflict\nCONFLICT_FOUND: at least one conflict could be found\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ConflictParticipationStatusCode","page":"Models","title":"MathOptInterface.ConflictParticipationStatusCode","text":"ConflictParticipationStatusCode\n\nAn Enum of possible values for the ConstraintConflictStatus attribute. This attribute is meant to indicate whether a given constraint participates or not in the last computed conflict.\n\nValues\n\nPossible values are:\n\nNOT_IN_CONFLICT: the constraint does not participate in the conflict\nIN_CONFLICT: the constraint participates in the conflict\nMAYBE_IN_CONFLICT: the constraint may participate in the conflict, the solver was not able to prove that the constraint can be excluded from the conflict\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NOT_IN_CONFLICT","page":"Models","title":"MathOptInterface.NOT_IN_CONFLICT","text":"NOT_IN_CONFLICT::ConflictParticipationStatusCode\n\nAn instance of the ConflictParticipationStatusCode enum.\n\nNOT_IN_CONFLICT: the constraint does not participate in the conflict\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.IN_CONFLICT","page":"Models","title":"MathOptInterface.IN_CONFLICT","text":"IN_CONFLICT::ConflictParticipationStatusCode\n\nAn instance of the ConflictParticipationStatusCode enum.\n\nIN_CONFLICT: the constraint participates in the conflict\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.MAYBE_IN_CONFLICT","page":"Models","title":"MathOptInterface.MAYBE_IN_CONFLICT","text":"MAYBE_IN_CONFLICT::ConflictParticipationStatusCode\n\nAn instance of the ConflictParticipationStatusCode enum.\n\nMAYBE_IN_CONFLICT: the constraint may participate in the conflict, the solver was not able to prove that the constraint can be excluded from the conflict\n\n\n\n\n\n","category":"constant"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Utilities/overview/#The-Utilities-submodule","page":"Overview","title":"The Utilities submodule","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The Utilities submodule provides a variety of functions and datastructures for managing MOI.ModelLike objects.","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.Model","page":"Overview","title":"Utilities.Model","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Utilities.Model provides an implementation of a ModelLike that efficiently supports all functions and sets defined within MOI. However, given the extensibility of MOI, this might not cover all use cases.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Create a model as follows:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.UniversalFallback","page":"Overview","title":"Utilities.UniversalFallback","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Utilities.UniversalFallback is a layer that sits on top of any ModelLike and provides non-specialized (slower) fallbacks for constraints and attributes that the underlying ModelLike does not support.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"For example, Utilities.Model doesn't support some variable attributes like VariablePrimalStart, so JuMP uses a combination of Universal fallback and Utilities.Model as a generic problem cache:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())\nMOIU.UniversalFallback{MOIU.Model{Float64}}\nfallback for MOIU.Model{Float64}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nAdding a UniversalFallback means that your model will now support all constraints, even if the inner-model does not. This can lead to unexpected behavior.","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.@model","page":"Overview","title":"Utilities.@model","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"For advanced use cases that need efficient support for functions and sets defined outside of MOI (but still known at compile time), we provide the Utilities.@model macro.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The @model macro takes a name (for a new type, which must not exist yet), eight tuples specifying the types of constraints that are supported, and then a Bool indicating the type is a subtype of MOI.AbstractOptimizer (if true) or MOI.ModelLike (if false).","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The eight tuples are in the following order:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Un-typed scalar sets, for example, Integer\nTyped scalar sets, for example, LessThan\nUn-typed vector sets, for example, Nonnegatives\nTyped vector sets, for example, PowerCone\nUn-typed scalar functions, for example, VariableIndex\nTyped scalar functions, for example, ScalarAffineFunction\nUn-typed vector functions, for example, VectorOfVariables\nTyped vector functions, for example, VectorAffineFunction","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The tuples can contain more than one element. Typed-sets must be specified without their type parameter, for example, MOI.LessThan, not MOI.LessThan{Float64}.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Here is an example:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.@model(\n MyNewModel,\n (MOI.Integer,), # Un-typed scalar sets\n (MOI.GreaterThan,), # Typed scalar sets\n (MOI.Nonnegatives,), # Un-typed vector sets\n (MOI.PowerCone,), # Typed vector sets\n (MOI.VariableIndex,), # Un-typed scalar functions\n (MOI.ScalarAffineFunction,), # Typed scalar functions\n (MOI.VectorOfVariables,), # Un-typed vector functions\n (MOI.VectorAffineFunction,), # Typed vector functions\n true, # <:MOI.AbstractOptimizer?\n )\nMathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, MyNewModelFunctionConstraints{T}} where T\n\njulia> model = MyNewModel{Float64}()\nMOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MyNewModelFunctionConstraints{Float64}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nMyNewModel supports every VariableIndex-in-Set constraint, as well as VariableIndex, ScalarAffineFunction, and ScalarQuadraticFunction objective functions. Implement MOI.supports as needed to forbid constraint and objective function combinations.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"As another example, PATHSolver, which only supports VectorAffineFunction-in-Complements defines its optimizer as:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.@model(\n PathOptimizer,\n (), # Scalar sets\n (), # Typed scalar sets\n (MOI.Complements,), # Vector sets\n (), # Typed vector sets\n (), # Scalar functions\n (), # Typed scalar functions\n (), # Vector functions\n (MOI.VectorAffineFunction,), # Typed vector functions\n true, # is_optimizer\n )\nMathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{T}, MathOptInterface.Complements}} where T","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"However, PathOptimizer does not support some VariableIndex-in-Set constraints, so we must explicitly define:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> function MOI.supports_constraint(\n ::PathOptimizer,\n ::Type{MOI.VariableIndex},\n ::Type{Union{<:MOI.Semiinteger,MOI.Semicontinuous,MOI.ZeroOne,MOI.Integer}}\n )\n return false\n end","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Finally, PATH doesn't support an objective function, so we need to add:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.supports(::PathOptimizer, ::MOI.ObjectiveFunction) = false","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nThis macro creates a new type, so it must be called from the top-level of a module, for example, it cannot be called from inside a function.","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.CachingOptimizer","page":"Overview","title":"Utilities.CachingOptimizer","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"A [Utilities.CachingOptimizer] is an MOI layer that abstracts the difference between solvers that support incremental modification (for example, they support adding variables one-by-one), and solvers that require the entire problem in a single API call (for example, they only accept the A, b and c matrices of a linear program).","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"It has two parts:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"A cache, where the model can be built and modified incrementally\nAn optimizer, which is used to solve the problem","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.CachingOptimizer(\n MOI.Utilities.Model{Float64}(),\n PathOptimizer{Float64}(),\n )\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state EMPTY_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"A Utilities.CachingOptimizer may be in one of three possible states:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"NO_OPTIMIZER: The CachingOptimizer does not have any optimizer.\nEMPTY_OPTIMIZER: The CachingOptimizer has an empty optimizer, and it is not synchronized with the cached model. Modifications are forwarded to the cache, but not to the optimizer.\nATTACHED_OPTIMIZER: The CachingOptimizer has an optimizer, and it is synchronized with the cached model. Modifications are forwarded to the optimizer. If the optimizer does not support modifications, and error will be thrown.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use Utilities.attach_optimizer to go from EMPTY_OPTIMIZER to ATTACHED_OPTIMIZER:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.attach_optimizer(model)\n\njulia> model\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state ATTACHED_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"info: Info\nYou must be in ATTACHED_OPTIMIZER to use optimize!.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use Utilities.reset_optimizer to go from ATTACHED_OPTIMIZER to EMPTY_OPTIMIZER:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.reset_optimizer(model)\n\njulia> model\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state EMPTY_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"info: Info\nCalling MOI.empty!(model) also resets the state to EMPTY_OPTIMIZER. So after emptying a model, the modification will only be applied to the cache.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use Utilities.drop_optimizer to go from any state to NO_OPTIMIZER:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.drop_optimizer(model)\n\njulia> model\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state NO_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer nothing","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Pass an empty optimizer to Utilities.reset_optimizer to go from NO_OPTIMIZER to EMPTY_OPTIMIZER:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}())\n\njulia> model\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state EMPTY_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Deciding when to attach and reset the optimizer is tedious, and you will often write code like this:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"try\n # modification\ncatch\n MOI.Utilities.reset_optimizer(model)\n # Re-try modification\nend","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"To make this easier, Utilities.CachingOptimizer has two modes of operation:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"AUTOMATIC: The CachingOptimizer changes its state when necessary. Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to EMPTY_OPTIMIZER mode.\nMANUAL: The user must change the state of the CachingOptimizer. Attempting to perform an operation in the incorrect state results in an error.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"By default, AUTOMATIC mode is chosen. However, you can create a CachingOptimizer in MANUAL mode as follows:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.CachingOptimizer(\n MOI.Utilities.Model{Float64}(),\n MOI.Utilities.MANUAL,\n )\nMOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}}\nin state NO_OPTIMIZER\nin mode MANUAL\nwith model cache MOIU.Model{Float64}\nwith optimizer nothing\n\njulia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}())\n\njulia> model\nMOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}}\nin state EMPTY_OPTIMIZER\nin mode MANUAL\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/#Printing","page":"Overview","title":"Printing","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use print to print the formulation of the model.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.set(model, MOI.VariableName(), x, \"x_var\")\n\njulia> MOI.add_constraint(model, x, MOI.ZeroOne())\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)\n\njulia> MOI.set(model, MOI.ObjectiveFunction{typeof(x)}(), x)\n\njulia> MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)\n\njulia> print(model)\nMaximize VariableIndex:\n x_var\n\nSubject to:\n\nVariableIndex-in-ZeroOne\n x_var ∈ {0, 1}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use Utilities.latex_formulation to display the model in LaTeX form:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.latex_formulation(model)\n$$ \\begin{aligned}\n\\max\\quad & x\\_var \\\\\n\\text{Subject to}\\\\\n & \\text{VariableIndex-in-ZeroOne} \\\\\n & x\\_var \\in \\{0, 1\\} \\\\\n\\end{aligned} $$","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nIn IJulia, calling print or ending a cell with Utilities.latex_formulation will render the model in LaTeX.","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.PenaltyRelaxation","page":"Overview","title":"Utilities.PenaltyRelaxation","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Pass Utilities.PenaltyRelaxation to modify to relax the problem by adding penalized slack variables to the constraints. This is helpful when debugging sources of infeasible models.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> MOI.set(model, MOI.VariableName(), x, \"x\")\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 2.0)));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 2.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 x - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> map[c]\n0.0 + 1.0 MOI.VariableIndex(2)","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"You can also modify a single constraint using Utilities.ScalarPenaltyRelaxation:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> MOI.set(model, MOI.VariableName(), x, \"x\")\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 2.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 x - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> f\n0.0 + 1.0 MOI.VariableIndex(2)","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.MatrixOfConstraints","page":"Overview","title":"Utilities.MatrixOfConstraints","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The constraints of Utilities.Model are stored as a vector of tuples of function and set in a Utilities.VectorOfConstraints. Other representations can be used by parameterizing the type Utilities.GenericModel (resp. Utilities.GenericOptimizer). For instance, if all non-VariableIndex constraints are affine, the coefficients of all the constraints can be stored in a single sparse matrix using Utilities.MatrixOfConstraints. The constraints storage can even be customized up to a point where it exactly matches the storage of the solver of interest, in which case copy_to can be implemented for the solver by calling copy_to to this custom model.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"For instance, Clp defines the following model:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"MOI.Utilities.@product_of_scalar_sets(LP, MOI.EqualTo{T}, MOI.LessThan{T}, MOI.GreaterThan{T})\nconst Model = MOI.Utilities.GenericModel{\n Float64,\n MOI.Utilities.MatrixOfConstraints{\n Float64,\n MOI.Utilities.MutableSparseMatrixCSC{Float64,Cint,MOI.Utilities.ZeroBasedIndexing},\n MOI.Utilities.Hyperrectangle{Float64},\n LP{Float64},\n },\n}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The copy_to operation can now be implemented as follows:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"function _copy_to(dest::Optimizer, src::Model)\n @assert MOI.is_empty(dest)\n A = src.constraints.coefficients\n row_bounds = src.constraints.constants\n Clp_loadProblem(\n dest,\n A.n,\n A.m,\n A.colptr,\n A.rowval,\n A.nzval,\n src.lower_bound,\n src.upper_bound,\n # (...) objective vector (omitted),\n row_bounds.lower,\n row_bounds.upper,\n )\n # Set objective sense and constant (omitted)\n return\nend\n\nfunction MOI.copy_to(dest::Optimizer, src::Model)\n _copy_to(dest, src)\n return MOI.Utilities.identity_index_map(src)\nend\n\nfunction MOI.copy_to(\n dest::Optimizer,\n src::MOI.Utilities.UniversalFallback{Model},\n)\n # Copy attributes from `src` to `dest` and error in case any unsupported\n # constraints or attributes are set in `UniversalFallback`.\n return MOI.copy_to(dest, src.model)\nend\n\nfunction MOI.copy_to(\n dest::Optimizer,\n src::MOI.ModelLike,\n)\n model = Model()\n index_map = MOI.copy_to(model, src)\n _copy_to(dest, model)\n return index_map\nend","category":"page"},{"location":"submodules/Utilities/overview/#ModelFilter","page":"Overview","title":"ModelFilter","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Utilities provides Utilities.ModelFilter as a useful tool to copy a subset of a model. For example, given an infeasible model, we can copy the irreducible infeasible subsystem (for models implementing ConstraintConflictStatus) as follows:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"my_filter(::Any) = true\nfunction my_filter(ci::MOI.ConstraintIndex)\n status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)\n return status != MOI.NOT_IN_CONFLICT\nend\nfiltered_src = MOI.Utilities.ModelFilter(my_filter, src)\nindex_map = MOI.copy_to(dest, filtered_src)","category":"page"},{"location":"submodules/Utilities/overview/#Fallbacks","page":"Overview","title":"Fallbacks","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The value of some attributes can be inferred from the value of other attributes.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"For example, the value of ObjectiveValue can be computed using ObjectiveFunction and VariablePrimal.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"When a solver gives direct access to an attribute, it is better to return this value. However, if this is not the case, Utilities.get_fallback can be used instead. For example:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"function MOI.get(model::Optimizer, attr::MOI.ObjectiveFunction)\n return MOI.Utilities.get_fallback(model, attr)\nend","category":"page"},{"location":"submodules/Utilities/overview/#DoubleDicts","page":"Overview","title":"DoubleDicts","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"When writing MOI interfaces, we often need to handle situations in which we map ConstraintIndexs to different values. For example, to a string for ConstraintName.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"One option is to use a dictionary like Dict{MOI.ConstraintIndex,String}. However, this incurs a performance cost because the key is not a concrete type.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The DoubleDicts submodule helps this situation by providing two types main types Utilities.DoubleDicts.DoubleDict and Utilities.DoubleDicts.IndexDoubleDict. These types act like normal dictionaries, but internally they use more efficient dictionaries specialized to the type of the function-set pair.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The most common usage of a DoubleDict is in the index_map returned by copy_to. Performance can be improved, by using a function barrier. That is, instead of code like:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"index_map = MOI.copy_to(dest, src)\nfor (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())\n for ci in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())\n dest_ci = index_map[ci]\n # ...\n end\nend","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"use instead:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"function function_barrier(\n dest,\n src,\n index_map::MOI.Utilities.DoubleDicts.IndexDoubleDictInner{F,S},\n) where {F,S}\n for ci in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())\n dest_ci = index_map[ci]\n # ...\n end\n return\nend\n\nindex_map = MOI.copy_to(dest, src)\nfor (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())\n function_barrier(dest, src, index_map[F, S])\nend","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Nonlinear/overview/#nonlinear_developers","page":"Overview","title":"Nonlinear","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nThe Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The Nonlinear submodule contains data structures and functions for working with a nonlinear optimization problem in the form of an expression graph. This page explains the API and describes the rationale behind its design.","category":"page"},{"location":"submodules/Nonlinear/overview/#Standard-form","page":"Overview","title":"Standard form","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear programs (NLPs) are a class of optimization problems in which some of the constraints or the objective function are nonlinear:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"beginalign\n min_x in mathbbR^n f_0(x) \n textst l_j le f_j(x) le u_j j = 1 ldots m\nendalign","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"There may be additional constraints, as well as things like variable bounds and integrality restrictions, but we do not consider them here because they are best dealt with by other components of MathOptInterface.","category":"page"},{"location":"submodules/Nonlinear/overview/#API-overview","page":"Overview","title":"API overview","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The core element of the Nonlinear submodule is Nonlinear.Model:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> const Nonlinear = MOI.Nonlinear;\n\njulia> model = Nonlinear.Model()\nA Nonlinear.Model with:\n 0 objectives\n 0 parameters\n 0 expressions\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.Model is a mutable struct that stores all of the nonlinear information added to the model.","category":"page"},{"location":"submodules/Nonlinear/overview/#Decision-variables","page":"Overview","title":"Decision variables","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Decision variables are represented by VariableIndexes. The user is responsible for creating these using MOI.VariableIndex(i), where i is the column associated with the variable.","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_Expressions","page":"Overview","title":"Expressions","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The input data structure is a Julia Expr. The input expressions can incorporate VariableIndexes, but these must be interpolated into the expression with $:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> input = :(1 + sin($x)^2)\n:(1 + sin(MathOptInterface.VariableIndex(1)) ^ 2)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"There are a number of restrictions on the input Expr:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"It cannot contain macros\nIt cannot contain broadcasting\nIt cannot contain splatting (except in limited situations)\nIt cannot contain linear algebra, such as matrix-vector products\nIt cannot contain generator expressions, including sum(i for i in S)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Given an input expression, add an expression using Nonlinear.add_expression:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> expr = Nonlinear.add_expression(model, input)\nMathOptInterface.Nonlinear.ExpressionIndex(1)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The return value, expr, is a Nonlinear.ExpressionIndex that can then be interpolated into other input expressions.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Looking again at model, we see:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> model\nA Nonlinear.Model with:\n 0 objectives\n 0 parameters\n 1 expression\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_Parameters","page":"Overview","title":"Parameters","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"In addition to constant literals like 1 or 1.23, you can create parameters. Parameters are placeholders whose values can change before passing the expression to the solver. Create a parameter using Nonlinear.add_parameter, which accepts a default value:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> p = Nonlinear.add_parameter(model, 1.23)\nMathOptInterface.Nonlinear.ParameterIndex(1)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The return value, p, is a Nonlinear.ParameterIndex that can then be interpolated into other input expressions.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Looking again at model, we see:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> model\nA Nonlinear.Model with:\n 0 objectives\n 1 parameter\n 1 expression\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Update a parameter as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> model[p]\n1.23\n\njulia> model[p] = 4.56\n4.56\n\njulia> model[p]\n4.56","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_Objectives","page":"Overview","title":"Objectives","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Set a nonlinear objective using Nonlinear.set_objective:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> Nonlinear.set_objective(model, :($p + $expr + $x))\n\njulia> model\nA Nonlinear.Model with:\n 1 objective\n 1 parameter\n 1 expression\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Clear a nonlinear objective by passing nothing:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> Nonlinear.set_objective(model, nothing)\n\njulia> model\nA Nonlinear.Model with:\n 0 objectives\n 1 parameter\n 1 expression\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"But we'll re-add the objective for later:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> Nonlinear.set_objective(model, :($p + $expr + $x));","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_Constraints","page":"Overview","title":"Constraints","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Add a constraint using Nonlinear.add_constraint:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> c = Nonlinear.add_constraint(model, :(1 + sqrt($x)), MOI.LessThan(2.0))\nMathOptInterface.Nonlinear.ConstraintIndex(1)\n\njulia> model\nA Nonlinear.Model with:\n 1 objective\n 1 parameter\n 1 expression\n 1 constraint","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The return value, c, is a Nonlinear.ConstraintIndex that is a unique identifier for the constraint. Interval constraints are also supported:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> c2 = Nonlinear.add_constraint(model, :(1 + sqrt($x)), MOI.Interval(-1.0, 2.0))\nMathOptInterface.Nonlinear.ConstraintIndex(2)\n\njulia> model\nA Nonlinear.Model with:\n 1 objective\n 1 parameter\n 1 expression\n 2 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Delete a constraint using Nonlinear.delete:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> Nonlinear.delete(model, c2)\n\njulia> model\nA Nonlinear.Model with:\n 1 objective\n 1 parameter\n 1 expression\n 1 constraint","category":"page"},{"location":"submodules/Nonlinear/overview/#User-defined-operators","page":"Overview","title":"User-defined operators","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"By default, Nonlinear supports a wide range of univariate and multivariate operators. However, you can also define your own operators by registering them.","category":"page"},{"location":"submodules/Nonlinear/overview/#Univariate-operators","page":"Overview","title":"Univariate operators","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Register a univariate user-defined operator using Nonlinear.register_operator:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> f(x) = 1 + sin(x)^2\nf (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_f, 1, f)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Now, you can use :my_f in expressions:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> new_expr = Nonlinear.add_expression(model, :(my_f($x + 1)))\nMathOptInterface.Nonlinear.ExpressionIndex(2)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"By default, Nonlinear will compute first- and second-derivatives of the registered operator using ForwardDiff.jl. Override this by passing functions which compute the respective derivative:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> f′(x) = 2 * sin(x) * cos(x)\nf′ (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_f2, 1, f, f′)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"or","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> f′′(x) = 2 * (cos(x)^2 - sin(x)^2)\nf′′ (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_f3, 1, f, f′, f′′)","category":"page"},{"location":"submodules/Nonlinear/overview/#Multivariate-operators","page":"Overview","title":"Multivariate operators","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Register a multivariate user-defined operator using Nonlinear.register_operator:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> g(x...) = x[1]^2 + x[1] * x[2] + x[2]^2\ng (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_g, 2, g)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Now, you can use :my_g in expressions:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> new_expr = Nonlinear.add_expression(model, :(my_g($x + 1, $x)))\nMathOptInterface.Nonlinear.ExpressionIndex(3)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"By default, Nonlinear will compute the gradient of the registered operator using ForwardDiff.jl. (Hessian information is not supported.) Override this by passing a function to compute the gradient:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> function ∇g(ret, x...)\n ret[1] = 2 * x[1] + x[2]\n ret[2] = x[1] + 2 * x[2]\n return\n end\n∇g (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_g2, 2, g, ∇g)","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_MOI_interface","page":"Overview","title":"MathOptInterface","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"MathOptInterface communicates the nonlinear portion of an optimization problem to solvers using concrete subtypes of AbstractNLPEvaluator, which implement the Nonlinear programming API.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Create an AbstractNLPEvaluator from Nonlinear.Model using Nonlinear.Evaluator.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.Evaluator requires an Nonlinear.AbstractAutomaticDifferentiation backend and an ordered list of the variables that are included in the model.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"There following backends are available to choose from within MOI, although other packages may add more options by sub-typing Nonlinear.AbstractAutomaticDifferentiation:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.ExprGraphOnly\nNonlinear.SparseReverseMode.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> evaluator = Nonlinear.Evaluator(model, Nonlinear.ExprGraphOnly(), [x])\nNonlinear.Evaluator with available features:\n * :ExprGraph","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The functions of the Nonlinear programming API implemented by Nonlinear.Evaluator depends upon the chosen Nonlinear.AbstractAutomaticDifferentiation backend.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The :ExprGraph feature means we can call objective_expr and constraint_expr to retrieve the expression graph of the problem. However, we cannot call gradient terms such as eval_objective_gradient because Nonlinear.ExprGraphOnly does not have the capability to differentiate a nonlinear expression.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"If, instead, we pass Nonlinear.SparseReverseMode, then we get access to :Grad, the gradient of the objective function, :Jac, the Jacobian matrix of the constraints, :JacVec, the ability to compute Jacobian-vector products, and :ExprGraph.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> evaluator = Nonlinear.Evaluator(\n model,\n Nonlinear.SparseReverseMode(),\n [x],\n )\nNonlinear.Evaluator with available features:\n * :Grad\n * :Jac\n * :JacVec\n * :ExprGraph","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"However, before using the evaluator, we need to call initialize:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> MOI.initialize(evaluator, [:Grad, :Jac, :JacVec, :ExprGraph])","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Now we can call methods like eval_objective:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> x = [1.0]\n1-element Vector{Float64}:\n 1.0\n\njulia> MOI.eval_objective(evaluator, x)\n7.268073418273571","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"and eval_objective_gradient:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> grad = [0.0]\n1-element Vector{Float64}:\n 0.0\n\njulia> MOI.eval_objective_gradient(evaluator, grad, x)\n\njulia> grad\n1-element Vector{Float64}:\n 1.909297426825682","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Instead of passing Nonlinear.Evaluator directly to solvers, solvers query the NLPBlock attribute, which returns an NLPBlockData. This object wraps an Nonlinear.Evaluator and includes other information such as constraint bounds and whether the evaluator has a nonlinear objective. Create and set NLPBlockData as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> block = MOI.NLPBlockData(evaluator);\n\njulia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}());\n\njulia> MOI.set(model, MOI.NLPBlock(), block);","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nOnly call NLPBlockData once you have finished modifying the problem in model.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Putting everything together, you can create a nonlinear optimization problem in MathOptInterface as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"import MathOptInterface as MOI\n\nfunction build_model(\n model::MOI.ModelLike;\n backend::MOI.Nonlinear.AbstractAutomaticDifferentiation,\n)\n x = MOI.add_variable(model)\n y = MOI.add_variable(model)\n MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)\n nl_model = MOI.Nonlinear.Model()\n MOI.Nonlinear.set_objective(nl_model, :($x^2 + $y^2))\n evaluator = MOI.Nonlinear.Evaluator(nl_model, backend, [x, y])\n MOI.set(model, MOI.NLPBlock(), MOI.NLPBlockData(evaluator))\n return\nend\n\n# Replace `model` and `backend` with your optimizer and backend of choice.\nmodel = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())\nbuild_model(model; backend = MOI.Nonlinear.SparseReverseMode())","category":"page"},{"location":"submodules/Nonlinear/overview/#Expression-graph-representation","page":"Overview","title":"Expression-graph representation","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.Model stores nonlinear expressions in Nonlinear.Expressions. This section explains the design of the expression graph data structure in Nonlinear.Expression.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Given a nonlinear function like f(x) = sin(x)^2 + x, a conceptual aid for thinking about the graph representation of the expression is to convert it into Polish prefix notation:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"f(x, y) = (+ (^ (sin x) 2) x)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This format identifies each operator (function), as well as a list of arguments. Operators can be univariate, like sin, or multivariate, like +.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"A common way of representing Polish prefix notation in code is as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> x = MOI.VariableIndex(1);\n\njulia> struct ExprNode\n op::Symbol\n children::Vector{Union{ExprNode,Float64,MOI.VariableIndex}}\n end\n\njulia> expr = ExprNode(:+, [ExprNode(:^, [ExprNode(:sin, [x]), 2.0]), x]);","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This data structure follows our Polish prefix notation very closely, and we can easily identify the arguments to an operator. However, it has a significant draw-back: each node in the graph requires a Vector, which is heap-allocated and tracked by Julia's garbage collector (GC). For large models, we can expect to have millions of nodes in the expression graph, so this overhead quickly becomes prohibitive for computation.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"An alternative is to record the expression as a linear tape:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> expr = Any[:+, 2, :^, 2, :sin, 1, x, 2.0, x]\n9-element Vector{Any}:\n :+\n 2\n :^\n 2\n :sin\n 1\n MOI.VariableIndex(1)\n 2.0\n MOI.VariableIndex(1)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The Int after each operator Symbol specifies the number of arguments.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This data-structure is a single vector, which resolves our problem with the GC, but each element is the abstract type, Any, and so any operations on it will lead to slower dynamic dispatch. It's also hard to identify the children of each operation without reading the entire tape.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"To summarize, representing expression graphs in Julia has the following challenges:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nodes in the expression graph should not contain a heap-allocated object\nAll data-structures should be concretely typed\nIt should be easy to identify the children of a node","category":"page"},{"location":"submodules/Nonlinear/overview/#Sketch-of-the-design-in-Nonlinear","page":"Overview","title":"Sketch of the design in Nonlinear","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear overcomes these problems by decomposing the data structure into a number of different concrete-typed vectors.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"First, we create vectors of the supported uni- and multivariate operators.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> const UNIVARIATE_OPERATORS = [:sin];\n\njulia> const MULTIVARIATE_OPERATORS = [:+, :^];","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"In practice, there are many more supported operations than the ones listed here.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Second, we create an enum to represent the different types of nodes present in the expression graph:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> @enum(\n NodeType,\n NODE_CALL_MULTIVARIATE,\n NODE_CALL_UNIVARIATE,\n NODE_VARIABLE,\n NODE_VALUE,\n )","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"In practice, there are node types other than the ones listed here.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Third, we create two concretely typed structs as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> struct Node\n type::NodeType\n parent::Int\n index::Int\n end\n\njulia> struct Expression\n nodes::Vector{Node}\n values::Vector{Float64}\n end","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"For each node node in the .nodes field, if node.type is:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"NODE_CALL_MULTIVARIATE, we look up MULTIVARIATE_OPERATORS[node.index] to retrieve the operator\nNODE_CALL_UNIVARIATE, we look up UNIVARIATE_OPERATORS[node.index] to retrieve the operator\nNODE_VARIABLE, we create MOI.VariableIndex(node.index)\nNODE_VALUE, we look up values[node.index]","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The .parent field of each node is the integer index of the parent node in .nodes. For the first node, the parent is -1 by convention.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Therefore, we can represent our function as:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> expr = Expression(\n [\n Node(NODE_CALL_MULTIVARIATE, -1, 1),\n Node(NODE_CALL_MULTIVARIATE, 1, 2),\n Node(NODE_CALL_UNIVARIATE, 2, 1),\n Node(NODE_VARIABLE, 3, 1),\n Node(NODE_VALUE, 2, 1),\n Node(NODE_VARIABLE, 1, 1),\n ],\n [2.0],\n );","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This is less readable than the other options, but does this data structure meet our design goals?","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Instead of a heap-allocated object for each node, we only have two Vectors for each expression, nodes and values, as well as two constant vectors for the OPERATORS. In addition, all fields are concretely typed, and there are no Union or Any types.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"For our third goal, it is not easy to identify the children of a node, but it is easy to identify the parent of any node. Therefore, we can use Nonlinear.adjacency_matrix to compute a sparse matrix that maps parents to their children.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The tape is also ordered topologically, so that a reverse pass of the nodes evaluates all children nodes before their parent.","category":"page"},{"location":"submodules/Nonlinear/overview/#The-design-in-practice","page":"Overview","title":"The design in practice","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"In practice, Node and Expression are exactly Nonlinear.Node and Nonlinear.Expression. However, Nonlinear.NodeType has more fields to account for comparison operators such as :>= and :<=, logic operators such as :&& and :||, nonlinear parameters, and nested subexpressions.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Moreover, instead of storing the operators as global constants, they are stored in Nonlinear.OperatorRegistry, and it also stores a vector of logic operators and a vector of comparison operators. In addition to Nonlinear.DEFAULT_UNIVARIATE_OPERATORS and Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS, you can register user-defined functions using Nonlinear.register_operator.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.Model is a struct that stores the Nonlinear.OperatorRegistry, as well as a list of parameters and subexpressions in the model.","category":"page"},{"location":"submodules/Nonlinear/overview/#ReverseAD","page":"Overview","title":"ReverseAD","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.ReverseAD is a submodule for computing derivatives of a nonlinear optimization problem using sparse reverse-mode automatic differentiation (AD).","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This section does not attempt to explain how sparse reverse-mode AD works, but instead explains why MOI contains its own implementation, and highlights notable differences from similar packages.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nDon't use the API in ReverseAD to compute derivatives. Instead, create a Nonlinear.Evaluator object with Nonlinear.SparseReverseMode as the backend, and then query the MOI API methods.","category":"page"},{"location":"submodules/Nonlinear/overview/#Design-goals","page":"Overview","title":"Design goals","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The JuliaDiff organization maintains a list of packages for doing AD in Julia. At last count, there were at least ten packages——not including ReverseAD——for reverse-mode AD in Julia. ReverseAD exists because it has a different set of design goals.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Goal: handle scale and sparsity. The types of nonlinear optimization problems that MOI represents can be large scale (10^5 or more functions across 10^5 or more variables) with very sparse derivatives. The ability to compute a sparse Hessian matrix is essential. To the best of our knowledge, ReverseAD is the only reverse-mode AD system in Julia that handles sparsity by default.\nGoal: limit the scope to improve robustness. Most other AD packages accept arbitrary Julia functions as input and then trace an expression graph using operator overloading. This means they must deal (or detect and ignore) with control flow, I/O, and other vagaries of Julia. In contrast, ReverseAD only accepts functions in the form of Nonlinear.Expression, which greatly limits the range of syntax that it must deal with. By reducing the scope of what we accept as input to functions relevant for mathematical optimization, we can provide a simpler implementation with various performance optimizations.\nGoal: provide outputs which match what solvers expect. Other AD packages focus on differentiating individual Julia functions. In contrast, ReverseAD has a very specific use-case: to generate outputs needed by the MOI nonlinear API. This means it needs to efficiently compute sparse Hessians, and it needs subexpression handling to avoid recomputing subexpressions that are shared between functions.","category":"page"},{"location":"submodules/Nonlinear/overview/#History","page":"Overview","title":"History","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"ReverseAD started life as ReverseDiffSparse.jl, development of which began in early 2014(!). This was well before the other AD packages started development. Because we had a well-tested, working AD in JuMP, there was less motivation to contribute to and explore other AD packages. The lack of historical interaction also meant that other packages were not optimized for the types of problems that JuMP is built for (that is, large-scale sparse problems). When we first created MathOptInterface, we kept the AD in JuMP to simplify the transition, and post-poned the development of a first-class nonlinear interface in MathOptInterface.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Prior to the introduction of Nonlinear, JuMP's nonlinear implementation was a confusing mix of functions and types spread across the code base and in the private _Derivatives submodule. This made it hard to swap the AD system for another. The main motivation for refactoring JuMP to create the Nonlinear submodule in MathOptInterface was to abstract the interface between JuMP and the AD system, allowing us to swap-in and test new AD systems in the future.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/bridging_constraint/#Implementing-a-constraint-bridge","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"This guide outlines the basic steps to create a new bridge from a constraint expressed in the formalism Function-in-Set.","category":"page"},{"location":"tutorials/bridging_constraint/#Preliminaries","page":"Implementing a constraint bridge","title":"Preliminaries","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"First, decide on the set you want to bridge. Then, study its properties: the most important one is whether the set is scalar or vector, which impacts the dimensionality of the functions that can be used with the set.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"A scalar function only has one dimension. MOI defines three types of scalar functions: a variable (VariableIndex), an affine function (ScalarAffineFunction), or a quadratic function (ScalarQuadraticFunction).\nA vector function has several dimensions (at least one). MOI defines three types of vector functions: several variables (VectorOfVariables), an affine function (VectorAffineFunction), or a quadratic function (VectorQuadraticFunction). The main difference with scalar functions is that the order of dimensions can be very important: for instance, in an indicator constraint (Indicator), the first dimension indicates whether the constraint about the second dimension is active.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"To explain how to implement a bridge, we present the example of Bridges.Constraint.FlipSignBridge. This bridge maps <= (LessThan) constraints to >= (GreaterThan) constraints. This corresponds to reversing the sign of the inequality. We focus on scalar affine functions (we disregard the cases of a single variable or of quadratic functions). This example is a simplified version of the code included in MOI.","category":"page"},{"location":"tutorials/bridging_constraint/#Four-mandatory-parts-in-a-constraint-bridge","page":"Implementing a constraint bridge","title":"Four mandatory parts in a constraint bridge","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The first part of a constraint bridge is a new concrete subtype of Bridges.Constraint.AbstractBridge. This type must have fields to store all the new variables and constraints that the bridge will add. Typically, these types are parametrized by the type of the coefficients in the model.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Then, three sets of functions must be defined:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Bridges.Constraint.bridge_constraint: this function implements the bridge and creates the required variables and constraints.\nsupports_constraint: these functions must return true when the combination of function and set is supported by the bridge. By default, the base implementation always returns false and the bridge does not have to provide this implementation.\nBridges.added_constrained_variable_types and Bridges.added_constraint_types: these functions return the types of variables and constraints that this bridge adds. They are used to compute the set of other bridges that are required to use the one you are defining, if need be.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"More functions can be implemented, for instance to retrieve properties from the bridge or deleting a bridged constraint.","category":"page"},{"location":"tutorials/bridging_constraint/#.-Structure-for-the-bridge","page":"Implementing a constraint bridge","title":"1. Structure for the bridge","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"A typical struct behind a bridge depends on the type of the coefficients that are used for the model (typically Float64, but coefficients might also be integers or complex numbers).","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"This structure must hold a reference to all the variables and the constraints that are created as part of the bridge.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The type of this structure is used throughout MOI as an identifier for the bridge. It is passed as argument to most functions related to bridges.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The best practice is to have the name of this type end with Bridge.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In our example, the bridge maps any ScalarAffineFunction{T}-in-LessThan{T} constraint to a single ScalarAffineFunction{T}-in-GreaterThan{T} constraint. The affine function has coefficients of type T. The bridge is parametrized with T, so that the constraint that the bridge creates also has coefficients of type T.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"struct SignBridge{T<:Number} <: Bridges.Constraint.AbstractBridge\n constraint::ConstraintIndex{ScalarAffineFunction{T}, GreaterThan{T}}\nend","category":"page"},{"location":"tutorials/bridging_constraint/#.-Bridge-creation","page":"Implementing a constraint bridge","title":"2. Bridge creation","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The function Bridges.Constraint.bridge_constraint is called whenever the bridge is instantiated for a specific model, with the given function and set. The arguments to bridge_constraint are similar to add_constraint, with the exception of the first argument: it is the Type of the struct defined in the first step (for our example, Type{SignBridge{T}}).","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"bridge_constraint returns an instance of the struct defined in the first step. the first step.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In our example, the bridge constraint could be defined as:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function Bridges.Constraint.bridge_constraint(\n ::Type{SignBridge{T}}, # Bridge to use.\n model::ModelLike, # Model to which the constraint is being added.\n f::ScalarAffineFunction{T}, # Function to rewrite.\n s::LessThan{T}, # Set to rewrite.\n) where {T}\n # Create the variables and constraints required for the bridge.\n con = add_constraint(model, -f, GreaterThan(-s.upper))\n\n # Return an instance of the bridge type with a reference to all the\n # variables and constraints that were created in this function.\n return SignBridge(con)\nend","category":"page"},{"location":"tutorials/bridging_constraint/#.-Supported-constraint-types","page":"Implementing a constraint bridge","title":"3. Supported constraint types","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The function supports_constraint determines whether the bridge type supports a given combination of function and set.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"This function must closely match bridge_constraint, because it will not be called if supports_constraint returns false.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function supports_constraint(\n ::Type{SignBridge{T}}, # Bridge to use.\n ::Type{ScalarAffineFunction{T}}, # Function to rewrite.\n ::Type{LessThan{T}}, # Set to rewrite.\n) where {T}\n # Do some computation to ensure that the constraint is supported.\n # Typically, you can directly return true.\n return true\nend","category":"page"},{"location":"tutorials/bridging_constraint/#.-Metadata-about-the-bridge","page":"Implementing a constraint bridge","title":"4. Metadata about the bridge","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"To determine whether a bridge can be used, MOI uses a shortest-path algorithm that uses the variable types and the constraints that the bridge can create. This information is communicated from the bridge to MOI using the functions Bridges.added_constrained_variable_types and Bridges.added_constraint_types. Both return lists of tuples: either a list of 1-tuples containing the variable types (typically, ZeroOne or Integer) or a list of 2-tuples contained the functions and sets (like ScalarAffineFunction{T}-GreaterThan).","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"For our example, the bridge does not create any constrained variables, and only ScalarAffineFunction{T}-in-GreaterThan{T} constraints:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function Bridges.added_constrained_variable_types(::Type{SignBridge{T}}) where {T}\n # The bridge does not create variables, return an empty list of tuples:\n return Tuple{Type}[]\nend\n\nfunction Bridges.added_constraint_types(::Type{SignBridge{T}}) where {T}\n return Tuple{Type,Type}[\n # One element per F-in-S the bridge creates.\n (ScalarAffineFunction{T}, GreaterThan{T}),\n ]\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"A bridge that creates binary variables would rather have this definition of added_constrained_variable_types:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function Bridges.added_constrained_variable_types(::Type{SomeBridge{T}}) where {T}\n # The bridge only creates binary variables:\n return Tuple{Type}[(ZeroOne,)]\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"warning: Warning\nIf you declare the creation of constrained variables in added_constrained_variable_types, the corresponding constraint type VariableIndex must not be indicated in added_constraint_types. This would restrict the use of the bridge to solvers that can add such a constraint after the variable is created.More concretely, if you declare in added_constrained_variable_types that your bridge creates binary variables (ZeroOne), and if you never add such a constraint afterward (you do not call add_constraint(model, var, ZeroOne())), then you must not list (VariableIndex, ZeroOne) in added_constraint_types.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Typically, the function Bridges.Constraint.concrete_bridge_type does not have to be defined for most bridges.","category":"page"},{"location":"tutorials/bridging_constraint/#Bridge-registration","page":"Implementing a constraint bridge","title":"Bridge registration","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"For a bridge to be used by MOI, it must be known by MOI.","category":"page"},{"location":"tutorials/bridging_constraint/#SingleBridgeOptimizer","page":"Implementing a constraint bridge","title":"SingleBridgeOptimizer","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The first way to do so is to create a single-bridge optimizer. This type of optimizer wraps another optimizer and adds the possibility to use only one bridge. It is especially useful when unit testing bridges.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"It is common practice to use the same name as the type defined for the bridge (SignBridge, in our example) without the suffix Bridge.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"const Sign{T,OT<: ModelLike} =\n SingleBridgeOptimizer{SignBridge{T}, OT}","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In the context of unit tests, this bridge is used in conjunction with a Utilities.MockOptimizer:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"mock = Utilities.MockOptimizer(\n Utilities.UniversalFallback(Utilities.Model{Float64}()),\n)\nbridged_mock = Sign{Float64}(mock)","category":"page"},{"location":"tutorials/bridging_constraint/#New-bridge-for-a-LazyBridgeOptimizer","page":"Implementing a constraint bridge","title":"New bridge for a LazyBridgeOptimizer","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Typical user-facing models for MOI are based on Bridges.LazyBridgeOptimizer. For instance, this type of model is returned by Bridges.full_bridge_optimizer. These models can be added more bridges by using Bridges.add_bridge:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"inner_optimizer = Utilities.Model{Float64}()\noptimizer = Bridges.full_bridge_optimizer(inner_optimizer, Float64)\nBridges.add_bridge(optimizer, SignBridge{Float64})","category":"page"},{"location":"tutorials/bridging_constraint/#Bridge-improvements","page":"Implementing a constraint bridge","title":"Bridge improvements","text":"","category":"section"},{"location":"tutorials/bridging_constraint/#Attribute-retrieval","page":"Implementing a constraint bridge","title":"Attribute retrieval","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Like models, bridges have attributes that can be retrieved using get and set. The most important ones are the number of variables and constraints, but also the lists of variables and constraints.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In our example, we only have one constraint and only have to implement the NumberOfConstraints and ListOfConstraintIndices attributes:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function get(\n ::SignBridge{T},\n ::NumberOfConstraints{\n ScalarAffineFunction{T},\n GreaterThan{T},\n },\n) where {T}\n return 1\nend\n\nfunction get(\n bridge::SignBridge{T},\n ::ListOfConstraintIndices{\n ScalarAffineFunction{T},\n GreaterThan{T},\n },\n) where {T}\n return [bridge.constraint]\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"You must implement one such pair of functions for each type of constraint the bridge adds to the model.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"warning: Warning\nAvoid returning a list from the bridge object without copying it. Users must be able to change the contents of the returned list without altering the bridge object.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"For variables, the situation is simpler. If your bridge creates new variables, you must implement the NumberOfVariables and ListOfVariableIndices attributes. However, these attributes do not have parameters, unlike their constraint counterparts. Only two functions suffice:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function get(\n ::SignBridge{T},\n ::NumberOfVariables,\n) where {T}\n return 0\nend\n\nfunction get(\n ::SignBridge{T},\n ::ListOfVariableIndices,\n) where {T}\n return VariableIndex[]\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In order for the user to be able to access the function and set of the original constraint, the bridge needs to implement getters for the ConstraintFunction and ConstraintSet attributes:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function get(\n model::MOI.ModelLike,\n attr::MOI.ConstraintFunction,\n bridge::SignBridge,\n)\n return -MOI.get(model, attr, bridge.constraint)\nend\n\nfunction get(\n model::MOI.ModelLike,\n attr::MOI.ConstraintSet,\n bridge::SignBridge,\n)\n set = MOI.get(model, attr, bridge.constraint)\n return MOI.LessThan(-set.lower)\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"warning: Warning\nAlternatively, one could store the original function and set in SignBridge during Bridges.Constraint.bridge_constraint to make these getters simpler and more efficient. On the other hand, this will increase the memory footprint of the bridges as the garbage collector won't be able to delete that object. The convention is to not store the function in the bridge and not care too much about the efficiency of these getters. If the user needs efficient getters for ConstraintFunction then they should use a Utilities.CachingOptimizer.","category":"page"},{"location":"tutorials/bridging_constraint/#Model-modifications","page":"Implementing a constraint bridge","title":"Model modifications","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"To avoid copying the model when the user request to change a constraint, MOI provides modify. Bridges can also implement this API to allow certain changes, such as coefficient changes.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In our case, a modification of a coefficient in the original constraint (for example, replacing the value of the coefficient of a variable in the affine function) must be transmitted to the constraint created by the bridge, but with a sign change.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function modify(\n model::ModelLike,\n bridge::SignBridge,\n change::ScalarCoefficientChange,\n)\n modify(\n model,\n bridge.constraint,\n ScalarCoefficientChange(change.variable, -change.new_coefficient),\n )\n return\nend","category":"page"},{"location":"tutorials/bridging_constraint/#Bridge-deletion","page":"Implementing a constraint bridge","title":"Bridge deletion","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"When a bridge is deleted, the constraints it added must be deleted too.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function delete(model::ModelLike, bridge::SignBridge)\n delete(model, bridge.constraint)\n return\nend","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"CurrentModule = MathOptInterface","category":"page"},{"location":"release_notes/#Release-notes","page":"Release notes","title":"Release notes","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.","category":"page"},{"location":"release_notes/#[v1.20.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.20.0)-(September-7,-2023)","page":"Release notes","title":"v1.20.0 (September 7, 2023)","text":"","category":"section"},{"location":"release_notes/#Added","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Scaled set (#2237) (#2263) (#2264)\nAdded ObjectiveLimit attribute (#2257)","category":"page"},{"location":"release_notes/#Other","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Updated dependencies (#2258)\nImproved performance of ScalarNonlinearFunction utilities (#2259)\nFixed docstrings (#2261)","category":"page"},{"location":"release_notes/#[v1.19.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.19.0)-(August-15,-2023)","page":"Release notes","title":"v1.19.0 (August 15, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-2","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added VectorNonlinearFunction (#2201)\nAdded new bridges\nBridges.Constraint.IntegerToZeroOneBridge (#2205)\nBridges.Constraint.ToScalarQuadraticBridge (#2235)\nBridges.Constraint.ToVectorQuadraticBridge (#2235)\nBridges.Constraint.ToScalarNonlinearBridge (#2233) (#2235)\nBridges.Constraint.FunctionConversionBridge (#2235)\nAdded Bridges.bridging_cost for setting a bridge-specific cost in the bridging graph (#2235)\nAdded Utilities.eval_variables support for ScalarNonlinearFunction (#2218) (#2219)\nAdded support for ScalarNonlinearFunction in FileFormats.NL (#2228) (#2231)\nAdded support for writing non-Float64 functions in FileFormats.MOF\nAdded Utilities.lazy_map (#2254)","category":"page"},{"location":"release_notes/#Fixed","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed method ambiguities in operate (#2224)\nFixed reading LP file with a -infinity <= x <= +infinity variable (#2225)\nFixed missing require in Test.test_nonlinear_duals (#2230)\nFixed bug in ConstraintPrimal of Bridges.Constraint.QuadtoSOCBridge (#2240)","category":"page"},{"location":"release_notes/#Other-2","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added extensions to solver-tests.yml (#2229)\nRefactored test/Benchmarks (#2234)\nFixed warnings in tests (#2241) (#2243)\nSmall refactoring of bridges for upcoming VectorNonlinearFunction (#2244) (#2245)\nFixed various typos (#2251) (#2255)\nPartitioned how we run the tests on GitHub actions (#2252) (#2253)","category":"page"},{"location":"release_notes/#[v1.18.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.18.0)-(June-23,-2023)","page":"Release notes","title":"v1.18.0 (June 23, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-3","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Bridges.Objective.SlackBridgePrimalDualStart (#2194)\nAdded constraint_gradient_structure and eval_constraint_gradient (#2200)","category":"page"},{"location":"release_notes/#Fixed-2","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a missing @require in MOI.Test (#2195) (#2196)\nFixed incorrect usage of Utilities.operate! in bridges (#2207) (#2216)\nFixed splatting nonlinear expression with univariate operator (#2221)","category":"page"},{"location":"release_notes/#Other-3","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Removed unused argument names (#2199)\nReduced memory requirement for tests (#2204)\nRefactored Utilities.promote_operation (#2206)\nImproved code style in Utilities/mutable_arithmetics.jl (#2209)\nRefactored various methods in Utilities/functions.jl (#2208) (#2212) (#2213) (#2214) (#2215)","category":"page"},{"location":"release_notes/#[v1.17.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.17.1)-(June-6,-2023)","page":"Release notes","title":"v1.17.1 (June 6, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-3","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed comparison of ScalarFunctionConstantNotZero (#2190)","category":"page"},{"location":"release_notes/#Other-4","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added documentation for enum instances (#2186)\nUpdated chatroom links in documentation (#2188)\nChanged the documentation to build on Julia v1.9 (#2191)","category":"page"},{"location":"release_notes/#[v1.17.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.17.0)-(June-1,-2023)","page":"Release notes","title":"v1.17.0 (June 1, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-4","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added ScalarNonlinearFunction (#2059)\nAdded a variety of tests for NormSpectralCone, NormNuclearCone, and HermitianPositiveSemidefiniteConeTriangle (#2174)\nAdded Utilities.value_type for computing the value type of a function (#2176)","category":"page"},{"location":"release_notes/#Fixed-4","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed support for external sets in Utilities.loadfromstring! (#2177)\nFixed promote_operation for ScalarNonlinearFunction (#2179)\nFixed two issues in FileFormats.LP when reading files with quadratic functions (#2182) (#2184)","category":"page"},{"location":"release_notes/#[v1.16.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.16.0)-(May-16,-2023)","page":"Release notes","title":"v1.16.0 (May 16, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-5","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added support for MathOptFormat v1.3 and v1.4 (#2158) (#2169)\nAdded new method to the nonlinear API (#2162) (#2164)\neval_hessian_constraint\neval_hessian_objective\nhessian_constraint_structure\nhessian_objective_structure\nAdded new sets\nNormCone (#2119)\nScaledPositiveSemidefiniteConeTriangle (#2154)","category":"page"},{"location":"release_notes/#Fixed-5","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed support for Julia v1.9 to work around a bug in the upstream Julia compiler (#2161) (#2163)\nFixed a correctness bug in Bridges.Constraint.HermitianToSymmetricPSDBridge (#2171)\nFixed convert(::VariableIndex, ::ScalarAffineFunction) when the function has terms with 0coefficients (#2173)","category":"page"},{"location":"release_notes/#Other-5","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed solver-tests.yml (#2157)\nUpdated documentation links to developer chatroom (#2160)\nAdded various tests for bridges (#2156)\nAdded checklists to the developer documentation (#2167) (#2168)","category":"page"},{"location":"release_notes/#[v1.15.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.15.1)-(April-25,-2023)","page":"Release notes","title":"v1.15.1 (April 25, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-6","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed deleting a variable in a bridged objective (#2150)","category":"page"},{"location":"release_notes/#[v1.15.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.15.0)-(April-19,-2023)","page":"Release notes","title":"v1.15.0 (April 19, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-6","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Bridges.Objective.VectorFunctionizeBridge (#2139)","category":"page"},{"location":"release_notes/#Fixed-7","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed support for Rational in Bridges.Constraint.SplitIntervalBridge (#2137)\nFixed printing of LaTeX models (#2141)\nFixed modify in Bridges.Objective.VectorSlackBridge (#2144)\nFixed NAME record with spaces in FileFormats.MPS (#2146)\nFixed deleting a variable in a bridged objective (#2147)","category":"page"},{"location":"release_notes/#Other-6","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add a test for variables in one-sided open Interval sets (#2133)\nMinor style fixes in the source code (#2148)","category":"page"},{"location":"release_notes/#[v1.14.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.14.1)-(April-6,-2023)","page":"Release notes","title":"v1.14.1 (April 6, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-8","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in Bridges.print_active_bridges (#2135)","category":"page"},{"location":"release_notes/#Other-7","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added a warning when an ambiguous string is passed to exclude in Test.runtests (#2136)","category":"page"},{"location":"release_notes/#[v1.14.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.14.0)-(April-4,-2023)","page":"Release notes","title":"v1.14.0 (April 4, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-7","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added support for starting values in Bridges.Constraint.QuadtoSOCBridge (#2115)\nAdded support for Regex in the include and exclude arguments to Test.runtests (#2129)\nAdded Bridges.print_active_bridges methods for individual objectives and constraints (#2128)","category":"page"},{"location":"release_notes/#Fixed-9","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed ResultCount when parsing .sol files in FileFormats.NL (#2130)","category":"page"},{"location":"release_notes/#[v1.13.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.13.2)-(March-21,-2023)","page":"Release notes","title":"v1.13.2 (March 21, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-10","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed splatting of containers in MOI.Nonlinear (#2120)\nFixed a bug reading LP files with default bounds (#2121)\nFixed a bug in which Bridges.Constraint.HermitianToSymmetricPSDBridge was not enabled by default (#2123)","category":"page"},{"location":"release_notes/#Other-8","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed typos in the documentation (#2114)\nFunctions now print to the REPL in algebraic form. This is potentially breaking if you have tests which rely on a specific String form of MOI functions. (#2112) (#2126)","category":"page"},{"location":"release_notes/#[v1.13.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.13.1)-(March-3,-2023)","page":"Release notes","title":"v1.13.1 (March 3, 2023)","text":"","category":"section"},{"location":"release_notes/#Other-9","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added the Google style guide to the documentation linter Vale, and fixed the resulting warnings (#2110)\nImproved the docstrings in src/functions.jl (#2108)","category":"page"},{"location":"release_notes/#[v1.13.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.13.0)-(February-28,-2023)","page":"Release notes","title":"v1.13.0 (February 28, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-8","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Bridges.Constraint.NumberConversionBridge (#2091)\nAdded Parameter set (#2095) (#2105) (#2106) (#2109)\nAdded with_cache_type argument to instantiate (#2097)\nAdded support for HermitianPositiveSemidefiniteConeTriangle in Utilities.Model (#2100)","category":"page"},{"location":"release_notes/#Fixed-11","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed bug when Utilities.@product_of_sets is empty (#2101)\nFixed Bridges.print_active_bridges when variable bridge is an AbstractScalarSet (#2107)","category":"page"},{"location":"release_notes/#Other-10","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added tests for vector-valued objective functions in FileFormats.MOF (#2093)\nUsed and documented preference for import MathOptInterface as MOI (#2096)\nFix and test links in the documentation with linkcheck = true (#2098)\nImproved docstrings of sets in src/sets.jl (#2099)\nSkip checking flakey links in documentation with linkcheck_ignore (#2103)","category":"page"},{"location":"release_notes/#[v1.12.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.12.0)-(February-10,-2023)","page":"Release notes","title":"v1.12.0 (February 10, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-9","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added support for vector-valued objective functions (#2070)\nAdded a Utilities.distance_to_set method for SecondOrderCone (#2060)","category":"page"},{"location":"release_notes/#Fixed-12","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a number of constraint bridges so that Bridges.final_touch can be called multiple times without forcing a rebuild of the reformulation (#2089)","category":"page"},{"location":"release_notes/#Other-11","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new tests that a set ObjectiveFunction appears in ListOfModelAttributesSet (#2085)\nImproved the docstrings of a number of constraint-programming related sets (#2087)","category":"page"},{"location":"release_notes/#[v1.11.5](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.5)-(January-24,-2023)","page":"Release notes","title":"v1.11.5 (January 24, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-13","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug writing .lp files with an off-diagonal quadratic objective (#2082)","category":"page"},{"location":"release_notes/#Other-12","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added SnoopPrecompile directives for reduced time-to-first-X in Julia v1.9 (#2080)","category":"page"},{"location":"release_notes/#[v1.11.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.4)-(January-12,-2023)","page":"Release notes","title":"v1.11.4 (January 12, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-14","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .lp files with an Integer section (#2078)","category":"page"},{"location":"release_notes/#[v1.11.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.3)-(January-12,-2023)","page":"Release notes","title":"v1.11.3 (January 12, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-15","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a performance bug when deleting a vector of constraints (#2072)\nFixed a bug reading .lp files with terms like x -1 y (#2076)","category":"page"},{"location":"release_notes/#Other-13","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Documented the two-argument method of optimize! (#2074)","category":"page"},{"location":"release_notes/#[v1.11.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.2)-(January-2,-2023)","page":"Release notes","title":"v1.11.2 (January 2, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-16","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .mof.json files with ConstraintName set for VariableIndex constraints (#2066)\nFixed a bug reading .mof.json files with nonlinear objectives and no constraints (#2068)","category":"page"},{"location":"release_notes/#[v1.11.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.1)-(December-22,-2022)","page":"Release notes","title":"v1.11.1 (December 22, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-17","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .mof.json files with integer coefficients for affine and quadratic functions (#2063)","category":"page"},{"location":"release_notes/#[v1.11.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.0)-(December-2,-2022)","page":"Release notes","title":"v1.11.0 (December 2, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-10","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Utilities.PenaltyRelaxation and Utilities.ScalarPenaltyRelaxation (#1995)\nAdded Utilities.distance_to_set (#2048)\nAdded support for ConstraintPrimalStart and ConstraintDualStart in FileFormats.MOF (#2056)","category":"page"},{"location":"release_notes/#Other-14","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Tidied these release notes (#2055)","category":"page"},{"location":"release_notes/#[v1.10.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.10.0)-(November-22,-2022)","page":"Release notes","title":"v1.10.0 (November 22, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-11","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new methods set(::OptimizerWithAttributes, ::RawOptimizerAttribute, value) and get(::OptimizerWithAttributes, ::RawOptimizerAttribute) (#2049)\nAdded new methods Utilities.DoubleDicts.outer_keys and Utilities.DoubleDicts.nonempty_outer_keys (#2052)","category":"page"},{"location":"release_notes/#Fixed-18","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed Bridges.Objective.SlackBridge when the objective function is complex-valued (#2036) (#2038)\nFixed docstring of Test.runtests to clarify the warn_unsupported argument (#2037)\nFixed reading of free variables in FileFormats.LP (#2044)\nFixed numerous edge cases reading files from QPLIB using FileFormats.LP (#2042) (#2044)\nFixed situations in which x^y returns a complex value in Nonlinear (#2050)","category":"page"},{"location":"release_notes/#Other-15","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved the error message thrown when a user-defined nonlinear function does not accept splatted input (#2032)\nRemoved specialized iterators for keys and values in Utilities.CleverDicts (#2051)","category":"page"},{"location":"release_notes/#[v1.9.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.9.0)-(October-29,-2022)","page":"Release notes","title":"v1.9.0 (October 29, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-12","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added default fallback for getting ListOfConstraintIndices and NumberOfConstraints when the constraint type is unsupported by the model (#2021)\nAdded support for min and max in nonlinear expressions (#2023)\nAdded support for Indicator{EqualTo{T}} constraints in FileFormats.MPS (#2022)\nAdded default fallback for write_to_file and read_from_file (#2029)","category":"page"},{"location":"release_notes/#Fixed-19","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed Constraint.ZeroOneBridge by adding new bounds as affine constraints instead of variable bounds (#1879)\nFixed reading free rows in FileFormats.MPS files (#2009)\nFixed parsing of OBJSENSE blocks in FileFormats.MPS files (#2016) (#2019)\nFixed the parsing of deeply nested nonlinear expressions by removing the use of recursion (#2020)\nFixed the requirements check in Test.test_constrainnt_get_ConstraintIndex (#2024)","category":"page"},{"location":"release_notes/#[v1.8.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.8.2)-(September-20,-2022)","page":"Release notes","title":"v1.8.2 (September 20, 2022)","text":"","category":"section"},{"location":"release_notes/#Documentation","page":"Release notes","title":"Documentation","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added vale as a documentation linter (#2002)\nImproved styling of code blocks in the PDF (#1999) (#2000)\nFixed a number of typos in the documentation (#2001) (#2003)","category":"page"},{"location":"release_notes/#[v1.8.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.8.1)-(September-12,-2022)","page":"Release notes","title":"v1.8.1 (September 12, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-20","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in supports(::AbstractBridgeOptimizer for constraint attributes (#1991) (#1992)","category":"page"},{"location":"release_notes/#[v1.8.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.8.0)-(September-1,-2022)","page":"Release notes","title":"v1.8.0 (September 1, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-13","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new sets\nHyperRectangle (#1961)\nReified (#1955)\nAdded new bridges (#1955)\nBridges.Constraint.ReifiedAllDifferentToCountDistinctBridge\nBridges.Constraint.ReifiedCountDistinctToMILPBridge\nBridges.Constraint.SplitHyperRectangleBridge\nAdded support for atan(y, x) in Nonlinear (#1987)","category":"page"},{"location":"release_notes/#Fixed-21","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Lazily construct expressions in Nonlinear so that expressions are updated when Nonlinear.Parameter values are updated (#1984)\nAllow NORM_LIMIT as a TerminationStatus for unbounded problems in Test (#1990)","category":"page"},{"location":"release_notes/#[v1.7.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.7.0)-(August-16,-2022)","page":"Release notes","title":"v1.7.0 (August 16, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-14","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new sets\nHermitianPositiveSemidefiniteConeTriangle\nAdded new optimizer-independent options\nRelativeGapTolerance\nAbsoluteGapTolerance\nAdded new bridges\nBridges.Constraint.GeoMeanToPowerBridge\nBridges.Constraint.HermitianToSymmetricPSDBridge\nBridges.Constraint.IndicatorGreaterToLessThanBridge\nBridges.Constraint.IndicatorLessToGreaterThanBridge\nBridges.Constraint.SplitComplexZerosBridge\nBridges.Constraint.SplitComplexEqualToBridge\nBridges.Objective.QuadratizeBridge\nAdded support for generic number types in Utilities.loadfromstring!\nUpdated FileFormats.MOF to MathOptFormat v1.1, enabling support for constraint programming sets in the MOF file format\nAdded support in various FileFormats for\nindicator constraints in FileFormats.MPS\nquadratic constraints and an objective in FileFormats.LP\nquadratic constraints and an objective in FileFormats.MPS","category":"page"},{"location":"release_notes/#Fixed-22","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed some missing promotion rules","category":"page"},{"location":"release_notes/#Other-16","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved the performance of Jacobian products in Nonlinear\nRemoved an un-needed copy in Utilities.modify_function\nVarious clean-ups in Bridges/bridge_optimizer.jl","category":"page"},{"location":"release_notes/#[v1.6.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.6.1)-(July-23,-2022)","page":"Release notes","title":"v1.6.1 (July 23, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-23","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added support for ExponentialCone in MatrixOfConstraints\nFix PSDSquare_3 test to reflect a previously fixed bug getting the ConstraintDual of a PositiveSemidefiniteConeSquare constraint","category":"page"},{"location":"release_notes/#[v1.6.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.6.0)-(July-2,-2022)","page":"Release notes","title":"v1.6.0 (July 2, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-15","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Bridges.needs_final_touch and Bridges.final_touch\nAdded new bridges from constraint programming sets to mixed-integer linear programs:\nAllDifferentToCountDistinctBridge\nCountAtLeastToCountBelongsBridge\nCountBelongsToMILPBridge\nCountDistinctToMILPBridge\nCountGreaterThanToMILPBridge\nCircuitToMILPBridge","category":"page"},{"location":"release_notes/#Fixed-24","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Relax an instance of ::Vector to ::AbstractVector in MOI.Nonlinear\nFix BinPackingToMILPBridge to respect variable bounds\nFix SemiToBinaryBridge to throw error if other bounds are set","category":"page"},{"location":"release_notes/#[v1.5.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.5.0)-(June-27,-2022)","page":"Release notes","title":"v1.5.0 (June 27, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-16","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added GetAttributeNotAllowed for solvers to indicate when getting an attribute encounters an error\nAdded Utilities.get_fallback support for ObjectiveValue and DualObjectiveValue\nAdded new bridges:\nRootDetConeSquare to RootDetConeTriangle\nLogDetConeSquare to LogDetConeTriangle\nBinPacking to a mixed-integer linear program\nTable to a mixed-integer linear program\nAdded Bridges.print_active_bridges to display the current optimal hyper-path in a Bridges.LazyBridgeOptimizer","category":"page"},{"location":"release_notes/#Fixed-25","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed ZeroOne tests with lower and upper bounds\nFixed error in FileFormats.LP when reading a malformed file\nFixed reading of nonlinear programs in FileFormats.MOF\nFixed bug in ConstraintDual when using SquareBridge","category":"page"},{"location":"release_notes/#Other-17","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved documentation of nonlinear API\nDocumented duality convention for PositiveSemidefiniteConeSquare sets\nFixed typo in Bridges.Constraint.QuadToSOCBridge docstring","category":"page"},{"location":"release_notes/#[v1.4.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.4.0)-(June-9,-2022)","page":"Release notes","title":"v1.4.0 (June 9, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-17","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added a number of sets for constraint programming:\nAllDifferent\nBinPacking\nCircuit\nCountAtLeast\nCountBelongs\nCountDistinct\nCountGreaterThan\nCumulative\nPath\nTable\nAdded support for user-defined hessians in Nonlinear\nAdded Bridges.runtests to simplify the testing of bridge implementations","category":"page"},{"location":"release_notes/#Fixed-26","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in FileFormats.NL when writing univariate *","category":"page"},{"location":"release_notes/#Other-18","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Began a large refactoring of the Bridges submodule, with greatly improved documentation.","category":"page"},{"location":"release_notes/#[v1.3.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.3.0)-(May-27,-2022)","page":"Release notes","title":"v1.3.0 (May 27, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-18","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add MOI.Nonlinear submodule. This is a large new submodule that has been refactored from code that was in JuMP. For now, it should be considered experimental.\nAdd FileFormats.NL.SolFileResults(::IO, ::Model)\nAdd FileFormats.NL.read!(::IO, ::Model)\nAdd MOI.modify that accepts a vector of modifications","category":"page"},{"location":"release_notes/#Fixed-27","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in Test which attempted to include non-.jl files\nFixed a bug in FileFormats for models with open interval constraints","category":"page"},{"location":"release_notes/#Other-19","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a performance issue in Utilities.DoubleDict\nVarious minor improvements to the documentation","category":"page"},{"location":"release_notes/#[v1.2.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.2.0)-(April-25,-2022)","page":"Release notes","title":"v1.2.0 (April 25, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-19","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add support for the FORMAT_REW/.rew file format in FileFormats.","category":"page"},{"location":"release_notes/#Fixed-28","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix bug handling of default variable bounds in FileFormats.LP\nFix FileFormats.MPS to not write OBJSENSE by default since this is only supported by some readers.","category":"page"},{"location":"release_notes/#[v1.1.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.1.2)-(March-31,-2022)","page":"Release notes","title":"v1.1.2 (March 31, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-29","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix a range of bugs in FileFormats.LP\nFix reading of problem dimensions in FileFormats.SDPA","category":"page"},{"location":"release_notes/#[v1.1.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.1.1)-(March-23,-2022)","page":"Release notes","title":"v1.1.1 (March 23, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-30","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix bug in test_model_UpperBoundAlreadySet\nFix bug in test_infeasible_ tests\nFix bug in test_objective_ObjectiveFunction_blank\nRelax restriction of MOI.AbstractOptimizer to MOI.ModelLike in Utilities.CachingOptimizer and instantiate.","category":"page"},{"location":"release_notes/#New-tests","page":"Release notes","title":"New tests","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add test_conic_empty_matrix that checks conic solvers support problems with no variables.","category":"page"},{"location":"release_notes/#[v1.1.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.1.0)-(March-2,-2022)","page":"Release notes","title":"v1.1.0 (March 2, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-20","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added MOI.Utilities.throw_unsupported(::UniversalFallback) for simplifying solver wrappers which copy from a UniversalFallback.","category":"page"},{"location":"release_notes/#[v1.0.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.0.2)-(March-1,-2022)","page":"Release notes","title":"v1.0.2 (March 1, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-31","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in the test_model_ScalarFunctionConstantNotZero test\nFixed the error type when an AbstractFunctionConversionBridge cannot get or set an attribute\nIdentified a correctness bug in RSOCtoPSDBridge. We now thrown an error instead of returning an incorrect result.","category":"page"},{"location":"release_notes/#[v1.0.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.0.1)-(February-25,-2022)","page":"Release notes","title":"v1.0.1 (February 25, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-32","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in which OptimizerAttributes were not copied in CachingOptimizer\nFixed a bug in which shift_constant did not promote mixed types of coefficients\nFixed a bug in which deleting a constraint of a bridged variable threw ErrorException instead of MOI.DeleteNotAllowed\nFixed a bug in which add_constraint in MatrixOfConstraints did not canonicalize the function\nFixed a bug when modifying scalar constants of a function containing a bridged variable\nFixed a bug in which final_touch was not always called with a CachingOptimizer","category":"page"},{"location":"release_notes/#[v1.0.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.0.0)-(February-17,-2022)","page":"Release notes","title":"v1.0.0 (February 17, 2022)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Although tagged as a breaking release, v1.0.0 is v0.10.9 with deprecations removed, similar to how Julia 1.0 was Julia 0.7 with deprecations removed.","category":"page"},{"location":"release_notes/#Breaking","page":"Release notes","title":"Breaking","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Julia 1.6 is now the minimum supported version\nAll deprecations have been removed","category":"page"},{"location":"release_notes/#Troubleshooting-problems-when-updating","page":"Release notes","title":"Troubleshooting problems when updating","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"If you experience problems when updating, you are likely using previously deprecated features. (By default, Julia does not warn when you use deprecated features.)","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"To find the deprecated features you are using, start Julia with --depwarn=yes:","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"$ julia --depwarn=yes","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Then install MathOptInterface v0.10.9:","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"julia> using Pkg\njulia> pkg\"add MathOptInterface@0.10\"","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"And then run your code. Apply any suggestions, or search the release notes below for advice on updating a specific deprecated feature.","category":"page"},{"location":"release_notes/#[v0.10.9](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.9)-(February-16,-2022)","page":"Release notes","title":"v0.10.9 (February 16, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-21","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added MOI.Utilities.FreeVariables as a new VariablesConstrainer for conic solvers\nAdded MOI.default_cache for specifying the model used in CachingOptimizer","category":"page"},{"location":"release_notes/#Fixed-33","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed LaTeX printing of MOI.Interval sets","category":"page"},{"location":"release_notes/#Other-20","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Aqua.jl as a CI check, and fixed suggested issues\nThe constructors of GeoMeanBridge, StructOfConstraints, and CachingOptimizer were changed from outer to inner constructors. This change is technically breaking, but does not impact users who followed the documented API.","category":"page"},{"location":"release_notes/#[v0.10.8](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.8)-(February-3,-2022)","page":"Release notes","title":"v0.10.8 (February 3, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-22","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added a Base.read! for FileFormats.LP.","category":"page"},{"location":"release_notes/#Fixed-34","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in MutableSparseMatrix\nFixed a bug when calling operate!(vcat, ...) with Number arguments\nRemoved unintended export of deprecated symbols\nFixed a bug with PowerCone and DualPowerCone in MatrixOfConstraints.","category":"page"},{"location":"release_notes/#[v0.10.7](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.7)-(January-5,-2022)","page":"Release notes","title":"v0.10.7 (January 5, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-23","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added test for modifying the constant vector in a VectorAffineFunction-in-Zeros constraint.","category":"page"},{"location":"release_notes/#Fixed-35","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed the order in which sets are added to a LazyBridgeOptimizer. Compared to v0.10.6, this may result in bridged models being created with a different number (and order) of variables and constraints. However, it was necessary to fix cases which were previously rejected as unsupported, even though there was a valid bridge transformation.\nFixed an error message in FileFormats.CBF\nFixed comparison in test_linear_integration_Interval\nFixed errors for ConstraintPrimal in a CachingOptimizer\nFixed printing of models with non-Float64 coefficients.","category":"page"},{"location":"release_notes/#Other-21","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Various improvements to reduce time-to-first-solve latency\nImproved error message when an optimizer does not support compute_conflict!","category":"page"},{"location":"release_notes/#[v0.10.6](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.6)-(November-30,-2021)","page":"Release notes","title":"v0.10.6 (November 30, 2021)","text":"","category":"section"},{"location":"release_notes/#Added-24","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new documentation and tests for infeasibility certificates\nAdded a version control system for the tests in MOI.Test.runtests. Pass exclude_tests_after = v\"0.10.5\" to run tests added in v0.10.5 and earlier.\nMOI.Test.runtests now supports generic number types. To specify the number type T, pass MOI.Test.Config(T).\nAdded infeasible_status to MOI.Test.Config for solvers which return LOCALLY_INFEASIBLE\nCachingOptimizers now use a fallback for ConstraintPrimal. This should enable solvers using a CachingOptimizer to pass tests requiring ConstraintPrimal.","category":"page"},{"location":"release_notes/#Fixed-36","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a StackOverflow bug in copy_to\nFixed error thrown when nonconvex quadratic constraints cannot be bridged\nFixed a bug in copy_to for FileFormats.NL.Model\nFixed a bug in FileFormats.NL when printing large integers\nRemove a common test failure for LowerBoundAlreadySet tests\nUtilities.num_rows is now exported\nRemove parts of failing test_model_copy_to_xxx tests due to bridges","category":"page"},{"location":"release_notes/#[v0.10.5](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.5)-(November-7,-2021)","page":"Release notes","title":"v0.10.5 (November 7, 2021)","text":"","category":"section"},{"location":"release_notes/#Fixed-37","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed getter in UniversalFallback\nFixed test_solve_conflict_zeroone_ii","category":"page"},{"location":"release_notes/#Other-22","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Make normalize_and_add_constraint more flexible\nUpdate paper BibTeX","category":"page"},{"location":"release_notes/#[v0.10.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.4)-(October-26,-2021)","page":"Release notes","title":"v0.10.4 (October 26, 2021)","text":"","category":"section"},{"location":"release_notes/#Added-25","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add SolverVersion attribute\nAdd new tests:\ntest_solve_conflict_zeroone_ii\ntest_nonlinear_objective\nUtilities.VariablesContainer now supports ConstraintFunction and ConstraintSet\nThe documentation is now available as a PDF","category":"page"},{"location":"release_notes/#Other-23","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Update to MutableArithmetics 0.3\nVarious improvements to the documentation","category":"page"},{"location":"release_notes/#[v0.10.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.3)-(September-18,-2021)","page":"Release notes","title":"v0.10.3 (September 18, 2021)","text":"","category":"section"},{"location":"release_notes/#Fixed-38","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed bug which prevented callbacks from working through a CachingOptimizer\nFixed bug in Test submodule","category":"page"},{"location":"release_notes/#[v0.10.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.2)-(September-16,-2021)","page":"Release notes","title":"v0.10.2 (September 16, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Updated MathOptFormat to v1.0\nUpdated JSONSchema to v1.0\nAdded Utilities.set_with_dimension\nAdded two-argument optimize!(::AbstractOptimizer, ::ModelLike)\nThe experimental feature copy_to_and_optimize! has been removed\nDet bridges now support getting ConstraintFunction and ConstraintSet\nVarious minor bug fixes identified by improved testing","category":"page"},{"location":"release_notes/#[v0.10.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.1)-(September-8,-2021)","page":"Release notes","title":"v0.10.1 (September 8, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Various fixes to MOI.Test","category":"page"},{"location":"release_notes/#[v0.10.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.0)-(September-6,-2021)","page":"Release notes","title":"v0.10.0 (September 6, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"MOI v0.10 is a significant breaking release. There are a large number of user-visible breaking changes and code refactors, as well as a substantial number of new features.","category":"page"},{"location":"release_notes/#Breaking-in-MOI","page":"Release notes","title":"Breaking in MOI","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"SingleVariable has been removed; use VariableIndex instead\nSingleVariableConstraintNameError has been renamed to VariableIndexConstraintNameError\nSettingSingleVariableFunctionNotAllowed has been renamed to SettingVariableIndexFunctionNotAllowed\nVariableIndex constraints should not support ConstraintName\nVariableIndex constraints should not support ConstraintBasisStatus; implement VariableBasisStatus instead\nListOfConstraints has been renamed to ListOfConstraintTypesPresent\nListOfConstraintTypesPresent should now return Tuple{Type,Type} instead of Tuple{DataType,DataType}\nSolveTime has been renamed to SolveTimeSec\nIndicatorSet has been renamed to Indicator\nRawParameter has been renamed to RawOptimizerAttribute and now takes String instead of Any as the only argument\nThe .N field in result attributes has been renamed to .result_index\nThe .variable_index field in ScalarAffineTerm has been renamed to .variable\nThe .variable_index_1 field in ScalarQuadraticTerm has been renamed to .variable_1\nThe .variable_index_2 field in ScalarQuadraticTerm has been renamed to .variable_2\nThe order of affine_terms and quadratic_terms in ScalarQuadraticFunction and VectorQuadraticFunction have been reversed. Both functions now accept quadratic, affine, and constant terms in that order.\nThe index_value function has been removed. Use .value instead.\nisapprox has been removed for SOS1 and SOS2.\nThe dimension argument to Complements(dimension::Int) should now be the length of the corresponding function, instead of half the length. An ArgumentError is thrown if dimension is not even.\ncopy_to no longer takes keyword arguments:\ncopy_names: now copy names if they are supported by the destination solver\nfilter_constraints: use Utilities.ModelFilter instead\nwarn_attributes: never warn about optimizer attributes","category":"page"},{"location":"release_notes/#Breaking-in-Bridges","page":"Release notes","title":"Breaking in Bridges","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Constraint.RSOCBridge has been renamed to Constraint.RSOCtoSOCBridge\nConstraint.SOCRBridge has been renamed to Constraint.SOCtoRSOCBridge\nBridges now return vectors that can be modified by the user. Previously, some bridges returned views instead of copies.\nBridges.IndexInVector has been unified into a single type. Previously, there was a different type for each submodule within Bridges\nThe signature of indicator bridges has been fixed. Use MOI.Bridges.Constraint.IndicatortoSOS1{Float64}(model).","category":"page"},{"location":"release_notes/#Breaking-in-FileFormats","page":"Release notes","title":"Breaking in FileFormats","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"FileFormats.MOF.Model no longer accepts validate argument. Use the JSONSchema package to validate the MOF file. See the documentation for more information.","category":"page"},{"location":"release_notes/#Breaking-in-Utilities","page":"Release notes","title":"Breaking in Utilities","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"The datastructure of Utilities.Model (and models created with Utilities.@model) has been significantly refactored in a breaking way. This includes the way that objective functions and variable-related information is stored.\nUtilities.supports_default_copy has been renamed to supports_incremental_interface\nUtilities.automatic_copy_to has been renamed to Utilities.default_copy_to\nThe allocate-load API has been removed\nCachingOptimizers are now initialized as EMPTY_OPTIMIZER instead of ATTACHED_OPTIMIZER. If your code relies on the optimizer being attached, call MOIU.attach_optimizer(model) after creation.\nThe field names of Utilities.IndexMap have been renamed to var_map and con_map. Accessing these fields directly is considered a private detail that may change. Use the public getindex and setindex! API instead.\nThe size argument to Utilities.CleverDicts.CleverDict(::Integer) has been removed.\nThe size argument to Utilities.IndexMap(::Integer) has been removed.\nUtilities.DoubleDicts have been significantly refactored. Consult the source code for details.\nUtilities.test_models_equal has been moved to MOI.Test","category":"page"},{"location":"release_notes/#Breaking-in-Test","page":"Release notes","title":"Breaking in Test","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"MOI.Test has been renamed to MOI.DeprecatedTest\nAn entirely new MOI.Test submodule has been written. See the documentation for details. The new MOI.Test submodule may find many bugs in the implementations of existing solvers that were previously untested.","category":"page"},{"location":"release_notes/#Other-changes:","page":"Release notes","title":"Other changes:","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"attribute_value_type has been added\ncopy_to_and_optimize! has been added\nVariableBasisStatus has been added\nprint(model) now prints a human-readable description of the model\nVarious improvements to the FileFormats submodule\nFileFormats.CBF was refactored and received bugfixes\nSupport for MathOptFormat v0.6 was added in FileFormats.MOF\nFileFormats.MPS has had bugfixes and support for more features such as OBJSENSE and objective constants.\nFileFormats.NL has been added to support nonlinear files\nImproved type inference throughout to reduce latency","category":"page"},{"location":"release_notes/#Updating","page":"Release notes","title":"Updating","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"A helpful script when updating is:","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"for (root, dirs, files) in walkdir(\".\")\n for file in files\n if !endswith(file, \".jl\")\n continue\n end\n path = joinpath(root, file)\n s = read(path, String)\n for pair in [\n \".variable_index\" => \".variable\",\n \"RawParameter\" => \"RawOptimizerAttribute\",\n \"ListOfConstraints\" => \"ListOfConstraintTypesPresent\",\n \"TestConfig\" => \"Config\",\n \"attr.N\" => \"attr.result_index\",\n \"SolveTime\" => \"SolveTimeSec\",\n \"DataType\" => \"Type\",\n \"Utilities.supports_default_copy_to\" =>\n \"supports_incremental_interface\",\n \"SingleVariableConstraintNameError\" =>\n \"VariableIndexConstraintNameError\",\n \"SettingSingleVariableFunctionNotAllowed\" =>\n \"SettingVariableIndexFunctionNotAllowed\",\n \"automatic_copy_to\" => \"default_copy_to\",\n ]\n s = replace(s, pair)\n end\n write(path, s)\n end\nend","category":"page"},{"location":"release_notes/#[v0.9.22](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.22)-(May-22,-2021)","page":"Release notes","title":"v0.9.22 (May 22, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"This release contains backports from the ongoing development of the v0.10 release.","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved type inference in Utilities, Bridges and FileFormats submodules to reduce latency.\nImproved performance of Utilities.is_canonical.\nFixed Utilities.pass_nonvariable_constraints with bridged variables.\nFixed performance regression of Utilities.Model.\nFixed ordering of objective setting in parser.","category":"page"},{"location":"release_notes/#[v0.9.21](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.21)-(April-23,-2021)","page":"Release notes","title":"v0.9.21 (April 23, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added supports_shift_constant.\nImprove performance of bridging quadratic constraints.\nAdd precompilation statements.\nLarge improvements to the documentation.\nFix a variety of inference issues, benefiting precompilation and reducing initial latency.\nRawParameters are now ignored when resetting a CachingOptimizer. Previously, changing the underlying optimizer after RawParameters were set would throw an error.\nUtilities.AbstractModel is being refactored. This may break users interacting with private fields of a model generated using @model.","category":"page"},{"location":"release_notes/#[v0.9.20](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.20)-(February-20,-2021)","page":"Release notes","title":"v0.9.20 (February 20, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved performance of Utilities.ScalarFunctionIterator\nAdded support for compute_conflict to MOI layers\nAdded test with zero off-diagonal quadratic term in objective\nFixed double deletion of nested bridged SingleVariable/VectorOfVariables constraints\nFixed modification of un-set objective\nFixed function modification with duplicate terms\nMade unit tests abort without failing if the problem class is not supported\nFormatted code with JuliaFormatter\nClarified BasisStatusCode's docstring","category":"page"},{"location":"release_notes/#[v0.9.19](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.19)-(December-1,-2020)","page":"Release notes","title":"v0.9.19 (December 1, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added CallbackNodeStatus attribute\nAdded bridge from GreaterThan or LessThan to Interval\nAdded tests for infeasibility certificates and double optimize\nFixed support for Julia v1.6\nRe-organized MOI docs and added documentation for adding a test","category":"page"},{"location":"release_notes/#[v0.9.18](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.18)-(November-3,-2020)","page":"Release notes","title":"v0.9.18 (November 3, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Various improvements for working with complex numbers\nAdded GeoMeantoRelEntrBridge to bridge a GeometricMeanCone constraint to a relative entropy constraint","category":"page"},{"location":"release_notes/#[v0.9.17](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.17)-(September-21,-2020)","page":"Release notes","title":"v0.9.17 (September 21, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed CleverDict with variable of negative index value\nImplement supports_add_constrained_variable for MockOptimizer","category":"page"},{"location":"release_notes/#[v0.9.16](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.16)-(September-17,-2020)","page":"Release notes","title":"v0.9.16 (September 17, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Various fixes:\n32-bit support\nCleverDict with abstract value type\nChecks in test suite","category":"page"},{"location":"release_notes/#[v0.9.15](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.15)-(September-14,-2020)","page":"Release notes","title":"v0.9.15 (September 14, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Bridges improvements:\n(R)SOCtoNonConvexQuad bridge\nZeroOne bridge\nUse supports_add_constrained_variable in LazyBridgeOptimizer\nExposed VariableBridgeCost and ConstraintBridgeCost attributes\nPrioritize constraining variables on creation according to these costs\nRefactor bridge debugging\nLarge performance improvements across all submodules\nLots of documentation improvements\nFileFormats improvements:\nUpdate MathOptFormat to v0.5\nFix supported objectives in FileFormats\nTesting improvements:\nAdd name option for basic_constraint_test\nBug fixes and missing methods\nAdd length for iterators\nFix bug with duplicate terms\nFix order of LinearOfConstraintIndices","category":"page"},{"location":"release_notes/#[v0.9.14](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.14)-(May-30,-2020)","page":"Release notes","title":"v0.9.14 (May 30, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add a solver-independent interface for accessing the set of conflicting constraints an Irreducible Inconsistent Subsystem (#1056).\nBump JSONSchema dependency from v0.2 to v0.3 (#1090).\nDocumentation improvements:\nFix typos (#1054, #1060, #1061, #1064, #1069, #1070).\nRemove the outdated recommendation for a package implementing MOI for a solver XXX to be called MathOptInterfaceXXX (#1087).\nUtilities improvements:\nFix is_canonical for quadratic functions (#1081, #1089).\nImplement add_constrained_variable[s] for CachingOptimizer so that it is added as constrained variables to the underlying optimizer (#1084).\nAdd support for custom objective functions for UniversalFallback (#1086).\nDeterministic ordering of constraints in UniversalFallback (#1088).\nTesting improvements:\nAdd NormOneCone/NormInfinityCone tests (#1045).\nBridges improvements:\nAdd bridges from Semiinteger and Semicontinuous (#1059).\nImplement getting ConstraintSet for Variable.FlipSignBridge (#1066).\nFix setting ConstraintFunction for Constraint.ScalarizeBridge (#1093).\nFix NormOne/NormInf bridges with nonzero constants (#1045).\nFix StackOverflow in debug (#1063).\nFileFormats improvements:\n[SDPA] Implement the extension for integer variables (#1079).\n[SDPA] Ignore comments after m and nblocks and detect dat-s extension (#1077).\n[SDPA] No scaling of off-diagonal coefficient (#1076).\n[SDPA] Add missing negation of constant (#1075).","category":"page"},{"location":"release_notes/#[v0.9.13](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.13)-(March-24,-2020)","page":"Release notes","title":"v0.9.13 (March 24, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added tests for Semicontinuous and Semiinteger variables (#1033).\nAdded tests for using ExprGraphs from NLP evaluators (#1043).\nUpdate version compatibilities of dependencies (#1034, #1051, #1052).\nFixed typos in documentation (#1044).","category":"page"},{"location":"release_notes/#[v0.9.12](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.12)-(February-28,-2020)","page":"Release notes","title":"v0.9.12 (February 28, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed writing NLPBlock in MathOptFormat (#1037).\nFixed MockOptimizer for result attributes with non-one result index (#1039).\nUpdated test template with instantiate (#1032).","category":"page"},{"location":"release_notes/#[v0.9.11](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.11)-(February-21,-2020)","page":"Release notes","title":"v0.9.11 (February 21, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add an option for the model created by Utilities.@model to be a subtype of AbstractOptimizer (#1031).\nDescribed dual cone in docstrings of GeoMeanCone and RelativeEntropyCone (#1018, #1028).\nFixed typos in documentation (#1022, #1024).\nFixed warning of unsupported attribute (#1027).\nAdded more rootdet/logdet conic tests (#1026).\nImplemented ConstraintDual for Constraint.GeoMeanBridge, Constraint.RootDetBridge and Constraint.LogDetBridge and test duals in tests with GeoMeanCone and RootDetConeTriangle and LogDetConeTriangle cones (#1025, #1026).","category":"page"},{"location":"release_notes/#[v0.9.10](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.10)-(January-31,-2020)","page":"Release notes","title":"v0.9.10 (January 31, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added OptimizerWithAttributes grouping an optimizer constructor and a list of optimizer attributes (#1008).\nAdded RelativeEntropyCone with corresponding bridge into exponential cone constraints (#993).\nAdded NormSpectralCone and NormNuclearCone with corresponding bridges into positive semidefinite constraints (#976).\nAdded supports_constrained_variable(s) (#1004).\nAdded dual_set_type (#1002).\nAdded tests for vector specialized version of delete (#989, #1011).\nAdded PSD3 test (#1007).\nClarified dual solution of Tests.pow1v and Tests.pow1f (#1013).\nAdded support for EqualTo and Zero in Bridges.Constraint.SplitIntervalBridge (#1005).\nFixed Utilities.vectorize for empty vector (#1003).\nFixed free variables in LP writer (#1006).","category":"page"},{"location":"release_notes/#[v0.9.9](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.9)-(December-29,-2019)","page":"Release notes","title":"v0.9.9 (December 29, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Incorporated MathOptFormat.jl as the FileFormats submodule. FileFormats provides readers and writers for a number of standard file formats and MOF, a file format specialized for MOI (#969).\nImproved performance of deletion of vector of variables in MOI.Utilities.Model (#983).\nUpdated to MutableArithmetics v0.2 (#981).\nAdded MutableArithmetics.promote_operation allocation tests (#975).\nFixed inference issue on Julia v1.1 (#982).","category":"page"},{"location":"release_notes/#[v0.9.8](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.8)-(December-19,-2019)","page":"Release notes","title":"v0.9.8 (December 19, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Implemented MutableArithmetics API (#924).\nFixed callbacks with CachingOptimizer (#959).\nFixed MOI.dimension for MOI.Complements (#948).\nAdded fallback for add_variables (#972).\nAdded is_diagonal_vectorized_index utility (#965).\nImproved linear constraints display in manual (#963, #964).\nBridges improvements:\nAdded IndicatorSet to SOS1 bridge (#877).\nAdded support for starting values for Variable.VectorizeBridge (#944).\nFixed MOI.add_constraints with non-bridged variable constraint on bridged variable (#951).\nFixed corner cases and docstring of GeoMeanBridge (#961, #962, #966).\nFixed choice between variable or constraint bridges for constrained variables (#973).\nImprove performance of bridge shortest path (#945, #946, #956).\nAdded docstring for test_delete_bridge (#954).\nAdded Variable bridge tests (#952).","category":"page"},{"location":"release_notes/#[v0.9.7](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.7)-(October-30,-2019)","page":"Release notes","title":"v0.9.7 (October 30, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Implemented _result_index_field for NLPBlockDual (#934).\nFixed copy of model with starting values for vector constraints (#941).\nBridges improvements:\nImproved performance of add_bridge and added has_bridge (#935).\nAdded AbstractSetMapBridge for bridges between sets S1, S2 such that there is a linear map A such that A*S1 = S2 (#933).\nAdded support for starting values for FlipSignBridge, VectorizeBridge, ScalarizeBridge, SlackBridge, SplitIntervalBridge, RSOCBridge, SOCRBridge NormInfinityBridge, SOCtoPSDBridge and RSOCtoPSDBridge (#933, #936, #937, #938, #939).","category":"page"},{"location":"release_notes/#[v0.9.6](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.6)-(October-25,-2019)","page":"Release notes","title":"v0.9.6 (October 25, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added complementarity constraints (#913).\nAllowed ModelLike objects as value of attributes (#928).\nTesting improvements:\nAdded dual_objective_value option to MOI.Test.TestConfig (#922).\nAdded InvalidIndex tests in basic_constraint_tests (#921).\nAdded tests for the constant term in indicator constraint (#929).\nBridges improvements:\nAdded support for starting values for Functionize bridges (#923).\nAdded variable indices context to variable bridges (#920).\nFixed a typo in printing o debug_supports (#927).","category":"page"},{"location":"release_notes/#[v0.9.5](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.5)-(October-9,-2019)","page":"Release notes","title":"v0.9.5 (October 9, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Clarified PrimalStatus/DualStatus to be NO_SOLUTION if result_index is out of bounds (#912).\nAdded tolerance for checks and use ResultCount + 1 for the result_index in MOI.Test.solve_result_status (#910, #917).\nUse 0.5 instead of 2.0 for power in PowerCone in basic_constraint_test (#916).\nBridges improvements:\nAdded debug utilities for unsupported variable/constraint/objective (#861).\nFixed deletion of variables in bridged VectorOfVariables constraints (#909).\nFixed result_index with objective bridges (#911).","category":"page"},{"location":"release_notes/#[v0.9.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.4)-(October-2,-2019)","page":"Release notes","title":"v0.9.4 (October 2, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added solver-independent MIP callbacks (#782).\nImplements submit for Utilities.CachingOptimizer and Bridges.AbstractBridgeOptimizer (#906).\nAdded tests for result count of solution attributes (#901, #904).\nAdded NumberOfThreads attribute (#892).\nAdded Utilities.get_bounds to get the bounds on a variable (#890).\nAdded a note on duplicate coefficients in documentation (#581).\nAdded result index in ConstraintBasisStatus (#898).\nAdded extension dictionary to Utilities.Model (#884, #895).\nFixed deletion of constrained variables for CachingOptimizer (#905).\nImplemented Utilities.shift_constraint for Test.UnknownScalarSet (#896).\nBridges improvements:\nAdded Variable.RSOCtoSOCBridge (#907).\nImplemented MOI.get for ConstraintFunction/ConstraintSet for Bridges.Constraint.SquareBridge (#899).","category":"page"},{"location":"release_notes/#[v0.9.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.3)-(September-20,-2019)","page":"Release notes","title":"v0.9.3 (September 20, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed ambiguity detected in Julia v1.3 (#891, #893).\nFixed missing sets from ListOfSupportedConstraints (#880).\nFixed copy of VectorOfVariables constraints with duplicate indices (#886).\nAdded extension dictionary to MOIU.Model (#884).\nImplemented MOI.get for function and set for GeoMeanBridge (#888).\nUpdated documentation for SingleVariable indices and bridges (#885).\nTesting improvements:\nAdded more comprehensive tests for names (#882).\nAdded tests for SingleVariable duals (#883).\nAdded tests for DualExponentialCone and DualPowerCone (#873).\nImprovements for arbitrary coefficient type:\nFixed == for sets with mutable fields (#887).\nRemoved some Float64 assumptions in bridges (#878).\nAutomatic selection of Constraint.[Scalar|Vector]FunctionizeBridge (#889).","category":"page"},{"location":"release_notes/#[v0.9.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.2)-(September-5,-2019)","page":"Release notes","title":"v0.9.2 (September 5, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Implemented model printing for MOI.ModelLike and specialized it for models defined in MOI (864).\nGeneralized contlinear tests for arbitrary coefficient type (#855).\nFixed supports_constraint for Semiinteger and Semicontinuous and supports for ObjectiveFunction (#859).\nFixed Allocate-Load copy for single variable constraints (#856).\nBridges improvements:\nAdd objective bridges (#789).\nFixed Variable.RSOCtoPSDBridge for dimension 2 (#869).\nAdded Variable.SOCtoRSOCBridge (#865).\nAdded Constraint.SOCRBridge and disable MOI.Bridges.Constraint.SOCtoPSDBridge (#751).\nFixed added_constraint_types for Contraint.LogDetBridge and Constraint.RootDetBridge (#870).","category":"page"},{"location":"release_notes/#[v0.9.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.1)-(August-22,-2019)","page":"Release notes","title":"v0.9.1 (August 22, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix support for Julia v1.2 (#834).\nL1 and L∞ norm epigraph cones and corresponding bridges to LP were added (#818).\nAdded tests to MOI.Test.nametest (#833).\nFix MOI.Test.soc3test for solvers not supporting infeasibility certificates (#839).\nImplements operate for operators * and / between vector function and constant (#837).\nImplements show for MOI.Utilities.IndexMap (#847).\nFix corner cases for mapping of variables in MOI.Utilities.CachingOptimizer and substitution of variables in MOI.Bridges.AbstractBridgeOptimizer (#848).\nFix transformation of constant terms for MOI.Bridges.Constraint.SOCtoPSDBridge and MOI.Bridges.Constraint.RSOCtoPSDBridge (#840).","category":"page"},{"location":"release_notes/#[v0.9.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.0)-(August-13,-2019)","page":"Release notes","title":"v0.9.0 (August 13, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Support for Julia v0.6 and v0.7 was dropped (#714, #717).\nA MOI.Utilities.Model implementation of ModelLike, this should replace most use cases of MOI.Utilities.@model (#781).\nadd_constrained_variable and add_constrained_variables were added (#759).\nSupport for indicator constraints was added (#709, #712).\nDualObjectiveValue attribute was added (#473).\nRawParameter attribute was added (#733).\nA dual_set function was added (#804).\nA Benchmarks submodule was added to facilitate solver benchmarking (#769).\nA submit function was added, this may for instance allow the user to submit solutions or cuts to the solver from a callback (#775).\nThe field of ObjectiveValue was renamed to result_index (#729).\nThe _constant and Utilities.getconstant function were renamed to constant\nREDUCTION_CERTIFICATE result status was added (#734).\nAbstract matrix sets were added (#731).\nTesting improvements:\nThe testing guideline was updated (#728).\nQuadratic tests were added (#697).\nUnit tests for RawStatusString, SolveTime, Silent and SolverName were added (#726, #741).\nA rotated second-order cone test was added (#759).\nA power cone test was added (#768).\nTests for ZeroOne variables with variable bounds were added (#772).\nAn unbounded test was added (#773).\nExisting tests had a few updates (#702, #703, #763).\nDocumentation improvements:\nAdded a section on CachingOptimizer (#777).\nAdded a section on UniversalFallback, Model and @model (#762).\nTransition the knapsack example to a doctest with MockOptimizer (#786).\nUtilities improvements:\nA CleverDict utility was added for a vector that automatically transform into a dictionary once a first index is removed (#767).\nThe Utilities.constant function was renamed to Utilities.constant_vector (#740).\nImplement optimizer attributes for CachingOptimizer (#745).\nRename Utilities.add_scalar_constraint to Utilities.normalize_and_add_constraint (#801).\noperate with vcat, SingleVariable and VectorOfVariables now returns a VectorOfVariables (#616).\nFix a type piracy of operate (#784).\nThe load_constraint fallback signature was fixed (#760).\nThe set_dot function was extended to work with sparse arrays (#805).\nBridges improvements:\nThe bridges no longer store the constraint function and set before it is bridged, the bridges now have to implement ConstraintFunction and ConstraintSet if the user wants to recover them. As a consequence, the @bridge macro was removed (#722).\nBridge are now instantiated with a bridge_constraint function instead of using a constructor (#730).\nFix constraint attributes for bridges (#699).\nConstraint bridges were moved to the Bridges/Constraint submodule so they should now inherit from MOI.Bridges.Constraint.Abstract and should implement MOI.Bridges.Constraint.concrete_bridge_type instead of MOI.Bridges.concrete_bridge_type (#756).\nVariable bridges were added in (#759).\nVarious improvements (#746, #747).","category":"page"},{"location":"release_notes/#[v0.8.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.4)-(March-13,-2019)","page":"Release notes","title":"v0.8.4 (March 13, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Performance improvement in default_copy_to and bridge optimizer (#696).\nAdd Silent and implement setting optimizer attributes in caching and mock optimizers (#695).\nAdd Functionize bridges (SingleVariable and VectorOfVariables) (#659).\nMinor typo fixes (#694).","category":"page"},{"location":"release_notes/#[v0.8.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.3)-(March-6,-2019)","page":"Release notes","title":"v0.8.3 (March 6, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Use zero constant in scalar constraint function of MOI.Test.copytest (#691).\nFix variable deletion with SingleVariable objective function (#690).\nFix LazyBridgeOptimizer with bridges that add no constraints (#689).\nError message improvements (#673, #685, #686, #688).\nDocumentation improvements (#682, #683, #687).\nBasis status:\nRemove VariableBasisStatus (#679).\nTest ConstraintBasisStatus and implement it in bridges (#678).\nFix inference of NumberOfVariables and NumberOfConstraints (#677).\nImplement division between a quadratic function and a number (#675).","category":"page"},{"location":"release_notes/#[v0.8.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.2)-(February-7,-2019)","page":"Release notes","title":"v0.8.2 (February 7, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add RawStatusString attribute (#629).\nDo not set names to the optimizer but only to the cache in CachingOptimizer (#638).\nMake scalar MOI functions act as scalars in broadcast (#646).\nAdd function utilities:\nImplement Base.zero (#634), Base.iszero (#643), add missing arithmetic operations (#644, #645) and fix division (#648).\nAdd a vectorize function that turns a vector of ScalarAffineFunction into a VectorAffineFunction (#642).\nImprove support for starting values:\nShow a warning in copy when starting values are not supported instead of throwing an error (#630).\nFix UniversalFallback for getting an variable or constraint attribute set to no indices (#623).\nAdd a test in contlineartest with partially set VariablePrimalStart.\nBridges improvements:\nFix StackOverFlow in LazyBridgeOptimizer when there is a cycle in the graph of bridges.\nAdd Slack bridges (#610, #650).\nAdd FlipSign bridges (#658).\nAdd tests with duplicate coefficients in ScalarAffineFunction and VectorAffineFunction (#639).\nUse tolerance to compare VariablePrimal in rotatedsoc1 test (#632).\nUse a zero constant in ScalarAffineFunction of constraints in psdt2 (#622).","category":"page"},{"location":"release_notes/#[v0.8.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.1)-(January-7,-2019)","page":"Release notes","title":"v0.8.1 (January 7, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Adding an NLP objective now overrides any objective set using the ObjectiveFunction attribute (#619).\nRename fullbridgeoptimizer into full_bridge_optimizer (#621).\nAllow custom constraint types with full_bridge_optimizer (#617).\nAdd Vectorize bridge which transforms scalar linear constraints into vector linear constraints (#615).","category":"page"},{"location":"release_notes/#[v0.8.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.0)-(December-18,-2018)","page":"Release notes","title":"v0.8.0 (December 18, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Rename all enum values to follow the JuMP naming guidelines for constants, for example, Optimal becomes OPTIMAL, and DualInfeasible becomes DUAL_INFEASIBLE.\nRename CachingOptimizer methods for style compliance.\nAdd an MOI.TerminationStatusCode called ALMOST_DUAL_INFEASIBLE.","category":"page"},{"location":"release_notes/#[v0.7.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.7.0)-(December-13,-2018)","page":"Release notes","title":"v0.7.0 (December 13, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Test that MOI.TerminationStatus is MOI.OptimizeNotCalled before MOI.optimize! is called.\nCheck supports_default_copy_to in tests (#594).\nKey pieces of information like optimality, infeasibility, etc., are now reported through TerminationStatusCode. It is typically no longer necessary to check the result statuses in addition to the termination status.\nAdd perspective dimension to log-det cone (#593).","category":"page"},{"location":"release_notes/#[v0.6.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.4)-(November-27,-2018)","page":"Release notes","title":"v0.6.4 (November 27, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add OptimizeNotCalled termination status (#577) and improve documentation of other statuses (#575).\nAdd a solver naming guideline (#578).\nMake FeasibilitySense the default ObjectiveSense (#579).\nFix Utilities.@model and Bridges.@bridge macros for functions and sets defined outside MOI (#582).\nDocument solver-specific attributes (#580) and implement them in Utilities.CachingOptimizer (#565).","category":"page"},{"location":"release_notes/#[v0.6.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.3)-(November-16,-2018)","page":"Release notes","title":"v0.6.3 (November 16, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Variables and constraints are now allowed to have duplicate names. An error is thrown only on lookup. This change breaks some existing tests. (#549)\nAttributes may now be partially set (some values could be nothing). (#563)\nPerformance improvements in Utilities.Model (#549, #567, #568)\nFix bug in QuadtoSOC (#558).\nNew supports_default_copy_to method that optimizers should implement to control caching behavior.\nDocumentation improvements.","category":"page"},{"location":"release_notes/#[v0.6.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.2)-(October-26,-2018)","page":"Release notes","title":"v0.6.2 (October 26, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improve hygiene of @model macro (#544).\nFix bug in copy tests (#543).\nFix bug in UniversalFallback attribute getter (#540).\nAllow all correct solutions for solve_blank_obj unit test (#537).\nAdd errors for Allocate-Load and bad constraints (#534).\n[performance] Add specialized implementation of hash for VariableIndex (#533).\n[performance] Construct the name to object dictionaries lazily in model (#535).\nAdd the QuadtoSOC bridge which transforms ScalarQuadraticFunction constraints into RotatedSecondOrderCone (#483).","category":"page"},{"location":"release_notes/#[v0.6.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.1)-(September-22,-2018)","page":"Release notes","title":"v0.6.1 (September 22, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Enable PositiveSemidefiniteConeSquare set and quadratic functions in MOIB.fullbridgeoptimizer (#524).\nAdd warning in the bridge between PositiveSemidefiniteConeSquare and PositiveSemidefiniteConeTriangle when the matrix is almost symmetric (#522).\nModify MOIT.copytest to not add multiples constraints on the same variable (#521).\nAdd missing keyword argument in one of MOIU.add_scalar_constraint methods (#520).","category":"page"},{"location":"release_notes/#[v0.6.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.0)-(August-30,-2018)","page":"Release notes","title":"v0.6.0 (August 30, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"The MOIU.@model and MOIB.@bridge macros now support functions and sets defined in external modules. As a consequence, function and set names in the macro arguments need to be prefixed by module name.\nRename functions according to the JuMP style guide:\ncopy! with keyword arguments copynames and warnattributes -> copy_to with keyword arguments copy_names and warn_attributes;\nset! -> set;\naddvariable[s]! -> add_variable[s];\nsupportsconstraint -> supports_constraint;\naddconstraint[s]! -> add_constraint[s];\nisvalid -> is_valid;\nisempty -> is_empty;\nBase.delete! -> delete;\nmodify! -> modify;\ntransform! -> transform;\ninitialize! -> initialize;\nwrite -> write_to_file; and\nread! -> read_from_file.\nRemove free! (use Base.finalize instead).\nAdd the SquarePSD bridge which transforms PositiveSemidefiniteConeTriangle constraints into PositiveSemidefiniteConeTriangle.\nAdd result fallback for ConstraintDual of variable-wise constraint, ConstraintPrimal and ObjectiveValue.\nAdd tests for ObjectiveBound.\nAdd test for empty rows in vector linear constraint.\nRework errors: CannotError has been renamed NotAllowedError and the distinction between UnsupportedError and NotAllowedError is now about whether the element is not supported (for example, it cannot be copied a model containing this element) or the operation is not allowed (either because it is not implemented, because it cannot be performed in the current state of the model, or because it cannot be performed for a specific index)\ncanget is removed. NoSolution is added as a result status to indicate that the solver does not have either a primal or dual solution available (See #479).","category":"page"},{"location":"release_notes/#[v0.5.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.5.0)-(August-5,-2018)","page":"Release notes","title":"v0.5.0 (August 5, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix names with CachingOptimizer.\nCleanup thanks to @mohamed82008.\nAdded a universal fallback for constraints.\nFast utilities for function canonicalization thanks to @rdeits.\nRenamed dimension field to side_dimension in the context of matrix-like sets.\nNew and improved tests for cases like duplicate terms and ObjectiveBound.\nRemoved cantransform, canaddconstraint, canaddvariable, canset, canmodify, and candelete functions from the API. They are replaced by a new set of errors that are thrown: Subtypes of UnsupportedError indicate unsupported operations, while subtypes of CannotError indicate operations that cannot be performed in the current state.\nThe API for copy! is updated to remove the CopyResult type.\nUpdates for the new JuMP style guide.","category":"page"},{"location":"release_notes/#[v0.4.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.4.1)-(June-28,-2018)","page":"Release notes","title":"v0.4.1 (June 28, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixes vector function modification on 32 bits.\nFixes Bellman-Ford algorithm for bridges.\nAdded an NLP test with FeasibilitySense.\nUpdate modification documentation.","category":"page"},{"location":"release_notes/#[v0.4.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.4.0)-(June-23,-2018)","page":"Release notes","title":"v0.4.0 (June 23, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Helper constructors for VectorAffineTerm and VectorQuadraticTerm.\nAdded modify_lhs to TestConfig.\nAdditional unit tests for optimizers.\nAdded a type parameter to CachingOptimizer for the optimizer field.\nNew API for problem modification (#388)\nTests pass without deprecation warnings on Julia 0.7.\nSmall fixes and documentation updates.","category":"page"},{"location":"release_notes/#[v0.3.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.3.0)-(May-25,-2018)","page":"Release notes","title":"v0.3.0 (May 25, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Functions have been redefined to use arrays-of-structs instead of structs-of-arrays.\nImprovements to MockOptimizer.\nSignificant changes to Bridges.\nNew and improved unit tests.\nFixes for Julia 0.7.","category":"page"},{"location":"release_notes/#[v0.2.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.2.0)-(April-24,-2018)","page":"Release notes","title":"v0.2.0 (April 24, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improvements to and better coverage of Tests.\nDocumentation fixes.\nSolverName attribute.\nChanges to the NLP interface (new definition of variable order and arrays of structs for bound pairs and sparsity patterns).\nAddition of NLP tests.\nIntroduction of UniversalFallback.\ncopynames keyword argument to MOI.copy!.\nAdd Bridges submodule.","category":"page"},{"location":"release_notes/#[v0.1.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.1.0)-(February-28,-2018)","page":"Release notes","title":"v0.1.0 (February 28, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Initial public release.\nThe framework for MOI was developed at the JuMP-dev workshop at MIT in June 2017 as a sorely needed replacement for MathProgBase.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/constraints/#Constraints","page":"Constraints","title":"Constraints","text":"","category":"section"},{"location":"manual/constraints/#Add-a-constraint","page":"Constraints","title":"Add a constraint","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Use add_constraint to add a single constraint.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> c = MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(2))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"add_constraint returns a ConstraintIndex type, which is used to refer to the added constraint in other calls.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Check if a ConstraintIndex is valid using is_valid.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> MOI.is_valid(model, c)\ntrue","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Use add_constraints to add a number of constraints of the same type.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> c = MOI.add_constraints(\n model,\n [x[1], x[2]],\n [MOI.GreaterThan(0.0), MOI.GreaterThan(1.0)]\n )\n2-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(2)","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"This time, a vector of ConstraintIndex are returned.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Use supports_constraint to check if the model supports adding a constraint type.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> MOI.supports_constraint(\n model,\n MOI.VariableIndex,\n MOI.GreaterThan{Float64},\n )\ntrue","category":"page"},{"location":"manual/constraints/#Delete-a-constraint","page":"Constraints","title":"Delete a constraint","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Use delete to delete a constraint.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> MOI.delete(model, c)\n\njulia> MOI.is_valid(model, c)\nfalse","category":"page"},{"location":"manual/constraints/#Constraint-attributes","page":"Constraints","title":"Constraint attributes","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"The following attributes are available for constraints:","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"ConstraintName\nConstraintPrimalStart\nConstraintDualStart\nConstraintPrimal\nConstraintDual\nConstraintBasisStatus\nConstraintFunction\nCanonicalConstraintFunction\nConstraintSet","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Get and set these attributes using get and set.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> MOI.set(model, MOI.ConstraintName(), c, \"con_c\")\n\njulia> MOI.get(model, MOI.ConstraintName(), c)\n\"con_c\"","category":"page"},{"location":"manual/constraints/#Constraints-by-function-set-pairs","page":"Constraints","title":"Constraints by function-set pairs","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Below is a list of common constraint types and how they are represented as function-set pairs in MOI. In the notation below, x is a vector of decision variables, x_i is a scalar decision variable, alpha beta are scalar constants, a b are constant vectors, A is a constant matrix and mathbbR_+ (resp. mathbbR_-) is the set of non-negative (resp. non-positive) real numbers.","category":"page"},{"location":"manual/constraints/#Linear-constraints","page":"Constraints","title":"Linear constraints","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Mathematical Constraint MOI Function MOI Set\na^Tx le beta ScalarAffineFunction LessThan\na^Tx ge alpha ScalarAffineFunction GreaterThan\na^Tx = beta ScalarAffineFunction EqualTo\nalpha le a^Tx le beta ScalarAffineFunction Interval\nx_i le beta VariableIndex LessThan\nx_i ge alpha VariableIndex GreaterThan\nx_i = beta VariableIndex EqualTo\nalpha le x_i le beta VariableIndex Interval\nAx + b in mathbbR_+^n VectorAffineFunction Nonnegatives\nAx + b in mathbbR_-^n VectorAffineFunction Nonpositives\nAx + b = 0 VectorAffineFunction Zeros","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"By convention, solvers are not expected to support nonzero constant terms in the ScalarAffineFunctions the first four rows of the preceding table because they are redundant with the parameters of the sets. For example, encode 2x + 1 le 2 as 2x le 1.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Constraints with VariableIndex in LessThan, GreaterThan, EqualTo, or Interval sets have a natural interpretation as variable bounds. As such, it is typically not natural to impose multiple lower- or upper-bounds on the same variable, and the solver interfaces will throw respectively LowerBoundAlreadySet or UpperBoundAlreadySet.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Moreover, adding two VariableIndex constraints on the same variable with the same set is impossible because they share the same index as it is the index of the variable, see ConstraintIndex.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"It is natural, however, to impose upper- and lower-bounds separately as two different constraints on a single variable. The difference between imposing bounds by using a single Interval constraint and by using separate LessThan and GreaterThan constraints is that the latter will allow the solver to return separate dual multipliers for the two bounds, while the former will allow the solver to return only a single dual for the interval constraint.","category":"page"},{"location":"manual/constraints/#Conic-constraints","page":"Constraints","title":"Conic constraints","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Mathematical Constraint MOI Function MOI Set\nlVert Ax + brVert_2 le c^Tx + d VectorAffineFunction SecondOrderCone\ny ge lVert x rVert_2 VectorOfVariables SecondOrderCone\n2yz ge lVert x rVert_2^2 yz ge 0 VectorOfVariables RotatedSecondOrderCone\n(a_1^Tx + b_1a_2^Tx + b_2a_3^Tx + b_3) in mathcalE VectorAffineFunction ExponentialCone\nA(x) in mathcalS_+ VectorAffineFunction PositiveSemidefiniteConeTriangle\nB(x) in mathcalS_+ VectorAffineFunction PositiveSemidefiniteConeSquare\nx in mathcalS_+ VectorOfVariables PositiveSemidefiniteConeTriangle\nx in mathcalS_+ VectorOfVariables PositiveSemidefiniteConeSquare","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"where mathcalE is the exponential cone (see ExponentialCone), mathcalS_+ is the set of positive semidefinite symmetric matrices, A is an affine map that outputs symmetric matrices and B is an affine map that outputs square matrices.","category":"page"},{"location":"manual/constraints/#Quadratic-constraints","page":"Constraints","title":"Quadratic constraints","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Mathematical Constraint MOI Function MOI Set\nfrac12x^TQx + a^Tx + b ge 0 ScalarQuadraticFunction GreaterThan\nfrac12x^TQx + a^Tx + b le 0 ScalarQuadraticFunction LessThan\nfrac12x^TQx + a^Tx + b = 0 ScalarQuadraticFunction EqualTo\nBilinear matrix inequality VectorQuadraticFunction PositiveSemidefiniteCone...","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"note: Note\nFor more details on the internal format of the quadratic functions see ScalarQuadraticFunction or VectorQuadraticFunction.","category":"page"},{"location":"manual/constraints/#Discrete-and-logical-constraints","page":"Constraints","title":"Discrete and logical constraints","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Mathematical Constraint MOI Function MOI Set\nx_i in mathbbZ VariableIndex Integer\nx_i in 01 VariableIndex ZeroOne\nx_i in 0 cup lu VariableIndex Semicontinuous\nx_i in 0 cup ll+1ldotsu-1u VariableIndex Semiinteger\nAt most one component of x can be nonzero VectorOfVariables SOS1\nAt most two components of x can be nonzero, and if so they must be adjacent components VectorOfVariables SOS2\ny = 1 implies a^T x in S VectorAffineFunction Indicator","category":"page"},{"location":"manual/constraints/#JuMP-mapping","page":"Constraints","title":"JuMP mapping","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"The following bullet points show examples of how JuMP constraints are translated into MOI function-set pairs:","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"@constraint(m, 2x + y <= 10) becomes ScalarAffineFunction-in-LessThan\n@constraint(m, 2x + y >= 10) becomes ScalarAffineFunction-in-GreaterThan\n@constraint(m, 2x + y == 10) becomes ScalarAffineFunction-in-EqualTo\n@constraint(m, 0 <= 2x + y <= 10) becomes ScalarAffineFunction-in-Interval\n@constraint(m, 2x + y in ArbitrarySet()) becomes ScalarAffineFunction-in-ArbitrarySet.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Variable bounds are handled in a similar fashion:","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"@variable(m, x <= 1) becomes VariableIndex-in-LessThan\n@variable(m, x >= 1) becomes VariableIndex-in-GreaterThan","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"One notable difference is that a variable with an upper and lower bound is translated into two constraints, rather than an interval, that is:","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"@variable(m, 0 <= x <= 1) becomes VariableIndex-in-LessThan and VariableIndex-in-GreaterThan.","category":"page"},{"location":"reference/nonlinear/","page":"Nonlinear programming","title":"Nonlinear programming","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/nonlinear/#Nonlinear-programming","page":"Nonlinear programming","title":"Nonlinear programming","text":"","category":"section"},{"location":"reference/nonlinear/#Types","page":"Nonlinear programming","title":"Types","text":"","category":"section"},{"location":"reference/nonlinear/","page":"Nonlinear programming","title":"Nonlinear programming","text":"AbstractNLPEvaluator\nNLPBoundsPair\nNLPBlockData","category":"page"},{"location":"reference/nonlinear/#MathOptInterface.AbstractNLPEvaluator","page":"Nonlinear programming","title":"MathOptInterface.AbstractNLPEvaluator","text":"AbstractNLPEvaluator\n\nAbstract supertype for the callback object that is used to query function values, derivatives, and expression graphs.\n\nIt is used in NLPBlockData.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#MathOptInterface.NLPBoundsPair","page":"Nonlinear programming","title":"MathOptInterface.NLPBoundsPair","text":"NLPBoundsPair(lower::Float64, upper::Float64)\n\nA struct holding a pair of lower and upper bounds.\n\n-Inf and Inf can be used to indicate no lower or upper bound, respectively.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#MathOptInterface.NLPBlockData","page":"Nonlinear programming","title":"MathOptInterface.NLPBlockData","text":"struct NLPBlockData\n constraint_bounds::Vector{NLPBoundsPair}\n evaluator::AbstractNLPEvaluator\n has_objective::Bool\nend\n\nA struct encoding a set of nonlinear constraints of the form lb le g(x) le ub and, if has_objective == true, a nonlinear objective function f(x).\n\nNonlinear objectives override any objective set by using the ObjectiveFunction attribute.\n\nThe evaluator is a callback object that is used to query function values, derivatives, and expression graphs. If has_objective == false, then it is an error to query properties of the objective function, and in Hessian-of-the-Lagrangian queries, σ must be set to zero.\n\nnote: Note\nThroughout the evaluator, all variables are ordered according to ListOfVariableIndices. Hence, MOI copies of nonlinear problems must not re-order variables.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#Attributes","page":"Nonlinear programming","title":"Attributes","text":"","category":"section"},{"location":"reference/nonlinear/","page":"Nonlinear programming","title":"Nonlinear programming","text":"NLPBlock\nNLPBlockDual\nNLPBlockDualStart","category":"page"},{"location":"reference/nonlinear/#MathOptInterface.NLPBlock","page":"Nonlinear programming","title":"MathOptInterface.NLPBlock","text":"NLPBlock()\n\nAn AbstractModelAttribute that stores an NLPBlockData, representing a set of nonlinear constraints, and optionally a nonlinear objective.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#MathOptInterface.NLPBlockDual","page":"Nonlinear programming","title":"MathOptInterface.NLPBlockDual","text":"NLPBlockDual(result_index::Int = 1)\n\nAn AbstractModelAttribute for the Lagrange multipliers on the constraints from the NLPBlock in result result_index.\n\nIf result_index is omitted, it is 1 by default.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#MathOptInterface.NLPBlockDualStart","page":"Nonlinear programming","title":"MathOptInterface.NLPBlockDualStart","text":"NLPBlockDualStart()\n\nAn AbstractModelAttribute for the initial assignment of the Lagrange multipliers on the constraints from the NLPBlock that the solver may use to warm-start the solve.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#Functions","page":"Nonlinear programming","title":"Functions","text":"","category":"section"},{"location":"reference/nonlinear/","page":"Nonlinear programming","title":"Nonlinear programming","text":"initialize\nfeatures_available\neval_objective\neval_constraint\neval_objective_gradient\njacobian_structure\neval_constraint_gradient\nconstraint_gradient_structure\neval_constraint_jacobian\neval_constraint_jacobian_product\neval_constraint_jacobian_transpose_product\nhessian_lagrangian_structure\nhessian_objective_structure\nhessian_constraint_structure\neval_hessian_objective\neval_hessian_constraint\neval_hessian_lagrangian\neval_hessian_lagrangian_product\nobjective_expr\nconstraint_expr","category":"page"},{"location":"reference/nonlinear/#MathOptInterface.initialize","page":"Nonlinear programming","title":"MathOptInterface.initialize","text":"initialize(\n d::AbstractNLPEvaluator,\n requested_features::Vector{Symbol},\n)::Nothing\n\nInitialize d with the set of features in requested_features. Check features_available before calling initialize to see what features are supported by d.\n\nwarning: Warning\nThis method must be called before any other methods.\n\nFeatures\n\nThe following features are defined:\n\n:Grad: enables eval_objective_gradient\n:Jac: enables eval_constraint_jacobian\n:JacVec: enables eval_constraint_jacobian_product and eval_constraint_jacobian_transpose_product\n:Hess: enables eval_hessian_lagrangian\n:HessVec: enables eval_hessian_lagrangian_product\n:ExprGraph: enables objective_expr and constraint_expr.\n\nIn all cases, including when requested_features is empty, eval_objective and eval_constraint are supported.\n\nExamples\n\nMOI.initialize(d, Symbol[])\nMOI.initialize(d, [:ExprGraph])\nMOI.initialize(d, MOI.features_available(d))\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.features_available","page":"Nonlinear programming","title":"MathOptInterface.features_available","text":"features_available(d::AbstractNLPEvaluator)::Vector{Symbol}\n\nReturns the subset of features available for this problem instance.\n\nSee initialize for the list of defined features.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_objective","page":"Nonlinear programming","title":"MathOptInterface.eval_objective","text":"eval_objective(d::AbstractNLPEvaluator, x::AbstractVector{T})::T where {T}\n\nEvaluate the objective f(x), returning a scalar value.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint","text":"eval_constraint(d::AbstractNLPEvaluator,\n g::AbstractVector{T},\n x::AbstractVector{T},\n)::Nothing where {T}\n\nGiven a set of vector-valued constraints l le g(x) le u, evaluate the constraint function g(x), storing the result in the vector g.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that g is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_objective_gradient","page":"Nonlinear programming","title":"MathOptInterface.eval_objective_gradient","text":"eval_objective_gradient(\n d::AbstractNLPEvaluator,\n grad::AbstractVector{T},\n x::AbstractVector{T},\n)::Nothing where {T}\n\nEvaluate the gradient of the objective function grad = nabla f(x) as a dense vector, storing the result in the vector grad.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that grad is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.jacobian_structure","page":"Nonlinear programming","title":"MathOptInterface.jacobian_structure","text":"jacobian_structure(d::AbstractNLPEvaluator)::Vector{Tuple{Int64,Int64}}\n\nReturns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Jacobian matrix: J_g(x) = left beginarrayc nabla g_1(x) nabla g_2(x) vdots nabla g_m(x) endarrayright where g_i is the itextth component of the nonlinear constraints g(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint_gradient","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint_gradient","text":"eval_constraint_gradient(\n d::AbstractNLPEvaluator,\n ∇g::AbstractVector{T},\n x::AbstractVector{T},\n i::Int,\n)::Nothing where {T}\n\nEvaluate the gradient of constraint i, nabla g_i(x), and store the non-zero values in ∇g, corresponding to the structure returned by constraint_gradient_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that ∇g is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.constraint_gradient_structure","page":"Nonlinear programming","title":"MathOptInterface.constraint_gradient_structure","text":"constraint_gradient_structure(d::AbstractNLPEvaluator, i::Int)::Vector{Int64}\n\nReturns a vector of indices, where each element indicates the position of a structurally nonzero element in the gradient of constraint nabla g_i(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint_jacobian","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint_jacobian","text":"eval_constraint_jacobian(d::AbstractNLPEvaluator,\n J::AbstractVector{T},\n x::AbstractVector{T},\n)::Nothing where {T}\n\nEvaluates the sparse Jacobian matrix J_g(x) = left beginarrayc nabla g_1(x) nabla g_2(x) vdots nabla g_m(x) endarrayright.\n\nThe result is stored in the vector J in the same order as the indices returned by jacobian_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that J is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint_jacobian_product","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint_jacobian_product","text":"eval_constraint_jacobian_product(\n d::AbstractNLPEvaluator,\n y::AbstractVector{T},\n x::AbstractVector{T},\n w::AbstractVector{T},\n)::Nothing where {T}\n\nComputes the Jacobian-vector product y = J_g(x)w, storing the result in the vector y.\n\nThe vectors have dimensions such that length(w) == length(x), and length(y) is the number of nonlinear constraints.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that y is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint_jacobian_transpose_product","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint_jacobian_transpose_product","text":"eval_constraint_jacobian_transpose_product(\n d::AbstractNLPEvaluator,\n y::AbstractVector{T},\n x::AbstractVector{T},\n w::AbstractVector{T},\n)::Nothing where {T}\n\nComputes the Jacobian-transpose-vector product y = J_g(x)^Tw, storing the result in the vector y.\n\nThe vectors have dimensions such that length(y) == length(x), and length(w) is the number of nonlinear constraints.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that y is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.hessian_lagrangian_structure","page":"Nonlinear programming","title":"MathOptInterface.hessian_lagrangian_structure","text":"hessian_lagrangian_structure(\n d::AbstractNLPEvaluator,\n)::Vector{Tuple{Int64,Int64}}\n\nReturns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian-of-the-Lagrangian matrix: nabla^2 f(x) + sum_i=1^m nabla^2 g_i(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nAny mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.hessian_objective_structure","page":"Nonlinear programming","title":"MathOptInterface.hessian_objective_structure","text":"hessian_objective_structure(\n d::AbstractNLPEvaluator,\n)::Vector{Tuple{Int64,Int64}}\n\nReturns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian matrix: nabla^2 f(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nAny mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.hessian_constraint_structure","page":"Nonlinear programming","title":"MathOptInterface.hessian_constraint_structure","text":"hessian_constraint_structure(\n d::AbstractNLPEvaluator,\n i::Int64,\n)::Vector{Tuple{Int64,Int64}}\n\nReturns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian matrix: nabla^2 g_i(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nAny mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_hessian_objective","page":"Nonlinear programming","title":"MathOptInterface.eval_hessian_objective","text":"eval_hessian_objective(\n d::AbstractNLPEvaluator,\n H::AbstractVector{T},\n x::AbstractVector{T},\n)::Nothing where {T}\n\nThis function computes the sparse Hessian matrix: nabla^2 f(x), storing the result in the vector H in the same order as the indices returned by hessian_objective_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_hessian_constraint","page":"Nonlinear programming","title":"MathOptInterface.eval_hessian_constraint","text":"eval_hessian_constraint(\n d::AbstractNLPEvaluator,\n H::AbstractVector{T},\n x::AbstractVector{T},\n i::Int64,\n)::Nothing where {T}\n\nThis function computes the sparse Hessian matrix: nabla^2 g_i(x), storing the result in the vector H in the same order as the indices returned by hessian_constraint_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_hessian_lagrangian","page":"Nonlinear programming","title":"MathOptInterface.eval_hessian_lagrangian","text":"eval_hessian_lagrangian(\n d::AbstractNLPEvaluator,\n H::AbstractVector{T},\n x::AbstractVector{T},\n σ::T,\n μ::AbstractVector{T},\n)::Nothing where {T}\n\nGiven scalar weight σ and vector of constraint weights μ, this function computes the sparse Hessian-of-the-Lagrangian matrix: sigmanabla^2 f(x) + sum_i=1^m mu_i nabla^2 g_i(x), storing the result in the vector H in the same order as the indices returned by hessian_lagrangian_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_hessian_lagrangian_product","page":"Nonlinear programming","title":"MathOptInterface.eval_hessian_lagrangian_product","text":"eval_hessian_lagrangian_product(\n d::AbstractNLPEvaluator,\n h::AbstractVector{T},\n x::AbstractVector{T},\n v::AbstractVector{T},\n σ::T,\n μ::AbstractVector{T},\n)::Nothing where {T}\n\nGiven scalar weight σ and vector of constraint weights μ, computes the Hessian-of-the-Lagrangian-vector product h = left(sigmanabla^2 f(x) + sum_i=1^m mu_i nabla^2 g_i(x)right)v, storing the result in the vector h.\n\nThe vectors have dimensions such that length(h) == length(x) == length(v).\n\nImplementation notes\n\nWhen implementing this method, you must not assume that h is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.objective_expr","page":"Nonlinear programming","title":"MathOptInterface.objective_expr","text":"objective_expr(d::AbstractNLPEvaluator)::Expr\n\nReturns a Julia Expr object representing the expression graph of the objective function.\n\nFormat\n\nThe expression has a number of limitations, compared with arbitrary Julia expressions:\n\nAll sums and products are flattened out as simple Expr(:+, ...) and Expr(:*, ...) objects.\nAll decision variables must be of the form Expr(:ref, :x, MOI.VariableIndex(i)), where i is the ith variable in ListOfVariableIndices.\nThere are currently no restrictions on recognized functions; typically these will be built-in Julia functions like ^, exp, log, cos, tan, sqrt, etc., but modeling interfaces may choose to extend these basic functions, or error if they encounter unsupported functions.\n\nExamples\n\nThe expression x_1+sin(x_2exp(x_3)) is represented as\n\n:(x[MOI.VariableIndex(1)] + sin(x[MOI.VariableIndex(2)] / exp(x[MOI.VariableIndex[3]])))\n\nor equivalently\n\nExpr(\n :call,\n :+,\n Expr(:ref, :x, MOI.VariableIndex(1)),\n Expr(\n :call,\n :/,\n Expr(:call, :sin, Expr(:ref, :x, MOI.VariableIndex(2))),\n Expr(:call, :exp, Expr(:ref, :x, MOI.VariableIndex(3))),\n ),\n)\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.constraint_expr","page":"Nonlinear programming","title":"MathOptInterface.constraint_expr","text":"constraint_expr(d::AbstractNLPEvaluator, i::Integer)::Expr\n\nReturns a Julia Expr object representing the expression graph for the itextth nonlinear constraint.\n\nFormat\n\nThe format is the same as objective_expr, with an additional comparison operator indicating the sense of and bounds on the constraint.\n\nFor single-sided comparisons, the body of the constraint must be on the left-hand side, and the right-hand side must be a constant.\n\nFor double-sided comparisons (that is, l le f(x) le u), the body of the constraint must be in the middle, and the left- and right-hand sides must be constants.\n\nThe bounds on the constraints must match the NLPBoundsPairs passed to NLPBlockData.\n\nExamples\n\n:(x[MOI.VariableIndex(1)]^2 <= 1.0)\n:(x[MOI.VariableIndex(1)]^2 >= 2.0)\n:(x[MOI.VariableIndex(1)]^2 == 3.0)\n:(4.0 <= x[MOI.VariableIndex(1)]^2 <= 5.0)\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/standard_form/#Standard-form","page":"Standard form","title":"Standard form","text":"","category":"section"},{"location":"reference/standard_form/#Functions","page":"Standard form","title":"Functions","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractFunction\noutput_dimension\nconstant","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractFunction","page":"Standard form","title":"MathOptInterface.AbstractFunction","text":"AbstractFunction\n\nAbstract supertype for function objects.\n\nRequired methods\n\nAll functions must implement:\n\nBase.copy\nBase.isapprox\nconstant\n\nAbstract subtypes of AbstractFunction may require additional methods to be implemented.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.output_dimension","page":"Standard form","title":"MathOptInterface.output_dimension","text":"output_dimension(f::AbstractFunction)\n\nReturn 1 if f is an AbstractScalarFunction, or the number of output components if f is an AbstractVectorFunction.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.constant","page":"Standard form","title":"MathOptInterface.constant","text":"constant(f::AbstractFunction[, ::Type{T}]) where {T}\n\nReturns the constant term of a scalar-valued function, or the constant vector of a vector-valued function.\n\nIf f is untyped and T is provided, returns zero(T).\n\n\n\n\n\nconstant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})\n\nReturns the constant term of the set set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.constant(MOI.GreaterThan(1.0))\n1.0\n\njulia> MOI.constant(MOI.LessThan(2.5))\n2.5\n\njulia> MOI.constant(MOI.EqualTo(3))\n3\n\njulia> MOI.constant(MOI.Parameter(4.5))\n4.5\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#Scalar-functions","page":"Standard form","title":"Scalar functions","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractScalarFunction\nVariableIndex\nScalarAffineTerm\nScalarAffineFunction\nScalarQuadraticTerm\nScalarQuadraticFunction\nScalarNonlinearFunction","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractScalarFunction","page":"Standard form","title":"MathOptInterface.AbstractScalarFunction","text":"abstract type AbstractScalarFunction <: AbstractFunction\n\nAbstract supertype for scalar-valued AbstractFunctions.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VariableIndex","page":"Standard form","title":"MathOptInterface.VariableIndex","text":"VariableIndex\n\nA type-safe wrapper for Int64 for use in referencing variables in a model. To allow for deletion, indices need not be consecutive.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarAffineTerm","page":"Standard form","title":"MathOptInterface.ScalarAffineTerm","text":"ScalarAffineTerm{T}(coefficient::T, variable::VariableIndex) where {T}\n\nRepresents the scalar-valued term coefficient * variable.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> MOI.ScalarAffineTerm(2.0, x)\nMathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarAffineFunction","page":"Standard form","title":"MathOptInterface.ScalarAffineFunction","text":"ScalarAffineFunction{T}(terms::ScalarAffineTerm{T}, constant::T) where {T}\n\nRepresents the scalar-valued affine function a^top x + b, where:\n\na^top x is represented by the vector of ScalarAffineTerms\nb is a scalar constant::T\n\nDuplicates\n\nDuplicate variable indices in terms are accepted, and the corresponding coefficients are summed together.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> terms = [MOI.ScalarAffineTerm(2.0, x), MOI.ScalarAffineTerm(3.0, x)]\n2-element Vector{MathOptInterface.ScalarAffineTerm{Float64}}:\n MathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))\n MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1))\n\njulia> f = MOI.ScalarAffineFunction(terms, 4.0)\n4.0 + 2.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarQuadraticTerm","page":"Standard form","title":"MathOptInterface.ScalarQuadraticTerm","text":"ScalarQuadraticTerm{T}(\n coefficient::T,\n variable_1::VariableIndex,\n variable_2::VariableIndex,\n) where {T}\n\nRepresents the scalar-valued term c x_i x_j where c is coefficient, x_i is variable_1 and x_j is variable_2.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> MOI.ScalarQuadraticTerm(2.0, x, x)\nMathOptInterface.ScalarQuadraticTerm{Float64}(2.0, MOI.VariableIndex(1), MOI.VariableIndex(1))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarQuadraticFunction","page":"Standard form","title":"MathOptInterface.ScalarQuadraticFunction","text":"ScalarQuadraticFunction{T}(\n quadratic_terms::Vector{ScalarQuadraticTerm{T}},\n affine_terms::Vector{ScalarAffineTerm{T}},\n constant::T,\n) wher {T}\n\nThe scalar-valued quadratic function frac12x^top Q x + a^top x + b, where:\n\nQ is the symmetric matrix given by the vector of ScalarQuadraticTerms\na^top x is a sparse vector given by the vector of ScalarAffineTerms\nb is the scalar constant::T.\n\nDuplicates\n\nDuplicate indices in quadratic_terms or affine_terms are accepted, and the corresponding coefficients are summed together.\n\nIn quadratic_terms, \"mirrored\" indices, (q, r) and (r, q) where r and q are VariableIndexes, are considered duplicates; only one needs to be specified.\n\nThe 0.5 factor\n\nCoupled with the interpretation of mirrored indices, the 0.5 factor in front of the Q matrix is a common source of bugs.\n\nAs a rule, to represent a * x^2 + b * x * y:\n\nThe coefficient a in front of squared variables (diagonal elements in Q) must be doubled when creating a ScalarQuadraticTerm\nThe coefficient b in front of off-diagonal elements in Q should be left as b, be cause the mirrored index b * y * x will be implicitly added.\n\nExample\n\nTo represent the function f(x y) = 2 * x^2 + 3 * x * y + 4 * x + 5, do:\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> y = MOI.VariableIndex(2);\n\njulia> constant = 5.0;\n\njulia> affine_terms = [MOI.ScalarAffineTerm(4.0, x)];\n\njulia> quadratic_terms = [\n MOI.ScalarQuadraticTerm(4.0, x, x), # Note the changed coefficient\n MOI.ScalarQuadraticTerm(3.0, x, y),\n ]\n2-element Vector{MathOptInterface.ScalarQuadraticTerm{Float64}}:\n MathOptInterface.ScalarQuadraticTerm{Float64}(4.0, MOI.VariableIndex(1), MOI.VariableIndex(1))\n MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(2))\n\njulia> f = MOI.ScalarQuadraticFunction(quadratic_terms, affine_terms, constant)\n5.0 + 4.0 MOI.VariableIndex(1) + 2.0 MOI.VariableIndex(1)² + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarNonlinearFunction","page":"Standard form","title":"MathOptInterface.ScalarNonlinearFunction","text":"ScalarNonlinearFunction(head::Symbol, args::Vector{Any})\n\nThe scalar-valued nonlinear function head(args...), represented as a symbolic expression tree, with the call operator head and ordered arguments in args.\n\nhead\n\nThe head::Symbol must be an operator supported by the model.\n\nThe default list of supported univariate operators is given by:\n\nNonlinear.DEFAULT_UNIVARIATE_OPERATORS\n\nand the default list of supported multivariate operators is given by:\n\nNonlinear.DEFAULT_MULTIVARIATE_OPERATORS\n\nAdditional operators can be registered by setting a UserDefinedFunction attribute.\n\nSee the full list of operators supported by a ModelLike by querying ListOfSupportedNonlinearOperators.\n\nargs\n\nThe vector args contains the arguments to the nonlinear function. If the operator is univariate, it must contain one element. Otherwise, it may contain multiple elements.\n\nEach element must be one of the following:\n\nA constant value of type T<:Real\nA VariableIndex\nA ScalarAffineFunction\nA ScalarQuadraticFunction\nA ScalarNonlinearFunction\n\nUnsupported operators\n\nIf the optimizer does not support head, an UnsupportedNonlinearOperator error will be thrown.\n\nThere is no guarantee about when this error will be thrown; it may be thrown when the function is first added to the model, or it may be thrown when optimize! is called.\n\nExample\n\nTo represent the function f(x) = sin(x)^2, do:\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> MOI.ScalarNonlinearFunction(\n :^,\n Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2],\n )\n^(sin(MOI.VariableIndex(1)), (2))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Vector-functions","page":"Standard form","title":"Vector functions","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractVectorFunction\nVectorOfVariables\nVectorAffineTerm\nVectorAffineFunction\nVectorQuadraticTerm\nVectorQuadraticFunction\nVectorNonlinearFunction","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractVectorFunction","page":"Standard form","title":"MathOptInterface.AbstractVectorFunction","text":"abstract type AbstractVectorFunction <: AbstractFunction\n\nAbstract supertype for vector-valued AbstractFunctions.\n\nRequired methods\n\nAll subtypes of AbstractVectorFunction must implement:\n\noutput_dimension\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorOfVariables","page":"Standard form","title":"MathOptInterface.VectorOfVariables","text":"VectorOfVariables(variables::Vector{VariableIndex}) <: AbstractVectorFunction\n\nThe vector-valued function f(x) = variables, where variables is a subset of VariableIndexes in the model.\n\nThe list of variables may contain duplicates.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex.(1:2)\n2-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n\njulia> f = MOI.VectorOfVariables([x[1], x[2], x[1]])\n┌ ┐\n│MOI.VariableIndex(1)│\n│MOI.VariableIndex(2)│\n│MOI.VariableIndex(1)│\n└ ┘\n\njulia> MOI.output_dimension(f)\n3\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorAffineTerm","page":"Standard form","title":"MathOptInterface.VectorAffineTerm","text":"VectorAffineTerm{T}(\n output_index::Int64,\n scalar_term::ScalarAffineTerm{T},\n) where {T}\n\nA VectorAffineTerm is a scalar_term that appears in the output_index row of the vector-valued VectorAffineFunction or VectorQuadraticFunction.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x))\nMathOptInterface.VectorAffineTerm{Float64}(2, MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1)))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorAffineFunction","page":"Standard form","title":"MathOptInterface.VectorAffineFunction","text":"VectorAffineFunction{T}(\n terms::Vector{VectorAffineTerm{T}},\n constants::Vector{T},\n) where {T}\n\nThe vector-valued affine function A x + b, where:\n\nA x is the sparse matrix given by the vector of VectorAffineTerms\nb is the vector constants\n\nDuplicates\n\nDuplicate indices in the A are accepted, and the corresponding coefficients are summed together.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> terms = [\n MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),\n MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),\n ];\n\njulia> f = MOI.VectorAffineFunction(terms, [4.0, 5.0])\n┌ ┐\n│4.0 + 2.0 MOI.VariableIndex(1)│\n│5.0 + 3.0 MOI.VariableIndex(1)│\n└ ┘\n\njulia> MOI.output_dimension(f)\n2\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorQuadraticTerm","page":"Standard form","title":"MathOptInterface.VectorQuadraticTerm","text":"VectorQuadraticTerm{T}(\n output_index::Int64,\n scalar_term::ScalarQuadraticTerm{T},\n) where {T}\n\nA VectorQuadraticTerm is a ScalarQuadraticTerm scalar_term that appears in the output_index row of the vector-valued VectorQuadraticFunction.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, x))\nMathOptInterface.VectorQuadraticTerm{Float64}(2, MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(1)))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorQuadraticFunction","page":"Standard form","title":"MathOptInterface.VectorQuadraticFunction","text":"VectorQuadraticFunction{T}(\n quadratic_terms::Vector{VectorQuadraticTerm{T}},\n affine_terms::Vector{VectorAffineTerm{T}},\n constants::Vector{T},\n) where {T}\n\nThe vector-valued quadratic function with ith component (\"output index\") defined as frac12x^top Q_i x + a_i^top x + b_i, where:\n\nfrac12x^top Q_i x is the symmetric matrix given by the VectorQuadraticTerm elements in quadratic_terms with output_index == i\na_i^top x is the sparse vector given by the VectorAffineTerm elements in affine_terms with output_index == i\nb_i is a scalar given by constants[i]\n\nDuplicates\n\nDuplicate indices in quadratic_terms and affine_terms with the same output_index are handled in the same manner as duplicates in ScalarQuadraticFunction.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> y = MOI.VariableIndex(2);\n\njulia> constants = [4.0, 5.0];\n\njulia> affine_terms = [\n MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),\n MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),\n ];\n\njulia> quad_terms = [\n MOI.VectorQuadraticTerm(Int64(1), MOI.ScalarQuadraticTerm(2.0, x, x)),\n MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, y)),\n ];\n\njulia> f = MOI.VectorQuadraticFunction(quad_terms, affine_terms, constants)\n┌ ┐\n│4.0 + 2.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)² │\n│5.0 + 3.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)│\n└ ┘\n\njulia> MOI.output_dimension(f)\n2\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorNonlinearFunction","page":"Standard form","title":"MathOptInterface.VectorNonlinearFunction","text":"VectorNonlinearFunction(args::Vector{ScalarNonlinearFunction})\n\nThe vector-valued nonlinear function composed of a vector of ScalarNonlinearFunction.\n\nargs\n\nThe vector args contains the scalar elements of the nonlinear function. Each element must be a ScalarNonlinearFunction, but if you pass a Vector{Any}, the elements can be automatically converted from one of the following:\n\nA constant value of type T<:Real\nA VariableIndex\nA ScalarAffineFunction\nA ScalarQuadraticFunction\nA ScalarNonlinearFunction\n\nExample\n\nTo represent the function f(x) = sin(x)^2 x, do:\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> g = MOI.ScalarNonlinearFunction(\n :^,\n Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2.0],\n )\n^(sin(MOI.VariableIndex(1)), 2.0)\n\njulia> MOI.VectorNonlinearFunction([g, x])\n┌ ┐\n│^(sin(MOI.VariableIndex(1)), 2.0)│\n│+(MOI.VariableIndex(1)) │\n└ ┘\n\nNote the automatic conversion from x to +(x).\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Sets","page":"Standard form","title":"Sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractSet\nAbstractScalarSet\nAbstractVectorSet","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractSet","page":"Standard form","title":"MathOptInterface.AbstractSet","text":"AbstractSet\n\nAbstract supertype for set objects used to encode constraints.\n\nRequired methods\n\nFor sets of type S with isbitstype(S) == false, you must implement:\n\nBase.copy(set::S)\nBase.:(==)(x::S, y::S)\n\nSubtypes of AbstractSet such as AbstractScalarSet and AbstractVectorSet may prescribe additional required methods.\n\nOptional methods\n\nYou may optionally implement:\n\ndual_set\ndual_set_type\n\nNote for developers\n\nWhen creating a new set, the set struct must not contain any VariableIndex or ConstraintIndex objects.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.AbstractScalarSet","page":"Standard form","title":"MathOptInterface.AbstractScalarSet","text":"AbstractScalarSet\n\nAbstract supertype for subsets of mathbbR.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.AbstractVectorSet","page":"Standard form","title":"MathOptInterface.AbstractVectorSet","text":"AbstractVectorSet\n\nAbstract supertype for subsets of mathbbR^n for some n.\n\nRequired methods\n\nAll AbstractVectorSets of type S must implement:\n\ndimension, unless the dimension is stored in the set.dimension field\nUtilities.set_dot, unless the dot product between two vectors in the set is equivalent to LinearAlgebra.dot.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Utilities","page":"Standard form","title":"Utilities","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"dimension\ndual_set\ndual_set_type\nconstant(s::EqualTo)\nsupports_dimension_update\nupdate_dimension","category":"page"},{"location":"reference/standard_form/#MathOptInterface.dimension","page":"Standard form","title":"MathOptInterface.dimension","text":"dimension(set::AbstractSet)\n\nReturn the output_dimension that an AbstractFunction should have to be used with the set set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.dimension(MOI.Reals(4))\n4\n\njulia> MOI.dimension(MOI.LessThan(3.0))\n1\n\njulia> MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(2))\n3\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.dual_set","page":"Standard form","title":"MathOptInterface.dual_set","text":"dual_set(set::AbstractSet)\n\nReturn the dual set of set, that is the dual cone of the set. This follows the definition of duality discussed in Duality.\n\nSee Dual cone for more information.\n\nIf the dual cone is not defined it returns an error.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.dual_set(MOI.Reals(4))\nMathOptInterface.Zeros(4)\n\njulia> MOI.dual_set(MOI.SecondOrderCone(5))\nMathOptInterface.SecondOrderCone(5)\n\njulia> MOI.dual_set(MOI.ExponentialCone())\nMathOptInterface.DualExponentialCone()\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.dual_set_type","page":"Standard form","title":"MathOptInterface.dual_set_type","text":"dual_set_type(S::Type{<:AbstractSet})\n\nReturn the type of dual set of sets of type S, as returned by dual_set. If the dual cone is not defined it returns an error.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.dual_set_type(MOI.Reals)\nMathOptInterface.Zeros\n\njulia> MOI.dual_set_type(MOI.SecondOrderCone)\nMathOptInterface.SecondOrderCone\n\njulia> MOI.dual_set_type(MOI.ExponentialCone)\nMathOptInterface.DualExponentialCone\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.constant-Tuple{MathOptInterface.EqualTo}","page":"Standard form","title":"MathOptInterface.constant","text":"constant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})\n\nReturns the constant term of the set set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.constant(MOI.GreaterThan(1.0))\n1.0\n\njulia> MOI.constant(MOI.LessThan(2.5))\n2.5\n\njulia> MOI.constant(MOI.EqualTo(3))\n3\n\njulia> MOI.constant(MOI.Parameter(4.5))\n4.5\n\n\n\n\n\n","category":"method"},{"location":"reference/standard_form/#MathOptInterface.supports_dimension_update","page":"Standard form","title":"MathOptInterface.supports_dimension_update","text":"supports_dimension_update(S::Type{<:MOI.AbstractVectorSet})\n\nReturn a Bool indicating whether the elimination of any dimension of n-dimensional sets of type S give an n-1-dimensional set S. By default, this function returns false so it should only be implemented for sets that supports dimension update.\n\nFor instance, supports_dimension_update(MOI.Nonnegatives) is true because the elimination of any dimension of the n-dimensional nonnegative orthant gives the n-1-dimensional nonnegative orthant. However supports_dimension_update(MOI.ExponentialCone) is false.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.update_dimension","page":"Standard form","title":"MathOptInterface.update_dimension","text":"update_dimension(s::AbstractVectorSet, new_dim::Int)\n\nReturns a set with the dimension modified to new_dim.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#Scalar-sets","page":"Standard form","title":"Scalar sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"List of recognized scalar sets.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"GreaterThan\nLessThan\nEqualTo\nInterval\nInteger\nZeroOne\nSemicontinuous\nSemiinteger\nParameter","category":"page"},{"location":"reference/standard_form/#MathOptInterface.GreaterThan","page":"Standard form","title":"MathOptInterface.GreaterThan","text":"GreaterThan{T<:Real}(lower::T)\n\nThe set lower infty) subseteq mathbbR.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.GreaterThan(0.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.LessThan","page":"Standard form","title":"MathOptInterface.LessThan","text":"LessThan{T<:Real}(upper::T)\n\nThe set (-infty upper subseteq mathbbR.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.LessThan(2.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.EqualTo","page":"Standard form","title":"MathOptInterface.EqualTo","text":"EqualTo{T<:Number}(value::T)\n\nThe set containing the single point value subseteq mathbbR.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.EqualTo(2.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Interval","page":"Standard form","title":"MathOptInterface.Interval","text":"Interval{T<:Real}(lower::T, upper::T)\n\nThe interval lower upper subseteq mathbbR cup -infty +infty.\n\nIf lower or upper is -Inf or Inf, respectively, the set is interpreted as a one-sided interval.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.Interval(1.0, 2.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Integer","page":"Standard form","title":"MathOptInterface.Integer","text":"Integer()\n\nThe set of integers, mathbbZ.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.Integer())\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ZeroOne","page":"Standard form","title":"MathOptInterface.ZeroOne","text":"ZeroOne()\n\nThe set 0 1.\n\nVariables belonging to the ZeroOne set are also known as \"binary\" variables.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.ZeroOne())\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Semicontinuous","page":"Standard form","title":"MathOptInterface.Semicontinuous","text":"Semicontinuous{T<:Real}(lower::T, upper::T)\n\nThe set 0 cup lower upper.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.Semicontinuous(2.0, 3.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semicontinuous{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Semiinteger","page":"Standard form","title":"MathOptInterface.Semiinteger","text":"Semiinteger{T<:Real}(lower::T, upper::T)\n\nThe set 0 cup lower lower+1 ldots upper-1 upper.\n\nNote that if lower and upper are not equivalent to an integer, then the solver may throw an error, or it may round up lower and round down upper to the nearest integers.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.Semiinteger(2.0, 3.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semiinteger{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Parameter","page":"Standard form","title":"MathOptInterface.Parameter","text":"Parameter{T<:Number}(value::T)\n\nThe set containing the single point value subseteq mathbbR.\n\nThe Parameter set is conceptually similar to the EqualTo set, except that a variable constrained to the Parameter set cannot have other constraints added to it, and the Parameter set can never be deleted. Thus, solvers are free to treat the variable as a constant, and they need not add it as a decision variable to the model.\n\nBecause of this behavior, you must add parameters using add_constrained_variable, and solvers should declare supports_add_constrained_variable and not supports_constraint for the Parameter set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> p, ci = MOI.add_constrained_variable(model, MOI.Parameter(2.5))\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Parameter{Float64}}(1))\n\njulia> MOI.set(model, MOI.ConstraintSet(), ci, MOI.Parameter(3.0))\n\njulia> MOI.get(model, MOI.ConstraintSet(), ci)\nMathOptInterface.Parameter{Float64}(3.0)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Vector-sets","page":"Standard form","title":"Vector sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"List of recognized vector sets.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"Reals\nZeros\nNonnegatives\nNonpositives\nNormInfinityCone\nNormOneCone\nNormCone\nSecondOrderCone\nRotatedSecondOrderCone\nGeometricMeanCone\nExponentialCone\nDualExponentialCone\nPowerCone\nDualPowerCone\nRelativeEntropyCone\nNormSpectralCone\nNormNuclearCone\nSOS1\nSOS2\nIndicator\nComplements\nHyperRectangle\nScaled","category":"page"},{"location":"reference/standard_form/#MathOptInterface.Reals","page":"Standard form","title":"MathOptInterface.Reals","text":"Reals(dimension::Int)\n\nThe set mathbbR^dimension (containing all points) of non-negative dimension dimension.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Reals(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Reals}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Zeros","page":"Standard form","title":"MathOptInterface.Zeros","text":"Zeros(dimension::Int)\n\nThe set 0 ^dimension (containing only the origin) of non-negative dimension dimension.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Zeros(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Zeros}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Nonnegatives","page":"Standard form","title":"MathOptInterface.Nonnegatives","text":"Nonnegatives(dimension::Int)\n\nThe nonnegative orthant x in mathbbR^dimension x ge 0 of non-negative dimension dimension.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Nonpositives","page":"Standard form","title":"MathOptInterface.Nonpositives","text":"Nonpositives(dimension::Int)\n\nThe nonpositive orthant x in mathbbR^dimension x le 0 of non-negative dimension dimension.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonpositives(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonpositives}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormInfinityCone","page":"Standard form","title":"MathOptInterface.NormInfinityCone","text":"NormInfinityCone(dimension::Int)\n\nThe ell_infty-norm cone (tx) in mathbbR^dimension t ge lVert x rVert_infty = max_i lvert x_i rvert of dimension dimension.\n\nThe dimension must be at least 1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormInfinityCone(4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormInfinityCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormOneCone","page":"Standard form","title":"MathOptInterface.NormOneCone","text":"NormOneCone(dimension::Int)\n\nThe ell_1-norm cone (tx) in mathbbR^dimension t ge lVert x rVert_1 = sum_i lvert x_i rvert of dimension dimension.\n\nThe dimension must be at least 1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormOneCone(4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormOneCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormCone","page":"Standard form","title":"MathOptInterface.NormCone","text":"NormCone(p::Float64, dimension::Int)\n\nThe ell_p-norm cone (tx) in mathbbR^dimension t ge left(sumlimits_i x_i^pright)^frac1p of dimension dimension.\n\nThe dimension must be at least 1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormCone(3, 4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.SecondOrderCone","page":"Standard form","title":"MathOptInterface.SecondOrderCone","text":"SecondOrderCone(dimension::Int)\n\nThe second-order cone (or Lorenz cone or ell_2-norm cone) (tx) in mathbbR^dimension t ge lVert x rVert_2 of dimension dimension.\n\nThe dimension must be at least 1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.SecondOrderCone(4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SecondOrderCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.RotatedSecondOrderCone","page":"Standard form","title":"MathOptInterface.RotatedSecondOrderCone","text":"RotatedSecondOrderCone(dimension::Int)\n\nThe rotated second-order cone (tux) in mathbbR^dimension 2tu ge lVert x rVert_2^2 tu ge 0 of dimension dimension.\n\nThe dimension must be at least 2.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> u = MOI.add_variable(model)\nMOI.VariableIndex(2)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; u; x]),\n MOI.RotatedSecondOrderCone(5),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RotatedSecondOrderCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.GeometricMeanCone","page":"Standard form","title":"MathOptInterface.GeometricMeanCone","text":"GeometricMeanCone(dimension::Int)\n\nThe geometric mean cone (tx) in mathbbR^n+1 x ge 0 t le sqrtnx_1 x_2 cdots x_n , where dimension = n + 1 >= 2.\n\nDuality note\n\nThe dual of the geometric mean cone is (u v) in mathbbR^n+1 u le 0 v ge 0 -u le n sqrtnprod_i v_i , where dimension = n + 1 >= 2.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; x]),\n MOI.GeometricMeanCone(4),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.GeometricMeanCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ExponentialCone","page":"Standard form","title":"MathOptInterface.ExponentialCone","text":"ExponentialCone()\n\nThe 3-dimensional exponential cone (xyz) in mathbbR^3 y exp (xy) le z y 0 .\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.ExponentialCone())\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.ExponentialCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.DualExponentialCone","page":"Standard form","title":"MathOptInterface.DualExponentialCone","text":"DualExponentialCone()\n\nThe 3-dimensional dual exponential cone (uvw) in mathbbR^3 -u exp (vu) le exp(1) w u 0 .\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualExponentialCone())\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualExponentialCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.PowerCone","page":"Standard form","title":"MathOptInterface.PowerCone","text":"PowerCone{T<:Real}(exponent::T)\n\nThe 3-dimensional power cone (xyz) in mathbbR^3 x^exponent y^1-exponent ge z x ge 0 y ge 0 with parameter exponent.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.PowerCone(0.5))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.PowerCone{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.DualPowerCone","page":"Standard form","title":"MathOptInterface.DualPowerCone","text":"DualPowerCone{T<:Real}(exponent::T)\n\nThe 3-dimensional power cone (uvw) in mathbbR^3 (fracuexponent)^exponent (fracv1-exponent)^1-exponent ge w u ge 0 v ge 0 with parameter exponent.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualPowerCone(0.5))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualPowerCone{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.RelativeEntropyCone","page":"Standard form","title":"MathOptInterface.RelativeEntropyCone","text":"RelativeEntropyCone(dimension::Int)\n\nThe relative entropy cone (u v w) in mathbbR^1+2n u ge sum_i=1^n w_i log(fracw_iv_i) v_i ge 0 w_i ge 0 , where dimension = 2n + 1 >= 1.\n\nDuality note\n\nThe dual of the relative entropy cone is (u v w) in mathbbR^1+2n forall i w_i ge u (log (fracuv_i) - 1) v_i ge 0 u 0 of dimension dimension=2n+1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> u = MOI.add_variable(model);\n\njulia> v = MOI.add_variables(model, 3);\n\njulia> w = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([u; v; w]),\n MOI.RelativeEntropyCone(7),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RelativeEntropyCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormSpectralCone","page":"Standard form","title":"MathOptInterface.NormSpectralCone","text":"NormSpectralCone(row_dim::Int, column_dim::Int)\n\nThe epigraph of the matrix spectral norm (maximum singular value function) (t X) in mathbbR^1 + row_dim times column_dim t ge sigma_1(X) , where sigma_i is the ith singular value of the matrix X of non-negative row dimension row_dim and column dimension column_dim.\n\nThe matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = reshape(MOI.add_variables(model, 6), 2, 3)\n2×3 Matrix{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2) MOI.VariableIndex(4) MOI.VariableIndex(6)\n MOI.VariableIndex(3) MOI.VariableIndex(5) MOI.VariableIndex(7)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; vec(X)]),\n MOI.NormSpectralCone(2, 3),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormSpectralCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormNuclearCone","page":"Standard form","title":"MathOptInterface.NormNuclearCone","text":"NormNuclearCone(row_dim::Int, column_dim::Int)\n\nThe epigraph of the matrix nuclear norm (sum of singular values function) (t X) in mathbbR^1 + row_dim times column_dim t ge sum_i sigma_i(X) , where sigma_i is the ith singular value of the matrix X of non-negative row dimension row_dim and column dimension column_dim.\n\nThe matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = reshape(MOI.add_variables(model, 6), 2, 3)\n2×3 Matrix{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2) MOI.VariableIndex(4) MOI.VariableIndex(6)\n MOI.VariableIndex(3) MOI.VariableIndex(5) MOI.VariableIndex(7)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; vec(X)]),\n MOI.NormNuclearCone(2, 3),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormNuclearCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.SOS1","page":"Standard form","title":"MathOptInterface.SOS1","text":"SOS1{T<:Real}(weights::Vector{T})\n\nThe set corresponding to the Special Ordered Set (SOS) constraint of Type I.\n\nOf the variables in the set, at most one can be nonzero.\n\nThe weights induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights. Solvers may use these weights to improve the efficiency of the solution process, but the ordering does not change the set of feasible solutions.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables(x),\n MOI.SOS1([1.0, 3.0, 2.5]),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS1{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.SOS2","page":"Standard form","title":"MathOptInterface.SOS2","text":"SOS2{T<:Real}(weights::Vector{T})\n\nThe set corresponding to the Special Ordered Set (SOS) constraint of Type II.\n\nThe weights induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights. Therefore, the weights must be unique.\n\nOf the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables(x),\n MOI.SOS2([1.0, 3.0, 2.5]),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS2{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Indicator","page":"Standard form","title":"MathOptInterface.Indicator","text":"Indicator{A<:ActivationCondition,S<:AbstractScalarSet}(set::S)\n\nThe set corresponding to an indicator constraint.\n\nWhen A is ACTIVATE_ON_ZERO, this means: (y x) in 0 1 times mathbbR^n y = 0 implies x in set\n\nWhen A is ACTIVATE_ON_ONE, this means: (y x) in 0 1 times mathbbR^n y = 1 implies x in set\n\nNotes\n\nMost solvers expect that the first row of the function is interpretable as a variable index x_i (e.g., 1.0 * x + 0.0). An error will be thrown if this is not the case.\n\nExample\n\nThe constraint (y x) in 0 1 times mathbbR^2 y = 1 implies x_1 + x_2 leq 9 is defined as\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 2)\n2-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n\njulia> y, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())\n(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3))\n\njulia> f = MOI.VectorAffineFunction(\n [\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, y)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[1])),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[2])),\n ],\n [0.0, 0.0],\n )\n┌ ┐\n│0.0 + 1.0 MOI.VariableIndex(3) │\n│0.0 + 1.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(2)│\n└ ┘\n\njulia> s = MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(9.0))\nMathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}(MathOptInterface.LessThan{Float64}(9.0))\n\njulia> MOI.add_constraint(model, f, s)\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Complements","page":"Standard form","title":"MathOptInterface.Complements","text":"Complements(dimension::Base.Integer)\n\nThe set corresponding to a mixed complementarity constraint.\n\nComplementarity constraints should be specified with an AbstractVectorFunction-in-Complements(dimension) constraint.\n\nThe dimension of the vector-valued function F must be dimension. This defines a complementarity constraint between the scalar function F[i] and the variable in F[i + dimension/2]. Thus, F[i + dimension/2] must be interpretable as a single variable x_i (e.g., 1.0 * x + 0.0), and dimension must be even.\n\nThe mixed complementarity problem consists of finding x_i in the interval [lb, ub] (i.e., in the set Interval(lb, ub)), such that the following holds:\n\nF_i(x) == 0 if lb_i < x_i < ub_i\nF_i(x) >= 0 if lb_i == x_i\nF_i(x) <= 0 if x_i == ub_i\n\nClassically, the bounding set for x_i is Interval(0, Inf), which recovers: 0 <= F_i(x) ⟂ x_i >= 0, where the ⟂ operator implies F_i(x) * x_i = 0.\n\nExample\n\nThe problem:\n\nx -in- Interval(-1, 1)\n[-4 * x - 3, x] -in- Complements(2)\n\ndefines the mixed complementarity problem where the following holds:\n\n-4 * x - 3 == 0 if -1 < x < 1\n-4 * x - 3 >= 0 if x == -1\n-4 * x - 3 <= 0 if x == 1\n\nThere are three solutions:\n\nx = -3/4 with F(x) = 0\nx = -1 with F(x) = 1\nx = 1 with F(x) = -7\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x, _ = MOI.add_constrained_variable(model, MOI.Interval(-1.0, 1.0));\n\njulia> MOI.add_constraint(\n model,\n MOI.Utilities.vectorize([-4.0 * x - 3.0, x]),\n MOI.Complements(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Complements}(1)\n\nThe function F can also be defined in terms of single variables. For example, the problem:\n\n[x_3, x_4] -in- Nonnegatives(2)\n[x_1, x_2, x_3, x_4] -in- Complements(4)\n\ndefines the complementarity problem where 0 <= x_1 ⟂ x_3 >= 0 and 0 <= x_2 ⟂ x_4 >= 0.\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 4);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x[3:4]), MOI.Nonnegatives(2))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables(x),\n MOI.Complements(4),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Complements}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.HyperRectangle","page":"Standard form","title":"MathOptInterface.HyperRectangle","text":"HyperRectangle(lower::Vector{T}, upper::Vector{T}) where {T}\n\nThe set x in barmathbbR^d x_i in lower_i upper_i forall i=1ldotsd.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3)\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables(x),\n MOI.HyperRectangle(zeros(3), ones(3)),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.HyperRectangle{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Scaled","page":"Standard form","title":"MathOptInterface.Scaled","text":"struct Scaled{S<:AbstractVectorSet} <: AbstractVectorSet\n set::S\nend\n\nGiven a vector a in mathbbR^d and a set representing the set mathcalS in mathbbR^d such that Utilities.set_dot for x in mathcalS and y in mathcalS^* is\n\nsum_i=1^d a_i x_i y_i\n\nthe set Scaled(set) is defined as\n\n (sqrta_1 x_1 sqrta_2 x_2 ldots sqrta_d x_d) x in S \n\nExample\n\nThis can be used to scale a vector of numbers\n\njulia> import MathOptInterface as MOI\n\njulia> set = MOI.PositiveSemidefiniteConeTriangle(2)\nMathOptInterface.PositiveSemidefiniteConeTriangle(2)\n\njulia> a = MOI.Utilities.SetDotScalingVector{Float64}(set)\n3-element MathOptInterface.Utilities.SetDotScalingVector{Float64, MathOptInterface.PositiveSemidefiniteConeTriangle}:\n 1.0\n 1.4142135623730951\n 1.0\n\njulia> using LinearAlgebra\n\njulia> MOI.Utilities.operate(*, Float64, Diagonal(a), ones(3))\n3-element Vector{Float64}:\n 1.0\n 1.4142135623730951\n 1.0\n\nIt can be also used to scale a vector of function\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> func = MOI.VectorOfVariables(x)\n┌ ┐\n│MOI.VariableIndex(1)│\n│MOI.VariableIndex(2)│\n│MOI.VariableIndex(3)│\n└ ┘\n\njulia> set = MOI.PositiveSemidefiniteConeTriangle(2)\nMathOptInterface.PositiveSemidefiniteConeTriangle(2)\n\njulia> MOI.Utilities.operate(*, Float64, Diagonal(a), func)\n┌ ┐\n│0.0 + 1.0 MOI.VariableIndex(1) │\n│0.0 + 1.4142135623730951 MOI.VariableIndex(2)│\n│0.0 + 1.0 MOI.VariableIndex(3) │\n└ ┘\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Constraint-programming-sets","page":"Standard form","title":"Constraint programming sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AllDifferent\nBinPacking\nCircuit\nCountAtLeast\nCountBelongs\nCountDistinct\nCountGreaterThan\nCumulative\nPath\nReified\nTable","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AllDifferent","page":"Standard form","title":"MathOptInterface.AllDifferent","text":"AllDifferent(dimension::Int)\n\nThe set x in mathbbZ^d such that no two elements in x take the same value and dimension = d.\n\nAlso known as\n\nThis constraint is called all_different in MiniZinc, and is sometimes also called distinct.\n\nExample\n\nTo enforce x[1] != x[2] AND x[1] != x[3] AND x[2] != x[3]:\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.AllDifferent(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.AllDifferent}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.BinPacking","page":"Standard form","title":"MathOptInterface.BinPacking","text":"BinPacking(c::T, w::Vector{T}) where {T}\n\nThe set x in mathbbZ^d where d = length(w), such that each item i in 1:d of weight w[i] is put into bin x[i], and the total weight of each bin does not exceed c.\n\nThere are additional assumptions that the capacity, c, and the weights, w, must all be non-negative.\n\nThe bin numbers depend on the bounds of x, so they may be something other than the integers 1:d.\n\nAlso known as\n\nThis constraint is called bin_packing in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> bins = MOI.add_variables(model, 5)\n5-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n MOI.VariableIndex(5)\n\njulia> weights = Float64[1, 1, 2, 2, 3]\n5-element Vector{Float64}:\n 1.0\n 1.0\n 2.0\n 2.0\n 3.0\n\njulia> MOI.add_constraint.(model, bins, MOI.Integer())\n5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(4)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(5)\n\njulia> MOI.add_constraint.(model, bins, MOI.Interval(4.0, 6.0))\n5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(2)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(3)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(4)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(5)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(bins), MOI.BinPacking(3.0, weights))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.BinPacking{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Circuit","page":"Standard form","title":"MathOptInterface.Circuit","text":"Circuit(dimension::Int)\n\nThe set x in 1d^d that constraints x to be a circuit, such that x_i = j means that j is the successor of i, and dimension = d.\n\nGraphs with multiple independent circuits, such as [2, 1, 3] and [2, 1, 4, 3], are not valid.\n\nAlso known as\n\nThis constraint is called circuit in MiniZinc, and it is equivalent to forming a (potentially sub-optimal) tour in the travelling salesperson problem.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Circuit(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Circuit}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.CountAtLeast","page":"Standard form","title":"MathOptInterface.CountAtLeast","text":"CountAtLeast(n::Int, d::Vector{Int}, set::Set{Int})\n\nThe set x in mathbbZ^d_1 + d_2 + ldots d_N, where x is partitioned into N subsets (x_1 ldots x_d_1, x_d_1 + 1 ldots x_d_1 + d_2 and so on), and at least n elements of each subset take one of the values in set.\n\nAlso known as\n\nThis constraint is called at_least in MiniZinc.\n\nExample\n\nTo ensure that 3 appears at least once in each of the subsets {a, b} and {b, c}:\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> a, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))\n\njulia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3))\n\njulia> x, d, set = [a, b, b, c], [2, 2], [3]\n(MathOptInterface.VariableIndex[MOI.VariableIndex(1), MOI.VariableIndex(2), MOI.VariableIndex(2), MOI.VariableIndex(3)], [2, 2], [3])\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.CountAtLeast(1, d, Set(set)))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountAtLeast}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.CountBelongs","page":"Standard form","title":"MathOptInterface.CountBelongs","text":"CountBelongs(dimenson::Int, set::Set{Int})\n\nThe set (n x) in mathbbZ^1+d, such that n elements of the vector x take on of the values in set and dimension = 1 + d.\n\nAlso known as\n\nThis constraint is called among by MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n\njulia> set = Set([3, 4, 5])\nSet{Int64} with 3 elements:\n 5\n 4\n 3\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([n; x]), MOI.CountBelongs(4, set))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountBelongs}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.CountDistinct","page":"Standard form","title":"MathOptInterface.CountDistinct","text":"CountDistinct(dimension::Int)\n\nThe set (n x) in mathbbZ^1+d, such that the number of distinct values in x is n and dimension = 1 + d.\n\nAlso known as\n\nThis constraint is called nvalues in MiniZinc.\n\nExample\n\nTo model:\n\nif n == 1`, thenx[1] == x[2] == x[3]`\nif n == 2, then\nx[1] == x[2] != x[3] or\nx[1] != x[2] == x[3] or\nx[1] == x[3] != x[2]\nif n == 3, then x[1] != x[2], x[2] != x[3] and x[3] != x[1]\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(vcat(n, x)), MOI.CountDistinct(4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountDistinct}(1)\n\nRelationship to AllDifferent\n\nWhen the first element is d, CountDistinct is equivalent to an AllDifferent constraint.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.CountGreaterThan","page":"Standard form","title":"MathOptInterface.CountGreaterThan","text":"CountGreaterThan(dimension::Int)\n\nThe set (c y x) in mathbbZ^1+1+d, such that c is strictly greater than the number of occurances of y in x and dimension = 1 + 1 + d.\n\nAlso known as\n\nThis constraint is called count_gt in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> y, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n MOI.VariableIndex(5)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([c; y; x]), MOI.CountGreaterThan(5))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountGreaterThan}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Cumulative","page":"Standard form","title":"MathOptInterface.Cumulative","text":"Cumulative(dimension::Int)\n\nThe set (s d r b) in mathbbZ^3n+1, representing the cumulative global constraint, where n == length(s) == length(r) == length(b) and dimension = 3n + 1.\n\nCumulative requires that a set of tasks given by start times s, durations d, and resource requirements r, never requires more than the global resource bound b at any one time.\n\nAlso known as\n\nThis constraint is called cumulative in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> s = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> d = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(4)\n MOI.VariableIndex(5)\n MOI.VariableIndex(6)\n\njulia> r = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(7)\n MOI.VariableIndex(8)\n MOI.VariableIndex(9)\n\njulia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(10), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(10))\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([s; d; r; b]), MOI.Cumulative(10))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Cumulative}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Path","page":"Standard form","title":"MathOptInterface.Path","text":"Path(from::Vector{Int}, to::Vector{Int})\n\nGiven a graph comprised of a set of nodes 1..N and a set of arcs 1..E represented by an edge from node from[i] to node to[i], Path constrains the set (s t ns es) in (1N)times(1E)times01^Ntimes01^E, to form subgraph that is a path from node s to node t, where node n is in the path if ns[n] is 1, and edge e is in the path if es[e] is 1.\n\nThe path must be acyclic, and it must traverse all nodes n for which ns[n] is 1, and all edges e for which es[e] is 1.\n\nAlso known as\n\nThis constraint is called path in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> N, E = 4, 5\n(4, 5)\n\njulia> from = [1, 1, 2, 2, 3]\n5-element Vector{Int64}:\n 1\n 1\n 2\n 2\n 3\n\njulia> to = [2, 3, 3, 4, 4]\n5-element Vector{Int64}:\n 2\n 3\n 3\n 4\n 4\n\njulia> s, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> t, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))\n\njulia> ns = MOI.add_variables(model, N)\n4-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n MOI.VariableIndex(5)\n MOI.VariableIndex(6)\n\njulia> MOI.add_constraint.(model, ns, MOI.ZeroOne())\n4-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(4)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(5)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(6)\n\njulia> es = MOI.add_variables(model, E)\n5-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(7)\n MOI.VariableIndex(8)\n MOI.VariableIndex(9)\n MOI.VariableIndex(10)\n MOI.VariableIndex(11)\n\njulia> MOI.add_constraint.(model, es, MOI.ZeroOne())\n5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(7)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(8)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(9)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(10)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(11)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([s; t; ns; es]), MOI.Path(from, to))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Path}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Reified","page":"Standard form","title":"MathOptInterface.Reified","text":"Reified(set::AbstractSet)\n\nThe constraint z f(x) in Reified(S) ensures that f(x) in S if and only if z == 1, where z in 0 1.\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())\nMOIU.UniversalFallback{MOIU.Model{Float64}}\nfallback for MOIU.Model{Float64}\n\njulia> z, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1))\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(2)\n\njulia> MOI.add_constraint(\n model,\n MOI.Utilities.vectorize([z, 2.0 * x]),\n MOI.Reified(MOI.GreaterThan(1.0)),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Reified{MathOptInterface.GreaterThan{Float64}}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Table","page":"Standard form","title":"MathOptInterface.Table","text":"Table(table::Matrix{T}) where {T}\n\nThe set x in mathbbR^d where d = size(table, 2), such that x belongs to one row of table. That is, there exists some j in 1:size(table, 1), such that x[i] = table[j, i] for all i=1:size(table, 2).\n\nAlso known as\n\nThis constraint is called table in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3)\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> table = Float64[1 1 0; 0 1 1; 1 0 1; 1 1 1]\n4×3 Matrix{Float64}:\n 1.0 1.0 0.0\n 0.0 1.0 1.0\n 1.0 0.0 1.0\n 1.0 1.0 1.0\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Table(table))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Table{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Matrix-sets","page":"Standard form","title":"Matrix sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"Matrix sets are vectorized to be subtypes of AbstractVectorSet.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"For sets of symmetric matrices, storing both the (i, j) and (j, i) elements is redundant. Use the AbstractSymmetricMatrixSetTriangle set to represent only the vectorization of the upper triangular part of the matrix.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"When the matrix of expressions constrained to be in the set is not symmetric, and hence additional constraints are needed to force the equality of the (i, j) and (j, i) elements, use the AbstractSymmetricMatrixSetSquare set.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"The Bridges.Constraint.SquareBridge can transform a set from the square form to the triangular_form by adding appropriate constraints if the (i, j) and (j, i) expressions are different.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractSymmetricMatrixSetTriangle\nAbstractSymmetricMatrixSetSquare\nside_dimension\ntriangular_form","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractSymmetricMatrixSetTriangle","page":"Standard form","title":"MathOptInterface.AbstractSymmetricMatrixSetTriangle","text":"abstract type AbstractSymmetricMatrixSetTriangle <: AbstractVectorSet end\n\nAbstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row). A vectorized cone of dimension n corresponds to a square matrix with side dimension sqrt14 + 2 n - 12. (Because a d times d matrix has d(d + 1) 2 elements in the upper or lower triangle.)\n\nExample\n\nThe matrix\n\nbeginbmatrix\n 1 2 4\n 2 3 5\n 4 5 6\nendbmatrix\n\nhas side_dimension 3 and vectorization (1 2 3 4 5 6).\n\nNote\n\nTwo packed storage formats exist for symmetric matrices, the respective orders of the entries are:\n\nupper triangular column by column (or lower triangular row by row);\nlower triangular column by column (or upper triangular row by row).\n\nThe advantage of the first format is the mapping between the (i, j) matrix indices and the k index of the vectorized form. It is simpler and does not depend on the side dimension of the matrix. Indeed,\n\nthe entry of matrix indices (i, j) has vectorized index k = div((j - 1) * j, 2) + i if i leq j and k = div((i - 1) * i, 2) + j if j leq i;\nand the entry with vectorized index k has matrix indices i = div(1 + isqrt(8k - 7), 2) and j = k - div((i - 1) * i, 2) or j = div(1 + isqrt(8k - 7), 2) and i = k - div((j - 1) * j, 2).\n\nDuality note\n\nThe scalar product for the symmetric matrix in its vectorized form is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries; see [p. 634, 1]. This has important consequence for duality.\n\nConsider for example the following problem (PositiveSemidefiniteConeTriangle is a subtype of AbstractSymmetricMatrixSetTriangle)\n\nbeginalign*\n max_x in mathbbR x\n \n textst \n (1 -x 1) in textPositiveSemidefiniteConeTriangle(2)\nendalign*\n\nThe dual is the following problem\n\nbeginalign*\n min_x in mathbbR^3 y_1 + y_3\n \n textst 2y_2 = 1\n y in textPositiveSemidefiniteConeTriangle(2)\nendalign*\n\nWhy do we use 2y_2 in the dual constraint instead of y_2 ? The reason is that 2y_2 is the scalar product between y and the symmetric matrix whose vectorized form is (0 1 0). Indeed, with our modified scalar products we have\n\nlangle\n(0 1 0)\n(y_1 y_2 y_3)\nrangle\n=\nmathrmtrace\nbeginpmatrix\n 0 1\n 1 0\nendpmatrix\nbeginpmatrix\n y_1 y_2\n y_2 y_3\nendpmatrix\n= 2y_2\n\nReferences\n\n[1] Boyd, S. and Vandenberghe, L.. Convex optimization. Cambridge university press, 2004.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.AbstractSymmetricMatrixSetSquare","page":"Standard form","title":"MathOptInterface.AbstractSymmetricMatrixSetSquare","text":"abstract type AbstractSymmetricMatrixSetSquare <: AbstractVectorSet end\n\nAbstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the matrix are given column by column (or equivalently, row by row). The matrix is both constrained to be symmetric and to have its triangular_form belong to the corresponding set. That is, if the functions in entries (i j) and (j i) are different, then a constraint will be added to make sure that the entries are equal.\n\nExample\n\nPositiveSemidefiniteConeSquare is a subtype of AbstractSymmetricMatrixSetSquare and constraining the matrix\n\nbeginbmatrix\n 1 -y\n -z 0\nendbmatrix\n\nto be symmetric positive semidefinite can be achieved by constraining the vector (1 -z -y 0) (or (1 -y -z 0)) to belong to the PositiveSemidefiniteConeSquare(2). It both constrains y = z and (1 -y 0) (or (1 -z 0)) to be in PositiveSemidefiniteConeTriangle(2), since triangular_form(PositiveSemidefiniteConeSquare) is PositiveSemidefiniteConeTriangle.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.side_dimension","page":"Standard form","title":"MathOptInterface.side_dimension","text":"side_dimension(\n set::Union{\n AbstractSymmetricMatrixSetTriangle,\n AbstractSymmetricMatrixSetSquare,\n HermitianPositiveSemidefiniteConeTriangle,\n },\n)\n\nSide dimension of the matrices in set.\n\nConvention\n\nBy convention, the side dimension should be stored in the side_dimension field. If this is not the case for a subtype of AbstractSymmetricMatrixSetTriangle, or AbstractSymmetricMatrixSetSquare you must implement this method.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.triangular_form","page":"Standard form","title":"MathOptInterface.triangular_form","text":"triangular_form(S::Type{<:AbstractSymmetricMatrixSetSquare})\ntriangular_form(set::AbstractSymmetricMatrixSetSquare)\n\nReturn the AbstractSymmetricMatrixSetTriangle corresponding to the vectorization of the upper triangular part of matrices in the AbstractSymmetricMatrixSetSquare set.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"List of recognized matrix sets.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"PositiveSemidefiniteConeTriangle\nPositiveSemidefiniteConeSquare\nHermitianPositiveSemidefiniteConeTriangle\nLogDetConeTriangle\nLogDetConeSquare\nRootDetConeTriangle\nRootDetConeSquare","category":"page"},{"location":"reference/standard_form/#MathOptInterface.PositiveSemidefiniteConeTriangle","page":"Standard form","title":"MathOptInterface.PositiveSemidefiniteConeTriangle","text":"PositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractSymmetricMatrixSetTriangle\n\nThe (vectorized) cone of symmetric positive semidefinite matrices, with non-negative side_dimension rows and columns.\n\nSee AbstractSymmetricMatrixSetTriangle for more details on the vectorized form.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.PositiveSemidefiniteConeSquare","page":"Standard form","title":"MathOptInterface.PositiveSemidefiniteConeSquare","text":"PositiveSemidefiniteConeSquare(side_dimension::Int) <: AbstractSymmetricMatrixSetSquare\n\nThe cone of symmetric positive semidefinite matrices, with non-negative side length side_dimension.\n\nSee AbstractSymmetricMatrixSetSquare for more details on the vectorized form.\n\nThe entries of the matrix are given column by column (or equivalently, row by row).\n\nThe matrix is both constrained to be symmetric and to be positive semidefinite. That is, if the functions in entries (i j) and (j i) are different, then a constraint will be added to make sure that the entries are equal.\n\nExample\n\nConstraining the matrix\n\nbeginbmatrix\n 1 -y\n -z 0\nendbmatrix\n\nto be symmetric positive semidefinite can be achieved by constraining the vector (1 -z -y 0) (or (1 -y -z 0)) to belong to the PositiveSemidefiniteConeSquare(2).\n\nIt both constrains y = z and (1 -y 0) (or (1 -z 0)) to be in PositiveSemidefiniteConeTriangle(2).\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.HermitianPositiveSemidefiniteConeTriangle","page":"Standard form","title":"MathOptInterface.HermitianPositiveSemidefiniteConeTriangle","text":"HermitianPositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractVectorSet\n\nThe (vectorized) cone of Hermitian positive semidefinite matrices, with non-negative side_dimension rows and columns.\n\nBecaue the matrix is Hermitian, the diagonal elements are real, and the complex-valued lower triangular entries are obtained as the conjugate of corresponding upper triangular entries.\n\nVectorization format\n\nThe vectorized form starts with real part of the entries of the upper triangular part of the matrix, given column by column as explained in AbstractSymmetricMatrixSetSquare.\n\nIt is then followed by the imaginary part of the off-diagonal entries of the upper triangular part, also given column by column.\n\nFor example, the matrix\n\nbeginbmatrix\n 1 2 + 7im 4 + 8im\n 2 - 7im 3 5 + 9im\n 4 - 8im 5 - 9im 6\nendbmatrix\n\nhas side_dimension 3 and is represented as the vector 1 2 3 4 5 6 7 8 9.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.LogDetConeTriangle","page":"Standard form","title":"MathOptInterface.LogDetConeTriangle","text":"LogDetConeTriangle(side_dimension::Int)\n\nThe log-determinant cone (t u X) in mathbbR^2 + d(d+1)2 t le u log(det(Xu)) u 0 , where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle.\n\nThe non-negative argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; X]),\n MOI.LogDetConeTriangle(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeTriangle}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.LogDetConeSquare","page":"Standard form","title":"MathOptInterface.LogDetConeSquare","text":"LogDetConeSquare(side_dimension::Int)\n\nThe log-determinant cone (t u X) in mathbbR^2 + d^2 t le u log(det(Xu)) X text symmetric u 0 , where the matrix X is represented in the same format as in the PositiveSemidefiniteConeSquare.\n\nSimilarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric.\n\nThe non-negative argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = reshape(MOI.add_variables(model, 4), 2, 2)\n2×2 Matrix{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2) MOI.VariableIndex(4)\n MOI.VariableIndex(3) MOI.VariableIndex(5)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; vec(X)]),\n MOI.LogDetConeSquare(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeSquare}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.RootDetConeTriangle","page":"Standard form","title":"MathOptInterface.RootDetConeTriangle","text":"RootDetConeTriangle(side_dimension::Int)\n\nThe root-determinant cone (t X) in mathbbR^1 + d(d+1)2 t le det(X)^1d , where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle.\n\nThe non-negative argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; X]),\n MOI.RootDetConeTriangle(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeTriangle}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.RootDetConeSquare","page":"Standard form","title":"MathOptInterface.RootDetConeSquare","text":"RootDetConeSquare(side_dimension::Int)\n\nThe root-determinant cone (t X) in mathbbR^1 + d^2 t le det(X)^1d X text symmetric , where the matrix X is represented in the same format as PositiveSemidefiniteConeSquare.\n\nSimilarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric.\n\nThe non-negative argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = reshape(MOI.add_variables(model, 4), 2, 2)\n2×2 Matrix{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2) MOI.VariableIndex(4)\n MOI.VariableIndex(3) MOI.VariableIndex(5)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; vec(X)]),\n MOI.RootDetConeSquare(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeSquare}(1)\n\n\n\n\n\n","category":"type"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/latency/#Latency","page":"Latency","title":"Latency","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"MathOptInterface suffers the \"time-to-first-solve\" problem of start-up latency.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"This hurts both the user- and developer-experience of MathOptInterface. In the first case, because simple models have a multi-second delay before solving, and in the latter, because our tests take so long to run.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"This page contains some advice on profiling and fixing latency-related problems in the MathOptInterface.jl repository.","category":"page"},{"location":"tutorials/latency/#Background","page":"Latency","title":"Background","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Before reading this part of the documentation, you should familiarize yourself with the reasons for latency in Julia and how to fix them.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Read the blogposts on julialang.org on precompilation and SnoopCompile\nRead the SnoopCompile documentation.\nWatch Tim Holy's talk at JuliaCon 2021\nWatch the package development workshop at JuliaCon 2021","category":"page"},{"location":"tutorials/latency/#Causes","page":"Latency","title":"Causes","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"There are three main causes of latency in MathOptInterface:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"A large number of types\nLack of method ownership\nType-instability in the bridge layer","category":"page"},{"location":"tutorials/latency/#A-large-number-of-types","page":"Latency","title":"A large number of types","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Julia is very good at specializing method calls based on the input type. Each specialization has a compilation cost, but the benefit of faster run-time performance.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"The best-case scenario is for a method to be called a large number of times with a single set of argument types. The worst-case scenario is for a method to be called a single time for a large set of argument types.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Because of MathOptInterface's function-in-set formulation, we fall into the worst-case situation.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"This is a fundamental limitation of Julia, so there isn't much we can do about it. However, if we can precompile MathOptInterface, much of the cost can be shifted from start-up latency to the time it takes to precompile a package on installation.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"However, there are two things which make MathOptInterface hard to precompile.","category":"page"},{"location":"tutorials/latency/#Lack-of-method-ownership","page":"Latency","title":"Lack of method ownership","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Lack of method ownership happens when a call is made using a mix of structs and methods from different modules. Because of this, no single module \"owns\" the method that is being dispatched, and so it cannot be precompiled.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"tip: Tip\nThis is a slightly simplified explanation. Read the precompilation tutorial for a more in-depth discussion on back-edges.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Unfortunately, the design of MOI means that this is a frequent occurrence: we have a bunch of types in MOI.Utilities that wrap types defined in external packages (for example, the Optimizers), which implement methods of functions defined in MOI (for example, add_variable, add_constraint).","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Here's a simple example of method-ownership in practice:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"module MyMOI\nstruct Wrapper{T}\n inner::T\nend\noptimize!(x::Wrapper) = optimize!(x.inner)\nend # MyMOI\n\nmodule MyOptimizer\nusing ..MyMOI\nstruct Optimizer end\nMyMOI.optimize!(x::Optimizer) = 1\nend # MyOptimizer\n\nusing SnoopCompile\nmodel = MyMOI.Wrapper(MyOptimizer.Optimizer())\n\njulia> tinf = @snoopi_deep MyMOI.optimize!(model)\nInferenceTimingNode: 0.008256/0.008543 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 1 direct children","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"The result is that there was one method that required type inference. If we visualize tinf:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"using ProfileView\nProfileView.view(flamegraph(tinf))","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"we see a flamegraph with a large red-bar indicating that the method MyMOI.optimize(MyMOI.Wrapper{MyOptimizer.Optimizer}) cannot be precompiled.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"To fix this, we need to designate a module to \"own\" that method (that is, create a back-edge). The easiest way to do this is for MyOptimizer to call MyMOI.optimize(MyMOI.Wrapper{MyOptimizer.Optimizer}) during using MyOptimizer. Let's see that in practice:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"module MyMOI\nstruct Wrapper{T}\n inner::T\nend\noptimize(x::Wrapper) = optimize(x.inner)\nend # MyMOI\n\nmodule MyOptimizer\nusing ..MyMOI\nstruct Optimizer end\nMyMOI.optimize(x::Optimizer) = 1\n# The syntax of this let-while loop is very particular:\n# * `let ... end` keeps everything local to avoid polluting the MyOptimizer\n# namespace\n# * `while true ... break end` runs the code once, and forces Julia to compile\n# the inner loop, rather than interpret it.\nlet\n while true\n model = MyMOI.Wrapper(Optimizer())\n MyMOI.optimize(model)\n break\n end\nend\nend # MyOptimizer\n\nusing SnoopCompile\nmodel = MyMOI.Wrapper(MyOptimizer.Optimizer())\n\njulia> tinf = @snoopi_deep MyMOI.optimize(model)\nInferenceTimingNode: 0.006822/0.006822 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 0 direct children","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"There are now 0 direct children that required type inference because the method was already stored in MyOptimizer!","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Unfortunately, this trick only works if the call-chain is fully inferrable. If there are breaks (due to type instability), then the benefit of doing this is reduced. And unfortunately for us, the design of MathOptInterface has a lot of type instabilities.","category":"page"},{"location":"tutorials/latency/#Type-instability-in-the-bridge-layer","page":"Latency","title":"Type instability in the bridge layer","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Most of MathOptInterface is pretty good at ensuring type-stability. However, a key component is not type stable, and that is the bridging layer.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"In particular, the bridging layer defines Bridges.LazyBridgeOptimizer, which has fields like:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"struct LazyBridgeOptimizer\n constraint_bridge_types::Vector{Any}\n constraint_node::Dict{Tuple{Type,Type},ConstraintNode}\n constraint_types::Vector{Tuple{Type,Type}}\nend","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"This is because the LazyBridgeOptimizer needs to be able to deal with any function-in-set type passed to it, and we also allow users to pass additional bridges that they defined in external packages.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"So to recap, MathOptInterface suffers package latency because:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"there are a large number of types and functions\nand these are split between multiple modules, including external packages\nand there are type-instabilities like those in the bridging layer.","category":"page"},{"location":"tutorials/latency/#Resolutions","page":"Latency","title":"Resolutions","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"There are no magic solutions to reduce latency. Issue #1313 tracks progress on reducing latency in MathOptInterface.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"A useful script is the following (replace GLPK as needed):","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"import GLPK\nimport MathOptInterface as MOI\n\nfunction example_diet(optimizer, bridge)\n category_data = [\n 1800.0 2200.0;\n 91.0 Inf;\n 0.0 65.0;\n 0.0 1779.0\n ]\n cost = [2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59]\n food_data = [\n 410 24 26 730;\n 420 32 10 1190;\n 560 20 32 1800;\n 380 4 19 270;\n 320 12 10 930;\n 320 15 12 820;\n 320 31 12 1230;\n 100 8 2.5 125;\n 330 8 10 180\n ]\n bridge_model = if bridge\n MOI.instantiate(optimizer; with_bridge_type=Float64)\n else\n MOI.instantiate(optimizer)\n end\n model = MOI.Utilities.CachingOptimizer(\n MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),\n MOI.Utilities.AUTOMATIC,\n )\n MOI.Utilities.reset_optimizer(model, bridge_model)\n MOI.set(model, MOI.Silent(), true)\n nutrition = MOI.add_variables(model, size(category_data, 1))\n for (i, v) in enumerate(nutrition)\n MOI.add_constraint(model, v, MOI.GreaterThan(category_data[i, 1]))\n MOI.add_constraint(model, v, MOI.LessThan(category_data[i, 2]))\n end\n buy = MOI.add_variables(model, size(food_data, 1))\n MOI.add_constraint.(model, buy, MOI.GreaterThan(0.0))\n MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)\n f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(cost, buy), 0.0)\n MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)\n for (j, n) in enumerate(nutrition)\n f = MOI.ScalarAffineFunction(\n MOI.ScalarAffineTerm.(food_data[:, j], buy),\n 0.0,\n )\n push!(f.terms, MOI.ScalarAffineTerm(-1.0, n))\n MOI.add_constraint(model, f, MOI.EqualTo(0.0))\n end\n MOI.optimize!(model)\n term_status = MOI.get(model, MOI.TerminationStatus())\n @assert term_status == MOI.OPTIMAL\n MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction(\n MOI.ScalarAffineTerm.(1.0, [buy[end-1], buy[end]]),\n 0.0,\n ),\n MOI.LessThan(6.0),\n )\n MOI.optimize!(model)\n @assert MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE\n return\nend\n\nif length(ARGS) > 0\n bridge = get(ARGS, 2, \"\") != \"--no-bridge\"\n println(\"Running: $(ARGS[1]) $(get(ARGS, 2, \"\"))\")\n @time example_diet(GLPK.Optimizer, bridge)\n @time example_diet(GLPK.Optimizer, bridge)\n exit(0)\nend","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"You can create a flame-graph via","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"using SnoopComile\ntinf = @snoopi_deep example_diet(GLPK.Optimizer, true)\nusing ProfileView\nProfileView.view(flamegraph(tinf))","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Here's how things looked in mid-August 2021: (Image: flamegraph)","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"There are a few opportunities for improvement (non-red flames, particularly on the right). But the main problem is a large red (non-precompilable due to method ownership) flame.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/manipulating_expressions/#Manipulating-expressions","page":"Manipulating expressions","title":"Manipulating expressions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"This guide highlights a syntactically appealing way to build expressions at the MOI level, but also to look at their contents. It may be especially useful when writing models or bridge code.","category":"page"},{"location":"tutorials/manipulating_expressions/#Creating-functions","page":"Manipulating expressions","title":"Creating functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"This section details the ways to create functions with MathOptInterface.","category":"page"},{"location":"tutorials/manipulating_expressions/#Creating-scalar-affine-functions","page":"Manipulating expressions","title":"Creating scalar affine functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"The simplest scalar function is simply a variable:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> x = MOI.add_variable(model) # Create the variable x\nMOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"This type of function is extremely simple; to express more complex functions, other types must be used. For instance, a ScalarAffineFunction is a sum of linear terms (a factor times a variable) and a constant. Such an object can be built using the standard constructor:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1, x)], 2) # x + 2\n(2) + (1) MOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"However, you can also use operators to build the same scalar function:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> f = x + 2\n(2) + (1) MOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/#Creating-scalar-quadratic-functions","page":"Manipulating expressions","title":"Creating scalar quadratic functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Scalar quadratic functions are stored in ScalarQuadraticFunction objects, in a way that is highly similar to scalar affine functions. You can obtain a quadratic function as a product of affine functions:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> 1 * x * x\n(0) + 1.0 MOI.VariableIndex(1)²\n\njulia> f * f # (x + 2)²\n(4) + (2) MOI.VariableIndex(1) + (2) MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²\n\njulia> f^2 # (x + 2)² too\n(4) + (2) MOI.VariableIndex(1) + (2) MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²","category":"page"},{"location":"tutorials/manipulating_expressions/#Creating-vector-functions","page":"Manipulating expressions","title":"Creating vector functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"A vector function is a function with several values, irrespective of the number of input variables. Similarly to scalar functions, there are three main types of vector functions: VectorOfVariables, VectorAffineFunction, and VectorQuadraticFunction.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"The easiest way to create a vector function is to stack several scalar functions using Utilities.vectorize. It takes a vector as input, and the generated vector function (of the most appropriate type) has each dimension corresponding to a dimension of the vector.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> g = MOI.Utilities.vectorize([f, 2 * f])\n┌ ┐\n│(2) + (1) MOI.VariableIndex(1)│\n│(4) + (2) MOI.VariableIndex(1)│\n└ ┘","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"warning: Warning\nUtilities.vectorize only takes a vector of similar scalar functions: you cannot mix VariableIndex and ScalarAffineFunction, for instance. In practice, it means that Utilities.vectorize([x, f]) does not work; you should rather use Utilities.vectorize([1 * x, f]) instead to only have ScalarAffineFunction objects.","category":"page"},{"location":"tutorials/manipulating_expressions/#Canonicalizing-functions","page":"Manipulating expressions","title":"Canonicalizing functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"In more advanced use cases, you might need to ensure that a function is \"canonical.\" Functions are stored as an array of terms, but there is no check that these terms are redundant: a ScalarAffineFunction object might have two terms with the same variable, like x + x + 1. These terms could be merged without changing the semantics of the function: 2x + 1.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Working with these objects might be cumbersome. Canonicalization helps maintain redundancy to zero.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Utilities.is_canonical checks whether a function is already in its canonical form:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> MOI.Utilities.is_canonical(f + f) # (x + 2) + (x + 2) is stored as x + x + 4\nfalse","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Utilities.canonical returns the equivalent canonical version of the function:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> MOI.Utilities.canonical(f + f) # Returns 2x + 4\n(4) + (2) MOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/#Exploring-functions","page":"Manipulating expressions","title":"Exploring functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"At some point, you might need to dig into a function, for instance to map it into solver constructs.","category":"page"},{"location":"tutorials/manipulating_expressions/#Vector-functions","page":"Manipulating expressions","title":"Vector functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Utilities.scalarize returns a vector of scalar functions from a vector function:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> MOI.Utilities.scalarize(g) # Returns a vector [f, 2 * f].\n2-element Vector{MathOptInterface.ScalarAffineFunction{Int64}}:\n (2) + (1) MOI.VariableIndex(1)\n (4) + (2) MOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"note: Note\nUtilities.eachscalar returns an iterator on the dimensions, which serves the same purpose as Utilities.scalarize.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"output_dimension returns the number of dimensions of the output of a function:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> MOI.output_dimension(g)\n2","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/solutions/#manual_solutions","page":"Solutions","title":"Solutions","text":"","category":"section"},{"location":"manual/solutions/#Solving-and-retrieving-the-results","page":"Solutions","title":"Solving and retrieving the results","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Once an optimizer is loaded with the objective function and all of the constraints, we can ask the solver to solve the model by calling optimize!.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"MOI.optimize!(optimizer)","category":"page"},{"location":"manual/solutions/#Why-did-the-solver-stop?","page":"Solutions","title":"Why did the solver stop?","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"The optimization procedure may stop for a number of reasons. The TerminationStatus attribute of the optimizer returns a TerminationStatusCode object which explains why the solver stopped.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"The termination statuses distinguish between proofs of optimality, infeasibility, local convergence, limits, and termination because of something unexpected like invalid problem data or failure to converge.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"A typical usage of the TerminationStatus attribute is as follows:","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"status = MOI.get(optimizer, TerminationStatus())\nif status == MOI.OPTIMAL\n # Ok, we solved the problem!\nelse\n # Handle other cases.\nend","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"After checking the TerminationStatus, check ResultCount. This attribute returns the number of results that the solver has available to return. A result is defined as a primal-dual pair, but either the primal or the dual may be missing from the result. While the OPTIMAL termination status normally implies that at least one result is available, other statuses do not. For example, in the case of infeasibility, a solver may return no result or a proof of infeasibility. The ResultCount attribute distinguishes between these two cases.","category":"page"},{"location":"manual/solutions/#Primal-solutions","page":"Solutions","title":"Primal solutions","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Use the PrimalStatus optimizer attribute to return a ResultStatusCode describing the status of the primal solution.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Common returns are described below in the Common status situations section.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Query the primal solution using the VariablePrimal and ConstraintPrimal attributes.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Query the objective function value using the ObjectiveValue attribute.","category":"page"},{"location":"manual/solutions/#Dual-solutions","page":"Solutions","title":"Dual solutions","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"warning: Warning\nSee Duality for a discussion of the MOI conventions for primal-dual pairs and certificates.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Use the DualStatus optimizer attribute to return a ResultStatusCode describing the status of the dual solution.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Query the dual solution using the ConstraintDual attribute.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Query the dual objective function value using the DualObjectiveValue attribute.","category":"page"},{"location":"manual/solutions/#Common-status-situations","page":"Solutions","title":"Common status situations","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"The sections below describe how to interpret typical or interesting status cases for three common classes of solvers. The example cases are illustrative, not comprehensive. Solver wrappers may provide additional information on how the solver's statuses map to MOI statuses.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"info: Info\n* in the tables indicate that multiple different values are possible.","category":"page"},{"location":"manual/solutions/#Primal-dual-convex-solver","page":"Solutions","title":"Primal-dual convex solver","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Linear programming and conic optimization solvers fall into this category.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"What happened? TerminationStatus ResultCount PrimalStatus DualStatus\nProved optimality OPTIMAL 1 FEASIBLE_POINT FEASIBLE_POINT\nProved infeasible INFEASIBLE 1 NO_SOLUTION INFEASIBILITY_CERTIFICATE\nOptimal within relaxed tolerances ALMOST_OPTIMAL 1 FEASIBLE_POINT FEASIBLE_POINT\nOptimal within relaxed tolerances ALMOST_OPTIMAL 1 ALMOST_FEASIBLE_POINT ALMOST_FEASIBLE_POINT\nDetected an unbounded ray of the primal DUAL_INFEASIBLE 1 INFEASIBILITY_CERTIFICATE NO_SOLUTION\nStall SLOW_PROGRESS 1 * *","category":"page"},{"location":"manual/solutions/#Global-branch-and-bound-solvers","page":"Solutions","title":"Global branch-and-bound solvers","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Mixed-integer programming solvers fall into this category.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"What happened? TerminationStatus ResultCount PrimalStatus DualStatus\nProved optimality OPTIMAL 1 FEASIBLE_POINT NO_SOLUTION\nPresolve detected infeasibility or unboundedness INFEASIBLE_OR_UNBOUNDED 0 NO_SOLUTION NO_SOLUTION\nProved infeasibility INFEASIBLE 0 NO_SOLUTION NO_SOLUTION\nTimed out (no solution) TIME_LIMIT 0 NO_SOLUTION NO_SOLUTION\nTimed out (with a solution) TIME_LIMIT 1 FEASIBLE_POINT NO_SOLUTION\nCPXMIP_OPTIMAL_INFEAS ALMOST_OPTIMAL 1 INFEASIBLE_POINT NO_SOLUTION","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"info: Info\nCPXMIP_OPTIMAL_INFEAS is a CPLEX status that indicates that a preprocessed problem was solved to optimality, but the solver was unable to recover a feasible solution to the original problem. Handling this status was one of the motivating drivers behind the design of MOI.","category":"page"},{"location":"manual/solutions/#Local-search-solvers","page":"Solutions","title":"Local search solvers","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Nonlinear programming solvers fall into this category. It also includes non-global tree search solvers like Juniper.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"What happened? TerminationStatus ResultCount PrimalStatus DualStatus\nConverged to a stationary point LOCALLY_SOLVED 1 FEASIBLE_POINT FEASIBLE_POINT\nCompleted a non-global tree search (with a solution) LOCALLY_SOLVED 1 FEASIBLE_POINT FEASIBLE_POINT\nConverged to an infeasible point LOCALLY_INFEASIBLE 1 INFEASIBLE_POINT *\nCompleted a non-global tree search (no solution found) LOCALLY_INFEASIBLE 0 NO_SOLUTION NO_SOLUTION\nIteration limit ITERATION_LIMIT 1 * *\nDiverging iterates NORM_LIMIT or OBJECTIVE_LIMIT 1 * *","category":"page"},{"location":"manual/solutions/#Querying-solution-attributes","page":"Solutions","title":"Querying solution attributes","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Some solvers will not implement every solution attribute. Therefore, a call like MOI.get(model, MOI.SolveTimeSec()) may throw an UnsupportedAttribute error.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"If you need to write code that is agnostic to the solver (for example, you are writing a library that an end-user passes their choice of solver to), you can work-around this problem using a try-catch:","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"function get_solve_time(model)\n try\n return MOI.get(model, MOI.SolveTimeSec())\n catch err\n if err isa MOI.UnsupportedAttribute\n return NaN # Solver doesn't support. Return a placeholder value.\n end\n rethrow(err) # Something else went wrong. Rethrow the error\n end\nend","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"If, after careful profiling, you find that the try-catch is taking a significant portion of your runtime, you can improve performance by caching the result of the try-catch:","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"mutable struct CachedSolveTime{M}\n model::M\n supports_solve_time::Bool\n CachedSolveTime(model::M) where {M} = new(model, true)\nend\n\nfunction get_solve_time(model::CachedSolveTime)\n if !model.supports_solve_time\n return NaN\n end\n try\n return MOI.get(model, MOI.SolveTimeSec())\n catch err\n if err isa MOI.UnsupportedAttribute\n model.supports_solve_time = false\n return NaN\n end\n rethrow(err) # Something else went wrong. Rethrow the error\n end\nend","category":"page"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Bridges/reference/#Bridges","page":"API Reference","title":"Bridges","text":"","category":"section"},{"location":"submodules/Bridges/reference/#AbstractBridge-API","page":"API Reference","title":"AbstractBridge API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.AbstractBridge\nBridges.added_constrained_variable_types\nBridges.added_constraint_types\nget(::Bridges.AbstractBridge, ::NumberOfVariables)\nget(::Bridges.AbstractBridge, ::ListOfVariableIndices)\nget(::Bridges.AbstractBridge, ::NumberOfConstraints)\nget(::Bridges.AbstractBridge, ::ListOfConstraintIndices)\nBridges.needs_final_touch\nBridges.final_touch\nBridges.bridging_cost","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.AbstractBridge","page":"API Reference","title":"MathOptInterface.Bridges.AbstractBridge","text":"abstract type AbstractBridge end\n\nAn abstract type representing a bridged constraint or variable in a MOI.Bridges.AbstractBridgeOptimizer.\n\nAll bridges must implement:\n\nadded_constrained_variable_types\nadded_constraint_types\nMOI.get(::AbstractBridge, ::MOI.NumberOfVariables)\nMOI.get(::AbstractBridge, ::MOI.ListOfVariableIndices)\nMOI.get(::AbstractBridge, ::MOI.NumberOfConstraints)\nMOI.get(::AbstractBridge, ::MOI.ListOfConstraintIndices)\n\nSubtypes of AbstractBridge may have additional requirements. Consult their docstrings for details.\n\nIn addition, all subtypes may optionally implement the following constraint attributes with the bridge in place of the constraint index:\n\nMOI.ConstraintDual\nMOI.ConstraintPrimal\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.added_constrained_variable_types","page":"API Reference","title":"MathOptInterface.Bridges.added_constrained_variable_types","text":"added_constrained_variable_types(\n BT::Type{<:AbstractBridge},\n)::Vector{Tuple{Type}}\n\nReturn a list of the types of constrained variables that bridges of concrete type BT add.\n\nImplementation notes\n\nThis method depends only on the type of the bridge, not the runtime value. If the bridge may add a constrained variable, the type must be included in the return vector.\nIf the bridge adds a free variable via MOI.add_variable or MOI.add_variables, the return vector must include (MOI.Reals,).\n\nExample\n\njulia> MOI.Bridges.added_constrained_variable_types(\n MOI.Bridges.Variable.NonposToNonnegBridge{Float64},\n )\n1-element Vector{Tuple{Type}}:\n (MathOptInterface.Nonnegatives,)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.added_constraint_types","page":"API Reference","title":"MathOptInterface.Bridges.added_constraint_types","text":"added_constraint_types(\n BT::Type{<:AbstractBridge},\n)::Vector{Tuple{Type,Type}}\n\nReturn a list of the types of constraints that bridges of concrete type BT add.\n\nImplementation notes\n\nThis method depends only on the type of the bridge, not the runtime value. If the bridge may add a constraint, the type must be included in the return vector.\n\nExample\n\njulia> MOI.Bridges.added_constraint_types(\n MOI.Bridges.Constraint.ZeroOneBridge{Float64},\n )\n2-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.Interval{Float64})\n (MathOptInterface.VariableIndex, MathOptInterface.Integer)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.get-Tuple{MathOptInterface.Bridges.AbstractBridge, MathOptInterface.NumberOfVariables}","page":"API Reference","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64\n\nReturn the number of variables created by the bridge b in the model.\n\nSee also MOI.NumberOfConstraints.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this if the bridge adds new variables.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.get-Tuple{MathOptInterface.Bridges.AbstractBridge, MathOptInterface.ListOfVariableIndices}","page":"API Reference","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)\n\nReturn the list of variables created by the bridge b.\n\nSee also MOI.ListOfVariableIndices.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this if the bridge adds new variables.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.get-Tuple{MathOptInterface.Bridges.AbstractBridge, MathOptInterface.NumberOfConstraints}","page":"API Reference","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}\n\nReturn the number of constraints of the type F-in-S created by the bridge b.\n\nSee also MOI.NumberOfConstraints.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.get-Tuple{MathOptInterface.Bridges.AbstractBridge, MathOptInterface.ListOfConstraintIndices}","page":"API Reference","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}\n\nReturn a Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-in-S created by the bride b.\n\nSee also MOI.ListOfConstraintIndices.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.needs_final_touch","page":"API Reference","title":"MathOptInterface.Bridges.needs_final_touch","text":"needs_final_touch(bridge::AbstractBridge)::Bool\n\nReturn whether final_touch is implemented by bridge.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.final_touch","page":"API Reference","title":"MathOptInterface.Bridges.final_touch","text":"final_touch(bridge::AbstractBridge, model::MOI.ModelLike)::Nothing\n\nA function that is called immediately prior to MOI.optimize! to allow bridges to modify their reformulations with repsect to other variables and constraints in model.\n\nFor example, if the correctness of bridge depends on the bounds of a variable or the fact that variables are integer, then the bridge can implement final_touch to check assumptions immediately before a call to MOI.optimize!.\n\nIf you implement this method, you must also implement needs_final_touch.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.bridging_cost","page":"API Reference","title":"MathOptInterface.Bridges.bridging_cost","text":"bridging_cost(b::AbstractBridgeOptimizer, S::Type{<:MOI.AbstractSet}})\n\nReturn the cost of bridging variables constrained in S on creation, is_bridged(b, S) is assumed to be true.\n\nbridging_cost(\n b::AbstractBridgeOptimizer,\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet},\n)\n\nReturn the cost of bridging F-in-S constraints.\n\nis_bridged(b, S) is assumed to be true.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#Constraint-bridge-API","page":"API Reference","title":"Constraint bridge API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.Constraint.AbstractBridge\nsupports_constraint(::Type{<:Bridges.Constraint.AbstractBridge}, ::Type{<:AbstractFunction}, ::Type{<:AbstractSet})\nBridges.Constraint.concrete_bridge_type\nBridges.Constraint.bridge_constraint\nBridges.Constraint.AbstractFunctionConversionBridge\nBridges.Constraint.SingleBridgeOptimizer\nBridges.Constraint.add_all_bridges\nBridges.Constraint.FlipSignBridge\nBridges.Constraint.AbstractToIntervalBridge\nBridges.Constraint.SetMapBridge\nBridges.Constraint.conversion_cost","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.AbstractBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.AbstractBridge","text":"abstract type AbstractBridge <: MOI.Bridges.AbstractType\n\nSubtype of MOI.Bridges.AbstractBridge for constraint bridges.\n\nIn addition to the required implementation described in MOI.Bridges.AbstractBridge, subtypes of AbstractBridge must additionally implement:\n\nMOI.supports_constraint(::Type{<:AbstractBridge}, ::Type{<:MOI.AbstractFunction}, ::Type{<:MOI.AbstractSet})\nconcrete_bridge_type\nbridge_constraint\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.supports_constraint-Tuple{Type{<:MathOptInterface.Bridges.Constraint.AbstractBridge}, Type{<:MathOptInterface.AbstractFunction}, Type{<:MathOptInterface.AbstractSet}}","page":"API Reference","title":"MathOptInterface.supports_constraint","text":"MOI.supports_constraint(\n BT::Type{<:AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet},\n)::Bool\n\nReturn a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.\n\nImplementation notes\n\nThis method depends only on the type of the inputs, not the runtime values.\nThere is a default fallback, so you need only implement this method for constraint types that the bridge implements.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.concrete_bridge_type","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.concrete_bridge_type","text":"concrete_bridge_type(\n BT::Type{<:AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet}\n)::Type\n\nReturn the concrete type of the bridge supporting F-in-S constraints.\n\nThis function can only be called if MOI.supports_constraint(BT, F, S) is true.\n\nExample\n\nThe SplitIntervalBridge bridges a MOI.VariableIndex-in-MOI.Interval constraint into a MOI.VariableIndex-in-MOI.GreaterThan and a MOI.VariableIndex-in-MOI.LessThan constraint.\n\njulia> MOI.Bridges.Constraint.concrete_bridge_type(\n MOI.Bridges.Constraint.SplitIntervalBridge{Float64},\n MOI.VariableIndex,\n MOI.Interval{Float64},\n )\nMathOptInterface.Bridges.Constraint.SplitIntervalBridge{Float64, MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}, MathOptInterface.GreaterThan{Float64}, MathOptInterface.LessThan{Float64}}\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.bridge_constraint","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.bridge_constraint","text":"bridge_constraint(\n BT::Type{<:AbstractBridge},\n model::MOI.ModelLike,\n func::AbstractFunction,\n set::MOI.AbstractSet,\n)::BT\n\nBridge the constraint func-in-set using bridge BT to model and returns a bridge object of type BT.\n\nImplementation notes\n\nThe bridge type BT should be a concrete type, that is, all the type parameters of the bridge must be set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.AbstractFunctionConversionBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.AbstractFunctionConversionBridge","text":"abstract type AbstractFunctionConversionBridge{F,S} <: AbstractBridge end\n\nAbstract type to support writing bridges in which the function changes but the set does not.\n\nBy convention, the transformed function is stored in the .constraint field.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.SingleBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.SingleBridgeOptimizer","text":"SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)\n\nReturn AbstractBridgeOptimizer that always bridges any objective function supported by the bridge BT.\n\nThis is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the objective function if it is supported by the bridge BT and unsupported by model.\n\nExample\n\njulia> struct MyNewBridge{T} <: MOI.Bridges.Constraint.AbstractBridge end\n\njulia> bridge = MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}}(\n MOI.Utilities.Model{Float64}(),\n )\nMOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 constraint bridges\nwith inner model MOIU.Model{Float64}\n\nImplementation notes\n\nAll bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.\n\njulia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =\n MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{T},OT};\n\nThis enables users to create bridged models as follows:\n\njulia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())\nMOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 constraint bridges\nwith inner model MOIU.Model{Float64}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.add_all_bridges","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.add_all_bridges","text":"add_all_bridges(bridged_model, ::Type{T}) where {T}\n\nAdd all bridges defined in the Bridges.Constraint submodule to bridged_model. The coefficient type used is T.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.FlipSignBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.FlipSignBridge","text":"FlipSignBridge{T,S1,S2,F,G}\n\nAn abstract type that simplifies the creation of other bridges.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.AbstractToIntervalBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.AbstractToIntervalBridge","text":"AbstractToIntervalBridge{T<:AbstractFloat,S,F}\n\nAn abstract type that simplifies the creation of other bridges.\n\nwarning: Warning\nT must be a AbstractFloat type because otherwise typemin and typemax would either be not implemented (e.g. BigInt), or would not give infinite value (e.g. Int). For this reason, this bridge is only added to MOI.Bridges.full_bridge_optimizer when T is a subtype of AbstractFloat.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.SetMapBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.SetMapBridge","text":"abstract type SetMapBridge{T,S2,S1,F,G} <: AbstractBridge end\n\nConsider two type of sets, S1 and S2, and a linear mapping A such that the image of a set of type S1 under A is a set of type S2.\n\nA SetMapBridge{T,S2,S1,F,G} is a bridge that maps G-in-S1 constraints into F-in-S2 by mapping the function through A.\n\nThe linear map A is described by;\n\nMOI.Bridges.map_set\nMOI.Bridges.map_function.\n\nImplementing a method for these two functions is sufficient to bridge constraints. However, in order for the getters and setters of attributes such as dual solutions and starting values to work as well, a method for the following functions must be implemented:\n\nMOI.Bridges.inverse_map_set\nMOI.Bridges.inverse_map_function\nMOI.Bridges.adjoint_map_function\nMOI.Bridges.inverse_adjoint_map_function\n\nSee the docstrings of each function to see which feature would be missing if it was not implemented for a given bridge.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.conversion_cost","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.conversion_cost","text":"conversion_cost(\n F::Type{<:MOI.AbstractFunction},\n G::Type{<:MOI.AbstractFunction},\n)::Float64\n\nReturn a Float64 returning the cost of converting any function of type G to a function of type F with convert.\n\nThis cost is used to compute MOI.Bridges.bridging_cost.\n\nThe default cost is Inf, which means that MOI.Bridges.Constraint.FunctionConversionBridge should not attempt the conversion.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#Objective-bridge-API","page":"API Reference","title":"Objective bridge API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.Objective.AbstractBridge\nBridges.Objective.supports_objective_function\nBridges.set_objective_function_type\nBridges.Objective.concrete_bridge_type\nBridges.Objective.bridge_objective\nBridges.Objective.SingleBridgeOptimizer\nBridges.Objective.add_all_bridges","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.AbstractBridge","page":"API Reference","title":"MathOptInterface.Bridges.Objective.AbstractBridge","text":"abstract type AbstractBridge <: MOI.Bridges.AbstractBridge end\n\nSubtype of MOI.Bridges.AbstractBridge for objective bridges.\n\nIn addition to the required implementation described in MOI.Bridges.AbstractBridge, subtypes of AbstractBridge must additionally implement:\n\nsupports_objective_function\nconcrete_bridge_type\nbridge_objective\nMOI.Bridges.set_objective_function_type\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.supports_objective_function","page":"API Reference","title":"MathOptInterface.Bridges.Objective.supports_objective_function","text":"supports_objective_function(\n BT::Type{<:MOI.Bridges.Objective.AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n)::Bool\n\nReturn a Bool indicating whether the bridges of type BT support bridging objective functions of type F.\n\nImplementation notes\n\nThis method depends only on the type of the inputs, not the runtime values.\nThere is a default fallback, so you need only implement this method For objective functions that the bridge implements.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.set_objective_function_type","page":"API Reference","title":"MathOptInterface.Bridges.set_objective_function_type","text":"set_objective_function_type(\n BT::Type{<:Objective.AbstractBridge},\n)::Type{<:MOI.AbstractFunction}\n\nReturn the type of objective function that bridges of concrete type BT set.\n\nImplementation notes\n\nThis method depends only on the type of the bridge, not the runtime value.\n\nExample\n\njulia> MOI.Bridges.set_objective_function_type(\n MOI.Bridges.Objective.FunctionizeBridge{Float64},\n )\nMathOptInterface.ScalarAffineFunction{Float64}\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.concrete_bridge_type","page":"API Reference","title":"MathOptInterface.Bridges.Objective.concrete_bridge_type","text":"concrete_bridge_type(\n BT::Type{<:MOI.Bridges.Objective.AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n)::Type\n\nReturn the concrete type of the bridge supporting objective functions of type F.\n\nThis function can only be called if MOI.supports_objective_function(BT, F) is true.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.bridge_objective","page":"API Reference","title":"MathOptInterface.Bridges.Objective.bridge_objective","text":"bridge_objective(\n BT::Type{<:MOI.Bridges.Objective.AbstractBridge},\n model::MOI.ModelLike,\n func::MOI.AbstractFunction,\n)::BT\n\nBridge the objective function func using bridge BT to model and returns a bridge object of type BT.\n\nImplementation notes\n\nThe bridge type BT must be a concrete type, that is, all the type parameters of the bridge must be set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.SingleBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.Objective.SingleBridgeOptimizer","text":"SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)\n\nReturn AbstractBridgeOptimizer that always bridges any objective function supported by the bridge BT.\n\nThis is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the objective function if it is supported by the bridge BT and unsupported by model.\n\nExample\n\njulia> struct MyNewBridge{T} <: MOI.Bridges.Objective.AbstractBridge end\n\njulia> bridge = MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}}(\n MOI.Utilities.Model{Float64}(),\n )\nMOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}\n\nImplementation notes\n\nAll bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.\n\njulia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =\n MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{T},OT};\n\nThis enables users to create bridged models as follows:\n\njulia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())\nMOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.add_all_bridges","page":"API Reference","title":"MathOptInterface.Bridges.Objective.add_all_bridges","text":"add_all_bridges(model, ::Type{T}) where {T}\n\nAdd all bridges defined in the Bridges.Objective submodule to model.\n\nThe coefficient type used is T.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#ref_variable_bridges","page":"API Reference","title":"Variable bridge API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.Variable.AbstractBridge\nBridges.Variable.supports_constrained_variable\nBridges.Variable.concrete_bridge_type\nBridges.Variable.bridge_constrained_variable\nBridges.Variable.SingleBridgeOptimizer\nBridges.Variable.add_all_bridges\nBridges.Variable.FlipSignBridge\nBridges.Variable.SetMapBridge\nBridges.Variable.unbridged_map","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.AbstractBridge","page":"API Reference","title":"MathOptInterface.Bridges.Variable.AbstractBridge","text":"abstract type AbstractBridge <: MOI.Bridges.AbstractBridge end\n\nSubtype of MOI.Bridges.AbstractBridge for variable bridges.\n\nIn addition to the required implementation described in MOI.Bridges.AbstractBridge, subtypes of AbstractBridge must additionally implement:\n\nsupports_constrained_variable\nconcrete_bridge_type\nbridge_constrained_variable\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.supports_constrained_variable","page":"API Reference","title":"MathOptInterface.Bridges.Variable.supports_constrained_variable","text":"supports_constrained_variable(\n BT::Type{<:AbstractBridge},\n S::Type{<:MOI.AbstractSet},\n)::Bool\n\nReturn a Bool indicating whether the bridges of type BT support bridging constrained variables in S. That is, it returns true if the bridge of type BT converts constrained variables of type S into a form supported by the solver.\n\nImplementation notes\n\nThis method depends only on the type of the bridge and set, not the runtime values.\nThere is a default fallback, so you need only implement this method for sets that the bridge implements.\n\nExample\n\njulia> MOI.Bridges.Variable.supports_constrained_variable(\n MOI.Bridges.Variable.NonposToNonnegBridge{Float64},\n MOI.Nonpositives,\n )\ntrue\n\njulia> MOI.Bridges.Variable.supports_constrained_variable(\n MOI.Bridges.Variable.NonposToNonnegBridge{Float64},\n MOI.Nonnegatives,\n )\nfalse\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.concrete_bridge_type","page":"API Reference","title":"MathOptInterface.Bridges.Variable.concrete_bridge_type","text":"concrete_bridge_type(\n BT::Type{<:AbstractBridge},\n S::Type{<:MOI.AbstractSet},\n)::Type\n\nReturn the concrete type of the bridge supporting variables in S constraints.\n\nThis function can only be called if MOI.supports_constrained_variable(BT, S) is true.\n\nExamples\n\nAs a variable in MOI.GreaterThan is bridged into variables in MOI.Nonnegatives by the VectorizeBridge:\n\njulia> MOI.Bridges.Variable.concrete_bridge_type(\n MOI.Bridges.Variable.VectorizeBridge{Float64},\n MOI.GreaterThan{Float64},\n )\nMathOptInterface.Bridges.Variable.VectorizeBridge{Float64, MathOptInterface.Nonnegatives}\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.bridge_constrained_variable","page":"API Reference","title":"MathOptInterface.Bridges.Variable.bridge_constrained_variable","text":"bridge_constrained_variable(\n BT::Type{<:AbstractBridge},\n model::MOI.ModelLike,\n set::MOI.AbstractSet,\n)::BT\n\nBridge the constrained variable in set using bridge BT to model and returns a bridge object of type BT.\n\nImplementation notes\n\nThe bridge type BT must be a concrete type, that is, all the type parameters of the bridge must be set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.SingleBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.Variable.SingleBridgeOptimizer","text":"SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)\n\nReturn MOI.Bridges.AbstractBridgeOptimizer that always bridges any variables constrained on creation supported by the bridge BT.\n\nThis is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the variables constrained on creation if they are supported by the bridge BT and unsupported by model.\n\nwarning: Warning\nTwo SingleBridgeOptimizers cannot be used together as both of them assume that the underlying model only returns variable indices with nonnegative values. Use MOI.Bridges.LazyBridgeOptimizer instead.\n\nExample\n\njulia> struct MyNewBridge{T} <: MOI.Bridges.Variable.AbstractBridge end\n\njulia> bridge = MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}}(\n MOI.Utilities.Model{Float64}(),\n )\nMOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 variable bridges\nwith inner model MOIU.Model{Float64}\n\nImplementation notes\n\nAll bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.\n\njulia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =\n MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{T},OT};\n\nThis enables users to create bridged models as follows:\n\njulia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())\nMOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 variable bridges\nwith inner model MOIU.Model{Float64}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.add_all_bridges","page":"API Reference","title":"MathOptInterface.Bridges.Variable.add_all_bridges","text":"add_all_bridges(model, ::Type{T}) where {T}\n\nAdd all bridges defined in the Bridges.Variable submodule to model.\n\nThe coefficient type used is T.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.FlipSignBridge","page":"API Reference","title":"MathOptInterface.Bridges.Variable.FlipSignBridge","text":"abstract type FlipSignBridge{T,S1,S2} <: SetMapBridge{T,S2,S1} end\n\nAn abstract type that simplifies the creation of other bridges.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.SetMapBridge","page":"API Reference","title":"MathOptInterface.Bridges.Variable.SetMapBridge","text":"abstract type SetMapBridge{T,S1,S2} <: AbstractBridge end\n\nConsider two type of sets, S1 and S2, and a linear mapping A such that the image of a set of type S1 under A is a set of type S2.\n\nA SetMapBridge{T,S1,S2} is a bridge that substitutes constrained variables in S2 into the image through A of constrained variables in S1.\n\nThe linear map A is described by:\n\nMOI.Bridges.map_set\nMOI.Bridges.map_function\n\nImplementing a method for these two functions is sufficient to bridge constrained variables. However, in order for the getters and setters of attributes such as dual solutions and starting values to work as well, a method for the following functions must be implemented:\n\nMOI.Bridges.inverse_map_set\nMOI.Bridges.inverse_map_function\nMOI.Bridges.adjoint_map_function\nMOI.Bridges.inverse_adjoint_map_function.\n\nSee the docstrings of each function to see which feature would be missing if it was not implemented for a given bridge.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.unbridged_map","page":"API Reference","title":"MathOptInterface.Bridges.Variable.unbridged_map","text":"unbridged_map(\n bridge::MOI.Bridges.Variable.AbstractBridge,\n vi::MOI.VariableIndex,\n)\n\nFor a bridged variable in a scalar set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vi.\n\nunbridged_map(\n bridge::MOI.Bridges.Variable.AbstractBridge,\n vis::Vector{MOI.VariableIndex},\n)\n\nFor a bridged variable in a vector set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vis. If this method is not implemented, it falls back to calling the following method for every variable of vis.\n\nunbridged_map(\n bridge::MOI.Bridges.Variable.AbstractBridge,\n vi::MOI.VariableIndex,\n i::MOI.Bridges.IndexInVector,\n)\n\nFor a bridged variable in a vector set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vi corresponding to the ith variable of the vector.\n\nIf there is no way to recover the expression in terms of the bridged variable(s) vi(s), return nothing. See ZerosBridge for an example of bridge returning nothing.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#AbstractBridgeOptimizer-API","page":"API Reference","title":"AbstractBridgeOptimizer API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.AbstractBridgeOptimizer\nBridges.bridged_variable_function\nBridges.unbridged_variable_function\nBridges.bridged_function\nBridges.supports_constraint_bridges\nBridges.recursive_model","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.AbstractBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.AbstractBridgeOptimizer","text":"abstract type AbstractBridgeOptimizer <: MOI.AbstractOptimizer end\n\nAn abstract type that implements generic functions for bridges.\n\nImplementation notes\n\nBy convention, the inner optimizer should be stored in a model field. If not, the optimizer must implement MOI.optimize!.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.bridged_variable_function","page":"API Reference","title":"MathOptInterface.Bridges.bridged_variable_function","text":"bridged_variable_function(\n b::AbstractBridgeOptimizer,\n vi::MOI.VariableIndex,\n)\n\nReturn a MOI.AbstractScalarFunction of variables of b.model that equals vi. That is, if the variable vi is bridged, it returns its expression in terms of the variables of b.model. Otherwise, it returns vi.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.unbridged_variable_function","page":"API Reference","title":"MathOptInterface.Bridges.unbridged_variable_function","text":"unbridged_variable_function(\n b::AbstractBridgeOptimizer,\n vi::MOI.VariableIndex,\n)\n\nReturn a MOI.AbstractScalarFunction of variables of b that equals vi. That is, if the variable vi is an internal variable of b.model created by a bridge but not visible to the user, it returns its expression in terms of the variables of bridged variables. Otherwise, it returns vi.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.bridged_function","page":"API Reference","title":"MathOptInterface.Bridges.bridged_function","text":"bridged_function(b::AbstractBridgeOptimizer, value)::typeof(value)\n\nSubstitute any bridged MOI.VariableIndex in value by an equivalent expression in terms of variables of b.model.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.supports_constraint_bridges","page":"API Reference","title":"MathOptInterface.Bridges.supports_constraint_bridges","text":"supports_constraint_bridges(b::AbstractBridgeOptimizer)::Bool\n\nReturn a Bool indicating if b supports MOI.Bridges.Constraint.AbstractBridge.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.recursive_model","page":"API Reference","title":"MathOptInterface.Bridges.recursive_model","text":"recursive_model(b::AbstractBridgeOptimizer)\n\nIf a variable, constraint, or objective is bridged, return the context of the inner variables. For most optimizers, this should be b.model.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#LazyBridgeOptimizer-API","page":"API Reference","title":"LazyBridgeOptimizer API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.LazyBridgeOptimizer\nBridges.full_bridge_optimizer\nBridges.ListOfNonstandardBridges\nBridges.add_bridge\nBridges.remove_bridge\nBridges.has_bridge\nBridges.print_active_bridges\nBridges.print_graph\nBridges.debug_supports_constraint\nBridges.debug_supports","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.LazyBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.LazyBridgeOptimizer","text":"LazyBridgeOptimizer(model::MOI.ModelLike)\n\nThe LazyBridgeOptimizer is a bridge optimizer that supports multiple bridges, and only bridges things which are not supported by the internal model.\n\nInternally, the LazyBridgeOptimizer solves a shortest hyper-path problem to determine which bridges to use.\n\nIn general, you should use full_bridge_optimizer instead of this constructor because full_bridge_optimizer automatically adds a large number of supported bridges.\n\nSee also: add_bridge, remove_bridge, has_bridge and full_bridge_optimizer.\n\nExample\n\njulia> model = MOI.Bridges.LazyBridgeOptimizer(MOI.Utilities.Model{Float64}())\nMOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}\nwith 0 variable bridges\nwith 0 constraint bridges\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}\n\njulia> MOI.Bridges.add_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64})\n\njulia> MOI.Bridges.has_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64})\ntrue\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.full_bridge_optimizer","page":"API Reference","title":"MathOptInterface.Bridges.full_bridge_optimizer","text":"full_bridge_optimizer(model::MOI.ModelLike, ::Type{T}) where {T}\n\nReturns a LazyBridgeOptimizer bridging model for every bridge defined in this package (see below for the few exceptions) and for the coefficient type T, as well as the bridges in the list returned by the ListOfNonstandardBridges attribute.\n\nExample\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> bridged_model = MOI.Bridges.full_bridge_optimizer(model, Float64);\n\nExceptions\n\nThe following bridges are not added by full_bridge_optimizer, except if they are in the list returned by the ListOfNonstandardBridges attribute:\n\nConstraint.SOCtoNonConvexQuadBridge\nConstraint.RSOCtoNonConvexQuadBridge](@ref)\nConstraint.SOCtoPSDBridge\nIf T is not a subtype of AbstractFloat, subtypes of Constraint.AbstractToIntervalBridge\nConstraint.GreaterToIntervalBridge\nConstraint.LessToIntervalBridge)\n\nSee the docstring of the each bridge for the reason they are not added.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.ListOfNonstandardBridges","page":"API Reference","title":"MathOptInterface.Bridges.ListOfNonstandardBridges","text":"ListOfNonstandardBridges{T}() <: MOI.AbstractOptimizerAttribute\n\nAny optimizer can be wrapped in a LazyBridgeOptimizer using full_bridge_optimizer. However, by default LazyBridgeOptimizer uses a limited set of bridges that are:\n\nimplemented in MOI.Bridges\ngenerally applicable for all optimizers.\n\nFor some optimizers however, it is useful to add additional bridges, such as those that are implemented in external packages (e.g., within the solver package itself) or only apply in certain circumstances (e.g., Constraint.SOCtoNonConvexQuadBridge).\n\nSuch optimizers should implement the ListOfNonstandardBridges attribute to return a vector of bridge types that are added by full_bridge_optimizer in addition to the list of default bridges.\n\nNote that optimizers implementing ListOfNonstandardBridges may require package-specific functions or sets to be used if the non-standard bridges are not added. Therefore, you are recommended to use model = MOI.instantiate(Package.Optimizer; with_bridge_type = T) instead of model = MOI.instantiate(Package.Optimizer). See MOI.instantiate.\n\nExamples\n\nAn optimizer using a non-default bridge in MOI.Bridges\n\nSolvers supporting MOI.ScalarQuadraticFunction can support MOI.SecondOrderCone and MOI.RotatedSecondOrderCone by defining:\n\nfunction MOI.get(::MyQuadraticOptimizer, ::ListOfNonstandardBridges{Float64})\n return Type[\n MOI.Bridges.Constraint.SOCtoNonConvexQuadBridge{Float64},\n MOI.Bridges.Constraint.RSOCtoNonConvexQuadBridge{Float64},\n ]\nend\n\nAn optimizer defining an internal bridge\n\nSuppose an optimizer can exploit specific structure of a constraint, e.g., it can exploit the structure of the matrix A in the linear system of equations A * x = b.\n\nThe optimizer can define the function:\n\nstruct MatrixAffineFunction{T} <: MOI.AbstractVectorFunction\n A::SomeStructuredMatrixType{T}\n b::Vector{T}\nend\n\nand then a bridge\n\nstruct MatrixAffineFunctionBridge{T} <: MOI.Constraint.AbstractBridge\n # ...\nend\n# ...\n\nfrom VectorAffineFunction{T} to the MatrixAffineFunction. Finally, it defines:\n\nfunction MOI.get(::Optimizer{T}, ::ListOfNonstandardBridges{T}) where {T}\n return Type[MatrixAffineFunctionBridge{T}]\nend\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.add_bridge","page":"API Reference","title":"MathOptInterface.Bridges.add_bridge","text":"add_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge})\n\nEnable the use of the bridges of type BT by b.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.remove_bridge","page":"API Reference","title":"MathOptInterface.Bridges.remove_bridge","text":"remove_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge})\n\nDisable the use of the bridges of type BT by b.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.has_bridge","page":"API Reference","title":"MathOptInterface.Bridges.has_bridge","text":"has_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge})\n\nReturn a Bool indicating whether the bridges of type BT are used by b.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.print_active_bridges","page":"API Reference","title":"MathOptInterface.Bridges.print_active_bridges","text":"print_active_bridges([io::IO=stdout,] b::MOI.Bridges.LazyBridgeOptimizer)\n\nPrint the set of bridges that are active in the model b.\n\n\n\n\n\nprint_active_bridges(\n [io::IO=stdout,]\n b::MOI.Bridges.LazyBridgeOptimizer,\n F::Type{<:MOI.AbstractFunction}\n)\n\nPrint the set of bridges required for an objective function of type F.\n\n\n\n\n\nprint_active_bridges(\n [io::IO=stdout,]\n b::MOI.Bridges.LazyBridgeOptimizer,\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet},\n)\n\nPrint the set of bridges required for a constraint of type F-in-S.\n\n\n\n\n\nprint_active_bridges(\n [io::IO=stdout,]\n b::MOI.Bridges.LazyBridgeOptimizer,\n S::Type{<:MOI.AbstractSet}\n)\n\nPrint the set of bridges required for a variable constrained to set S.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.print_graph","page":"API Reference","title":"MathOptInterface.Bridges.print_graph","text":"print_graph([io::IO = stdout,] b::LazyBridgeOptimizer)\n\nPrint the hyper-graph containing all variable, constraint, and objective types that could be obtained by bridging the variables, constraints, and objectives that are present in the model by all the bridges added to b.\n\nEach node in the hyper-graph corresponds to a variable, constraint, or objective type.\n\nVariable nodes are indicated by [ ]\nConstraint nodes are indicated by ( )\nObjective nodes are indicated by | |\n\nThe number inside each pair of brackets is an index of the node in the hyper-graph.\n\nNote that this hyper-graph is the full list of possible transformations. When the bridged model is created, we select the shortest hyper-path(s) from this graph, so many nodes may be un-used.\n\nTo see which nodes are used, call print_active_bridges.\n\nFor more information, see Legat, B., Dowson, O., Garcia, J., and Lubin, M. (2020). \"MathOptInterface: a data structure for mathematical optimization problems.\" URL: https://arxiv.org/abs/2002.03447\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.debug_supports_constraint","page":"API Reference","title":"MathOptInterface.Bridges.debug_supports_constraint","text":"debug_supports_constraint(\n b::LazyBridgeOptimizer,\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet};\n io::IO = Base.stdout,\n)\n\nPrints to io explanations for the value of MOI.supports_constraint with the same arguments.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.debug_supports","page":"API Reference","title":"MathOptInterface.Bridges.debug_supports","text":"debug_supports(\n b::LazyBridgeOptimizer,\n ::MOI.ObjectiveFunction{F};\n io::IO = Base.stdout,\n) where F\n\nPrints to io explanations for the value of MOI.supports with the same arguments.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#constraint_set_map","page":"API Reference","title":"SetMap API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.map_set\nBridges.inverse_map_set\nBridges.map_function\nBridges.inverse_map_function\nBridges.adjoint_map_function\nBridges.inverse_adjoint_map_function","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.map_set","page":"API Reference","title":"MathOptInterface.Bridges.map_set","text":"map_set(::Type{BT}, set) where {BT}\n\nReturn the image of set through the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for bridging the constraint and setting the MOI.ConstraintSet.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.inverse_map_set","page":"API Reference","title":"MathOptInterface.Bridges.inverse_map_set","text":"inverse_map_set(::Type{BT}, set) where {BT}\n\nReturn the preimage of set through the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintSet.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.map_function","page":"API Reference","title":"MathOptInterface.Bridges.map_function","text":"map_function(::Type{BT}, func) where {BT}\n\nReturn the image of func through the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintPrimal of variable bridges. For constraint bridges, this is used for bridging the constraint, setting the MOI.ConstraintFunction and MOI.ConstraintPrimalStart and modifying the function with MOI.modify.\n\nmap_function(::Type{BT}, func, i::IndexInVector) where {BT}\n\nReturn the scalar function at the ith index of the vector function that would be returned by map_function(BT, func) except that it may compute the ith element. This is used by bridged_function and for getting the MOI.VariablePrimal and MOI.VariablePrimalStart of variable bridges.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.inverse_map_function","page":"API Reference","title":"MathOptInterface.Bridges.inverse_map_function","text":"inverse_map_function(::Type{BT}, func) where {BT}\n\nReturn the image of func through the inverse of the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used by Variable.unbridged_map and for setting the MOI.VariablePrimalStart of variable bridges and for getting the MOI.ConstraintFunction, the MOI.ConstraintPrimal and the MOI.ConstraintPrimalStart of constraint bridges.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.adjoint_map_function","page":"API Reference","title":"MathOptInterface.Bridges.adjoint_map_function","text":"adjoint_map_function(::Type{BT}, func) where {BT}\n\nReturn the image of func through the adjoint of the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintDual and MOI.ConstraintDualStart of constraint bridges.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.inverse_adjoint_map_function","page":"API Reference","title":"MathOptInterface.Bridges.inverse_adjoint_map_function","text":"inverse_adjoint_map_function(::Type{BT}, func) where {BT}\n\nReturn the image of func through the inverse of the adjoint of the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintDual of variable bridges and setting the MOI.ConstraintDualStart of constraint bridges.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#Bridging-graph-API","page":"API Reference","title":"Bridging graph API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.Graph\nBridges.VariableNode\nBridges.ConstraintNode\nBridges.ObjectiveNode\nBridges.Edge\nBridges.ObjectiveEdge\nBridges.add_node\nBridges.add_edge\nBridges.set_variable_constraint_node\nBridges.bridge_index\nBridges.is_variable_edge_best","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Graph","page":"API Reference","title":"MathOptInterface.Bridges.Graph","text":"Graph()\n\nA type-stable datastructure for computing the shortest hyperpath problem.\n\nNodes\n\nThere are three types of nodes in the graph:\n\nVariableNode\nConstraintNode\nObjectiveNode\n\nAdd nodes to the graph using add_node.\n\nEdges\n\nThere are two types of edges in the graph:\n\nEdge\nObjectiveEdge\n\nAdd edges to the graph using add_edge.\n\nFor the ability to add a variable constrained on creation as a free variable followed by a constraint, use set_variable_constraint_node.\n\nOptimal hyper-edges\n\nUse bridge_index to compute the minimum-cost bridge leaving a node.\n\nNote that bridge_index lazy runs a Bellman-Ford algorithm to compute the set of minimum cost edges. Thus, the first call to bridge_index after adding new nodes or edges will take longer than subsequent calls.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.VariableNode","page":"API Reference","title":"MathOptInterface.Bridges.VariableNode","text":"VariableNode(index::Int)\n\nA node in Graph representing a variable constrained on creation.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.ConstraintNode","page":"API Reference","title":"MathOptInterface.Bridges.ConstraintNode","text":"ConstraintNode(index::Int)\n\nA node in Graph representing a constraint.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.ObjectiveNode","page":"API Reference","title":"MathOptInterface.Bridges.ObjectiveNode","text":"ObjectiveNode(index::Int)\n\nA node in Graph representing an objective function.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Edge","page":"API Reference","title":"MathOptInterface.Bridges.Edge","text":"Edge(\n bridge_index::Int,\n added_variables::Vector{VariableNode},\n added_constraints::Vector{ConstraintNode},\n cost::Float64 = 1.0,\n)\n\nReturn a new datastructure representing an edge in Graph that starts at a VariableNode or a ConstraintNode.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.ObjectiveEdge","page":"API Reference","title":"MathOptInterface.Bridges.ObjectiveEdge","text":"ObjectiveEdge(\n bridge_index::Int,\n added_variables::Vector{VariableNode},\n added_constraints::Vector{ConstraintNode},\n)\n\nReturn a new datastructure representing an edge in Graph that starts at an ObjectiveNode.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.add_node","page":"API Reference","title":"MathOptInterface.Bridges.add_node","text":"add_node(graph::Graph, ::Type{VariableNode})::VariableNode\nadd_node(graph::Graph, ::Type{ConstraintNode})::ConstraintNode\nadd_node(graph::Graph, ::Type{ObjectiveNode})::ObjectiveNode\n\nAdd a new node to graph.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.add_edge","page":"API Reference","title":"MathOptInterface.Bridges.add_edge","text":"add_edge(graph::Graph, node::VariableNode, edge::Edge)::Nothing\nadd_edge(graph::Graph, node::ConstraintNode, edge::Edge)::Nothing\nadd_edge(graph::Graph, node::ObjectiveNode, edge::ObjectiveEdge)::Nothing\n\nAdd edge to graph, where edge starts at node and connects to the nodes defined in edge.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.set_variable_constraint_node","page":"API Reference","title":"MathOptInterface.Bridges.set_variable_constraint_node","text":"set_variable_constraint_node(\n graph::Graph,\n variable_node::VariableNode,\n constraint_node::ConstraintNode,\n cost::Int,\n)\n\nAs an alternative to variable_node, add a virtual edge to graph that represents adding a free variable, followed by a constraint of type constraint_node, with bridging cost cost.\n\nWhy is this needed?\n\nVariables can either be added as a variable constrained on creation, or as a free variable which then has a constraint added to it.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.bridge_index","page":"API Reference","title":"MathOptInterface.Bridges.bridge_index","text":"bridge_index(graph::Graph, node::VariableNode)::Int\nbridge_index(graph::Graph, node::ConstraintNode)::Int\nbridge_index(graph::Graph, node::ObjectiveNode)::Int\n\nReturn the optimal index of the bridge to chose from node.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.is_variable_edge_best","page":"API Reference","title":"MathOptInterface.Bridges.is_variable_edge_best","text":"is_variable_edge_best(graph::Graph, node::VariableNode)::Bool\n\nReturn a Bool indicating whether node should be added as a variable constrained on creation, or as a free variable followed by a constraint.\n\n\n\n\n\n","category":"function"},{"location":"#Introduction","page":"Introduction","title":"Introduction","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"Welcome to the documentation for MathOptInterface.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"note: Note\nThis documentation is also available in PDF format: MathOptInterface.pdf.","category":"page"},{"location":"#What-is-MathOptInterface?","page":"Introduction","title":"What is MathOptInterface?","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"MathOptInterface.jl (MOI) is an abstraction layer designed to provide a unified interface to mathematical optimization solvers so that users do not need to understand multiple solver-specific APIs.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"tip: Tip\nThis documentation is aimed at developers writing software interfaces to solvers and modeling languages using the MathOptInterface API. If you are a user interested in solving optimization problems, we encourage you instead to use MOI through a higher-level modeling interface like JuMP or Convex.jl.","category":"page"},{"location":"#How-the-documentation-is-structured","page":"Introduction","title":"How the documentation is structured","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"Having a high-level overview of how this documentation is structured will help you know where to look for certain things.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"The Tutorials section contains articles on how to use and implement the MathOptInteraface API. Look here if you want to write a model in MOI, or write an interface to a new solver.\nThe Manual contains short code-snippets that explain how to use the MOI API. Look here for more details on particular areas of MOI.\nThe Background section contains articles on the theory behind MathOptInterface. Look here if you want to understand why, rather than how.\nThe API Reference contains a complete list of functions and types that comprise the MOI API. Look here is you want to know how to use (or implement) a particular function.\nThe Submodules section contains stand-alone documentation for each of the submodules within MOI. These submodules are not required to interface a solver with MOI, but they make the job much easier.","category":"page"},{"location":"#Citing-MathOptInterface","page":"Introduction","title":"Citing MathOptInterface","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"A paper describing the design and features of MathOptInterface is available on arXiv.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"If you find MathOptInterface useful in your work, we kindly request that you cite the following paper:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"@article{legat2021mathoptinterface,\n title={{MathOptInterface}: a data structure for mathematical optimization problems},\n author={Legat, Beno{\\^\\i}t and Dowson, Oscar and Garcia, Joaquim Dias and Lubin, Miles},\n journal={INFORMS Journal on Computing},\n year={2021},\n doi={10.1287/ijoc.2021.1067},\n publisher={INFORMS}\n}","category":"page"},{"location":"background/naming_conventions/","page":"Naming conventions","title":"Naming conventions","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"background/naming_conventions/#Naming-conventions","page":"Naming conventions","title":"Naming conventions","text":"","category":"section"},{"location":"background/naming_conventions/","page":"Naming conventions","title":"Naming conventions","text":"MOI follows several conventions for naming functions and structures. These should also be followed by packages extending MOI.","category":"page"},{"location":"background/naming_conventions/#Sets","page":"Naming conventions","title":"Sets","text":"","category":"section"},{"location":"background/naming_conventions/","page":"Naming conventions","title":"Naming conventions","text":"Sets encode the structure of constraints. Their names should follow the following conventions:","category":"page"},{"location":"background/naming_conventions/","page":"Naming conventions","title":"Naming conventions","text":"Abstract types in the set hierarchy should begin with Abstract and end in Set, for example, AbstractScalarSet, AbstractVectorSet.\nVector-valued conic sets should end with Cone, for example, NormInfinityCone, SecondOrderCone.\nVector-valued Cartesian products should be plural and not end in Cone, for example, Nonnegatives, not NonnegativeCone.\nMatrix-valued conic sets should provide two representations: ConeSquare and ConeTriangle, for example, RootDetConeTriangle and RootDetConeSquare. See Matrix cones for more details.\nScalar sets should be singular, not plural, for example, Integer, not Integers.\nAs much as possible, the names should follow established conventions in the domain where this set is used: for instance, convex sets should have names close to those of CVX, and constraint-programming sets should follow MiniZinc's constraints.","category":"page"}] +} diff --git a/previews/PR2274/siteinfo.js b/previews/PR2274/siteinfo.js new file mode 100644 index 0000000000..4e7c44fbb5 --- /dev/null +++ b/previews/PR2274/siteinfo.js @@ -0,0 +1 @@ +var DOCUMENTER_CURRENT_VERSION = "previews/PR2274"; diff --git a/previews/PR2274/submodules/Benchmarks/overview/index.html b/previews/PR2274/submodules/Benchmarks/overview/index.html new file mode 100644 index 0000000000..d90a49e347 --- /dev/null +++ b/previews/PR2274/submodules/Benchmarks/overview/index.html @@ -0,0 +1,20 @@ + +Overview · MathOptInterface

The Benchmarks submodule

To aid the development of efficient solver wrappers, MathOptInterface provides benchmarking capability. Benchmarking a wrapper follows a two-step process.

First, prior to making changes, create a baseline for the benchmark results on a given benchmark suite as follows:

using SolverPackage  # Replace with your choice of solver.
+import MathOptInterface as MOI
+
+suite = MOI.Benchmarks.suite() do
+    SolverPackage.Optimizer()
+end
+
+MOI.Benchmarks.create_baseline(
+    suite, "current"; directory = "/tmp", verbose = true
+)

Use the exclude argument to Benchmarks.suite to exclude benchmarks that the solver doesn't support.

Second, after making changes to the package, re-run the benchmark suite and compare to the prior saved results:

using SolverPackage
+import MathOptInterface as MOI
+
+suite = MOI.Benchmarks.suite() do
+    SolverPackage.Optimizer()
+end
+
+MOI.Benchmarks.compare_against_baseline(
+    suite, "current"; directory = "/tmp", verbose = true
+)

This comparison will create a report detailing improvements and regressions.

diff --git a/previews/PR2274/submodules/Benchmarks/reference/index.html b/previews/PR2274/submodules/Benchmarks/reference/index.html new file mode 100644 index 0000000000..46f5077cff --- /dev/null +++ b/previews/PR2274/submodules/Benchmarks/reference/index.html @@ -0,0 +1,17 @@ + +API Reference · MathOptInterface

Benchmarks

Functions to help benchmark the performance of solver wrappers. See The Benchmarks submodule for more details.

MathOptInterface.Benchmarks.suiteFunction
suite(
+    new_model::Function;
+    exclude::Vector{Regex} = Regex[]
+)

Create a suite of benchmarks. new_model should be a function that takes no arguments, and returns a new instance of the optimizer you wish to benchmark.

Use exclude to exclude a subset of benchmarks.

Examples

suite() do
+    GLPK.Optimizer()
+end
+suite(exclude = [r"delete"]) do
+    Gurobi.Optimizer(OutputFlag=0)
+end
source
MathOptInterface.Benchmarks.create_baselineFunction
create_baseline(suite, name::String; directory::String = ""; kwargs...)

Run all benchmarks in suite and save to files called name in directory.

Extra kwargs are based to BenchmarkTools.run.

Examples

my_suite = suite(() -> GLPK.Optimizer())
+create_baseline(my_suite, "glpk_master"; directory = "/tmp", verbose = true)
source
MathOptInterface.Benchmarks.compare_against_baselineFunction
compare_against_baseline(
+    suite, name::String; directory::String = "",
+    report_filename::String = "report.txt"
+)

Run all benchmarks in suite and compare against files called name in directory that were created by a call to create_baseline.

A report summarizing the comparison is written to report_filename in directory.

Extra kwargs are based to BenchmarkTools.run.

Examples

my_suite = suite(() -> GLPK.Optimizer())
+compare_against_baseline(
+    my_suite, "glpk_master"; directory = "/tmp", verbose = true
+)
source
diff --git a/previews/PR2274/submodules/Bridges/list_of_bridges/index.html b/previews/PR2274/submodules/Bridges/list_of_bridges/index.html new file mode 100644 index 0000000000..2f1e996c32 --- /dev/null +++ b/previews/PR2274/submodules/Bridges/list_of_bridges/index.html @@ -0,0 +1,110 @@ + +List of bridges · MathOptInterface

List of bridges

This section describes the Bridges.AbstractBridges that are implemented in MathOptInterface.

Constraint bridges

These bridges are subtypes of Bridges.Constraint.AbstractBridge.

MathOptInterface.Bridges.Constraint.VectorizeBridgeType
VectorizeBridge{T,F,S,G} <: Bridges.Constraint.AbstractBridge

VectorizeBridge implements the following reformulations:

  • $g(x) \ge a$ into $[g(x) - a] \in \mathbb{R}_+$
  • $g(x) \le a$ into $[g(x) - a] \in \mathbb{R}_-$
  • $g(x) == a$ into $[g(x) - a] \in \{0\}$

where T is the coefficient type of g(x) - a.

Source node

VectorizeBridge supports:

Target nodes

VectorizeBridge creates:

source
MathOptInterface.Bridges.Constraint.ScalarizeBridgeType
ScalarizeBridge{T,F,S}

ScalarizeBridge implements the following reformulations:

  • $f(x) - a \in \mathbb{R}_+$ into $f_i(x) \ge a_i$ for all $i$
  • $f(x) - a \in \mathbb{R}_-$ into $f_i(x) \le a_i$ for all $i$
  • $f(x) - a \in \{0\}$ into $f_i(x) == a_i$ for all $i$

Source node

ScalarizeBridge supports:

Target nodes

ScalarizeBridge creates:

source
MathOptInterface.Bridges.Constraint.FunctionConversionBridgeType
FunctionConversionBridge{T,F,G,S} <: AbstractFunctionConversionBridge{G,S}

FunctionConversionBridge implements the following reformulations:

  • $g(x) \in S$ into $f(x) \in S$

for these pairs of functions:

Source node

FunctionConversionBridge supports:

  • G in S

Target nodes

FunctionConversionBridge creates:

  • F in S
source
MathOptInterface.Bridges.Constraint.SplitComplexEqualToBridgeType
SplitComplexEqualToBridge{T,F,G} <: Bridges.Constraint.AbstractBridge

SplitComplexEqualToBridge implements the following reformulation:

  • $f(x) + g(x) * im = a + b * im$ into $f(x) = a$ and $g(x) = b$

Source node

SplitComplexEqualToBridge supports:

where G is a function with Complex coefficients.

Target nodes

SplitComplexEqualToBridge creates:

where F is the type of the real/imaginary part of G.

source
MathOptInterface.Bridges.Constraint.SplitComplexZerosBridgeType
SplitComplexZerosBridge{T,F,G} <: Bridges.Constraint.AbstractBridge

SplitComplexZerosBridge implements the following reformulation:

  • $f(x) \in \{0\}^n$ into $\text{Re}(f(x)) \in \{0\}^n$ and $\text{Im}(f(x)) \in \{0\}^n$

Source node

SplitComplexZerosBridge supports:

where G is a function with Complex coefficients.

Target nodes

SplitComplexZerosBridge creates:

where F is the type of the real/imaginary part of G.

source
MathOptInterface.Bridges.Constraint.SplitIntervalBridgeType
SplitIntervalBridge{T,F,S,LS,US} <: Bridges.Constraint.AbstractBridge

SplitIntervalBridge implements the following reformulations:

  • $l \le f(x) \le u$ into $f(x) \ge l$ and $f(x) \le u$
  • $f(x) = b$ into $f(x) \ge b$ and $f(x) \le b$
  • $f(x) \in \{0\}$ into $f(x) \in \mathbb{R}_+$ and $f(x) \in \mathbb{R}_-$

Source node

SplitIntervalBridge supports:

Target nodes

SplitIntervalBridge creates:

or

Note

If T<:AbstractFloat and S is MOI.Interval{T} then no lower (resp. upper) bound constraint is created if the lower (resp. upper) bound is typemin(T) (resp. typemax(T)). Similarly, when MOI.ConstraintSet is set, a lower or upper bound constraint may be deleted or created accordingly.

source
MathOptInterface.Bridges.Constraint.SOCtoNonConvexQuadBridgeType
SOCtoNonConvexQuadBridge{T} <: Bridges.Constraint.AbstractBridge

SOCtoNonConvexQuadBridge implements the following reformulations:

  • $||x||_2 \le t$ into $\sum x^2 - t^2 \le 0$ and $1t + 0 \ge 0$

The MOI.ScalarAffineFunction $1t + 0$ is used in case the variable has other bound constraints.

Warning

This transformation starts from a convex constraint and creates a non-convex constraint. Unless the solver has explicit support for detecting second-order cones in quadratic form, this may (wrongly) be interpreted by the solver as being non-convex. Therefore, this bridge is not added automatically by MOI.Bridges.full_bridge_optimizer. Care is recommended when adding this bridge to a optimizer.

Source node

SOCtoNonConvexQuadBridge supports:

Target nodes

SOCtoNonConvexQuadBridge creates:

source
MathOptInterface.Bridges.Constraint.RSOCtoNonConvexQuadBridgeType
RSOCtoNonConvexQuadBridge{T} <: Bridges.Constraint.AbstractBridge

RSOCtoNonConvexQuadBridge implements the following reformulations:

  • $||x||_2^2 \le 2tu$ into $\sum x^2 - 2tu \le 0$, $1t + 0 \ge 0$, and $1u + 0 \ge 0$.

The MOI.ScalarAffineFunctions $1t + 0$ and $1u + 0$ are used in case the variables have other bound constraints.

Warning

This transformation starts from a convex constraint and creates a non-convex constraint. Unless the solver has explicit support for detecting rotated second-order cones in quadratic form, this may (wrongly) be interpreted by the solver as being non-convex. Therefore, this bridge is not added automatically by MOI.Bridges.full_bridge_optimizer. Care is recommended when adding this bridge to a optimizer.

Source node

RSOCtoNonConvexQuadBridge supports:

Target nodes

RSOCtoNonConvexQuadBridge creates:

source
MathOptInterface.Bridges.Constraint.QuadtoSOCBridgeType
QuadtoSOCBridge{T} <: Bridges.Constraint.AbstractBridge

QuadtoSOCBridge converts quadratic inequalities

\[\frac{1}{2}x^T Q x + a^T x \le ub\]

into MOI.RotatedSecondOrderCone constraints, but it only applies when $Q$ is positive definite.

This is because, if Q is positive definite, there exists U such that $Q = U^T U$, and so the inequality can then be rewritten as;

\[\|U x\|_2^2 \le 2 (-a^T x + ub)\]

Therefore, QuadtoSOCBridge implements the following reformulations:

  • $\frac{1}{2}x^T Q x + a^T x \le ub$ into $(1, -a^T x + ub, Ux) \in RotatedSecondOrderCone$ where $Q = U^T U$
  • $\frac{1}{2}x^T Q x + a^T x \ge lb$ into $(1, a^T x - lb, Ux) \in RotatedSecondOrderCone$ where $-Q = U^T U$

Source node

QuadtoSOCBridge supports:

Target nodes

RelativeEntropyBridge creates:

Errors

This bridge errors if Q is not positive definite.

source
MathOptInterface.Bridges.Constraint.SOCtoPSDBridgeType
SOCtoPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge

SOCtoPSDBridge implements the following reformulation:

  • $||x||_2 \le t$ into $\left[\begin{array}{c c}t & x^\top \\ x & t \mathbf{I}\end{array}\right]\succeq 0$
Warning

This bridge is not added by default by MOI.Bridges.full_bridge_optimizer because bridging second order cone constraints to semidefinite constraints can be achieved by the SOCtoRSOCBridge followed by the RSOCtoPSDBridge, while creating a smaller semidefinite constraint.

Source node

SOCtoPSDBridge supports:

Target nodes

SOCtoPSDBridge creates:

source
MathOptInterface.Bridges.Constraint.NormToPowerBridgeType
NormToPowerBridge{T,F} <: Bridges.Constraint.AbstractBridge

NormToPowerBridge implements the following reformulation:

  • $(t, x) \in NormCone(p, 1+d)$ into $(r_i, t, x_i) \in PowerCone(1 / p)$ for all $i$, and $\sum\limits_i r_i == t$.

For details, see Alizadeh, F., and Goldfarb, D. (2001). "Second-order cone programming." Mathematical Programming, Series B, 95:3-51.

Source node

NormToPowerBridge supports:

Target nodes

NormToPowerBridge creates:

source
MathOptInterface.Bridges.Constraint.GeoMeantoRelEntrBridgeType
GeoMeantoRelEntrBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge

GeoMeantoRelEntrBridge implements the following reformulation:

  • $(u, w) \in GeometricMeanCone$ into $(0, w, (u + y)\mathbf{1})\in RelativeEntropyCone$ and $y \ge 0$

Source node

GeoMeantoRelEntrBridge supports:

Target nodes

GeoMeantoRelEntrBridge creates:

Derivation

The derivation of the bridge is as follows:

\[\begin{aligned} +(u, w) \in GeometricMeanCone \iff & u \le \left(\prod_{i=1}^n w_i\right)^{1/n} \\ +\iff & 0 \le u + y \le \left(\prod_{i=1}^n w_i\right)^{1/n}, y \ge 0 \\ +\iff & 1 \le \frac{\left(\prod_{i=1}^n w_i\right)^{1/n}}{u + y}, y \ge 0 \\ +\iff & 1 \le \left(\prod_{i=1}^n \frac{w_i}{u + y}\right)^{1/n}, y \ge 0 \\ +\iff & 0 \le \sum_{i=1}^n \log\left(\frac{w_i}{u + y}\right), y \ge 0 \\ +\iff & 0 \ge \sum_{i=1}^n \log\left(\frac{u + y}{w_i}\right), y \ge 0 \\ +\iff & 0 \ge \sum_{i=1}^n (u + y) \log\left(\frac{u + y}{w_i}\right), y \ge 0 \\ +\iff & (0, w, (u + y)\mathbf{1}) \in RelativeEntropyCone, y \ge 0 \\ +\end{aligned}\]

This derivation assumes that $u + y > 0$, which is enforced by the relative entropy cone.

source
MathOptInterface.Bridges.Constraint.GeoMeanToPowerBridgeType
GeoMeanToPowerBridge{T,F} <: Bridges.Constraint.AbstractBridge

GeoMeanToPowerBridge implements the following reformulation:

  • $(y, x...) \in GeometricMeanCone(1+d)$ into $(x_1, t, y) \in PowerCone(1/d)$ and $(t, x_2, ..., x_d) in GeometricMeanCone(d)$, which is then recursively expanded into more PowerCone constraints.

Source node

GeoMeanToPowerBridge supports:

Target nodes

GeoMeanToPowerBridge creates:

source
MathOptInterface.Bridges.Constraint.GeoMeanBridgeType
GeoMeanBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge

GeoMeanBridge implements a reformulation from MOI.GeometricMeanCone into MOI.RotatedSecondOrderCone.

The reformulation is best described in an example.

Consider the cone of dimension 4:

\[t \le \sqrt[3]{x_1 x_2 x_3}\]

This can be rewritten as $\exists y \ge 0$ such that:

\[\begin{align*} + t & \le y,\\ + y^4 & \le x_1 x_2 x_3 y. +\end{align*}\]

Note that we need to create $y$ and not use $t^4$ directly because $t$ is allowed to be negative.

This is equivalent to:

\[\begin{align*} + t & \le \frac{y_1}{\sqrt{4}},\\ + y_1^2 & \le 2y_2 y_3,\\ + y_2^2 & \le 2x_1 x_2, \\ + y_3^2 & \le 2x_3(y_1/\sqrt{4}) \\ + y & \ge 0. +\end{align*}\]

More generally, you can show how the geometric mean code is recursively expanded into a set of new variables $y$ in MOI.Nonnegatives, a set of MOI.RotatedSecondOrderCone constraints, and a MOI.LessThan constraint between $t$ and $y_1$.

Source node

GeoMeanBridge supports:

Target nodes

GeoMeanBridge creates:

source
MathOptInterface.Bridges.Constraint.RelativeEntropyBridgeType
RelativeEntropyBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge

RelativeEntropyBridge implements the following reformulation that converts a MOI.RelativeEntropyCone into an MOI.ExponentialCone:

  • $u \ge \sum_{i=1}^n w_i \log \left(\frac{w_i}{v_i}\right)$ into $y_i \ge 0$, $u \ge \sum_{i=1}^n y_i$, and $(-y_i, w_i, v_i) \in ExponentialCone$.

Source node

RelativeEntropyBridge supports:

Target nodes

RelativeEntropyBridge creates:

source
MathOptInterface.Bridges.Constraint.SquareBridgeType
SquareBridge{T,F,G,TT,ST} <: Bridges.Constraint.AbstractBridge

SquareBridge implements the following reformulations:

  • $(t, u, X) \in LogDetConeSquare$ into $(t, u, Y) in LogDetConeTriangle$
  • $(t, X) \in RootDetConeSquare$ into $(t, Y) in RootDetConeTriangle$
  • $X \in AbstractSymmetricMatrixSetSquare$ into $Y in AbstractSymmetricMatrixSetTriangle$

where $Y$ is the upper triangluar component of $X$.

In addition, constraints are added as necessary to constrain the matrix $X$ to be symmetric. For example, the constraint for the matrix:

\[\begin{pmatrix} + 1 & 1 + x & 2 - 3x\\ + 1 + x & 2 + x & 3 - x\\ + 2 - 3x & 2 + x & 2x +\end{pmatrix}\]

can be broken down to the constraint of the symmetric matrix

\[\begin{pmatrix} + 1 & 1 + x & 2 - 3x\\ + \cdot & 2 + x & 3 - x\\ + \cdot & \cdot & 2x +\end{pmatrix}\]

and the equality constraint between the off-diagonal entries (2, 3) and (3, 2) $3 - x == 2 + x$. Note that no symmetrization constraint needs to be added between the off-diagonal entries (1, 2) and (2, 1) or between (1, 3) and (3, 1) because the expressions are the same.

Source node

SquareBridge supports:

  • F in ST

Target nodes

SquareBridge creates:

  • G in TT
source
MathOptInterface.Bridges.Constraint.HermitianToSymmetricPSDBridgeType
HermitianToSymmetricPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge

HermitianToSymmetricPSDBridge implements the following reformulation:

  • Hermitian positive semidefinite n x n complex matrix to a symmetric positive semidefinite 2n x 2n real matrix.

See also MOI.Bridges.Variable.HermitianToSymmetricPSDBridge.

Source node

HermitianToSymmetricPSDBridge supports:

Target node

HermitianToSymmetricPSDBridge creates:

Reformulation

The reformulation is best described by example.

The Hermitian matrix:

\[\begin{bmatrix} + x_{11} & x_{12} + y_{12}im & x_{13} + y_{13}im\\ + x_{12} - y_{12}im & x_{22} & x_{23} + y_{23}im\\ + x_{13} - y_{13}im & x_{23} - y_{23}im & x_{33} +\end{bmatrix}\]

is positive semidefinite if and only if the symmetric matrix:

\[\begin{bmatrix} + x_{11} & x_{12} & x_{13} & 0 & y_{12} & y_{13} \\ + & x_{22} & x_{23} & -y_{12} & 0 & y_{23} \\ + & & x_{33} & -y_{13} & -y_{23} & 0 \\ + & & & x_{11} & x_{12} & x_{13} \\ + & & & & x_{22} & x_{23} \\ + & & & & & x_{33} +\end{bmatrix}\]

is positive semidefinite.

The bridge achieves this reformulation by constraining the above matrix to belong to the MOI.PositiveSemidefiniteConeTriangle(6).

source
MathOptInterface.Bridges.Constraint.RootDetBridgeType
RootDetBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge

The MOI.RootDetConeTriangle is representable by MOI.PositiveSemidefiniteConeTriangle and MOI.GeometricMeanCone constraints, see [1, p. 149].

Indeed, $t \le \det(X)^{1/n}$ if and only if there exists a lower triangular matrix $Δ$ such that:

\[\begin{align*} + \begin{pmatrix} + X & Δ\\ + Δ^\top & \mathrm{Diag}(Δ) + \end{pmatrix} & \succeq 0\\ + (t, \mathrm{Diag}(Δ)) & \in GeometricMeanCone +\end{align*}\]

Source node

RootDetBridge supports:

Target nodes

RootDetBridge creates:

[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.

source
MathOptInterface.Bridges.Constraint.LogDetBridgeType
LogDetBridge{T,F,G,H,I} <: Bridges.Constraint.AbstractBridge

The MOI.LogDetConeTriangle is representable by MOI.PositiveSemidefiniteConeTriangle and MOI.ExponentialCone constraints.

Indeed, $\log\det(X) = \sum\limits_{i=1}^n \log(\delta_i)$ where $\delta_i$ are the eigenvalues of $X$.

Adapting the method from [1, p. 149], we see that $t \le u \log(\det(X/u))$ for $u > 0$ if and only if there exists a lower triangular matrix $Δ$ such that

\[\begin{align*} + \begin{pmatrix} + X & Δ\\ + Δ^\top & \mathrm{Diag}(Δ) + \end{pmatrix} & \succeq 0\\ + t - \sum_{i=1}^n u \log\left(\frac{Δ_{ii}}{u}\right) & \le 0 +\end{align*}\]

Which we reformulate further into

\[\begin{align*} + \begin{pmatrix} + X & Δ\\ + Δ^\top & \mathrm{Diag}(Δ) + \end{pmatrix} & \succeq 0\\ + (l_i, u , Δ_{ii}) & \in ExponentialCone\quad \forall i \\ + t - \sum_{i=1}^n l_i & \le 0 +\end{align*}\]

Source node

LogDetBridge supports:

Target nodes

LogDetBridge creates:

[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.

source
MathOptInterface.Bridges.Constraint.IndicatorActiveOnFalseBridgeType
IndicatorActiveOnFalseBridge{T,F,S} <: Bridges.Constraint.AbstractBridge

IndicatorActiveOnFalseBridge implements the following reformulation:

  • $\neg z \implies {f(x) \in S}$ into $y \implies {f(x) \in S}$, $z + y = 1$, and $y \in \{0, 1\}$

Source node

IndicatorActiveOnFalseBridge supports:

Target nodes

IndicatorActiveOnFalseBridge creates:

source
MathOptInterface.Bridges.Constraint.IndicatorGreaterToLessThanBridgeType
IndicatorGreaterToLessThanBridge{T,A} <: Bridges.Constraint.AbstractBridge

IndicatorGreaterToLessThanBridge implements the following reformulation:

  • $z \implies {f(x) \ge l}$ into $z \implies {-f(x) \le -l}$

Source node

IndicatorGreaterToLessThanBridge supports:

Target nodes

IndicatorGreaterToLessThanBridge creates:

source
MathOptInterface.Bridges.Constraint.IndicatorLessToGreaterThanBridgeType
IndicatorLessToGreaterThanBridge{T,A} <: Bridges.Constraint.AbstractBridge

IndicatorLessToGreaterThanBridge implements the following reformulations:

  • $z \implies {f(x) \le u}$ into $z \implies {-f(x) \ge -u}$

Source node

IndicatorLessToGreaterThanBridge supports:

Target nodes

IndicatorLessToGreaterThanBridge creates:

source
MathOptInterface.Bridges.Constraint.IndicatorSOS1BridgeType
IndicatorSOS1Bridge{T,S} <: Bridges.Constraint.AbstractBridge

IndicatorSOS1Bridge implements the following reformulation:

  • $z \implies {f(x) \in S}$ into $f(x) + y \in S$, $SOS1(y, z)$
Warning

This bridge assumes that the solver supports MOI.SOS1{T} constraints in which one of the variables ($y$) is continuous.

Source node

IndicatorSOS1Bridge supports:

Target nodes

IndicatorSOS1Bridge creates:

source
MathOptInterface.Bridges.Constraint.SemiToBinaryBridgeType
SemiToBinaryBridge{T,S} <: Bridges.Constraint.AbstractBridge

SemiToBinaryBridge implements the following reformulations:

  • $x \in \{0\} \cup [l, u]$ into

    \[\begin{aligned} +x \leq z u \\ +x \geq z l \\ +z \in \{0, 1\} +\end{aligned}\]

  • $x \in \{0\} \cup \{l, \ldots, u\}$ into

    \[\begin{aligned} +x \leq z u \\ +x \geq z l \\ +z \in \{0, 1\} \\ +x \in \mathbb{Z} +\end{aligned}\]

Source node

SemiToBinaryBridge supports:

Target nodes

SemiToBinaryBridge creates:

source
MathOptInterface.Bridges.Constraint.ZeroOneBridgeType
ZeroOneBridge{T} <: Bridges.Constraint.AbstractBridge

ZeroOneBridge implements the following reformulation:

  • $x \in \{0, 1\}$ into $x \in \mathbb{Z}$, $1x \in [0, 1]$.
Note

ZeroOneBridge adds a linear constraint instead of adding variable bounds to avoid conflicting with bounds set by the user.

Source node

ZeroOneBridge supports:

Target nodes

ZeroOneBridge creates:

source
MathOptInterface.Bridges.Constraint.IntegerToZeroOneBridgeType
IntegerToZeroOneBridge{T} <: Bridges.Constraint.AbstractBridge

IntegerToZeroOneBridge implements the following reformulation:

  • $x \in \mathbf{Z}$ into $y_i \in \{0, 1\}$, $x == lb + \sum 2^{i-1} y_i$.

Source node

IntegerToZeroOneBridge supports:

Target nodes

IntegerToZeroOneBridge creates:

Developer note

This bridge is implemented as a constraint bridge instead of a variable bridge because we don't want to substitute the linear combination of y for every instance of x. Doing so would be expensive and greatly reduce the sparsity of the constraints.

source
MathOptInterface.Bridges.Constraint.NumberConversionBridgeType
NumberConversionBridge{T,F1,S1,F2,S2} <: Bridges.Constraint.AbstractBridge

NumberConversionBridge implements the following reformulation:

  • $f1(x) \in S1$ to $f2(x) \in S2$

where f and S are the same functional form, but differ in their coefficient type.

Source node

NumberConversionBridge supports:

  • F1 in S1

Target node

NumberConversionBridge creates:

  • F2 in S2
source
MathOptInterface.Bridges.Constraint.AllDifferentToCountDistinctBridgeType
AllDifferentToCountDistinctBridge{T,F} <: Bridges.Constraint.AbstractBridge

AllDifferentToCountDistinctBridge implements the following reformulations:

  • $x \in \textsf{AllDifferent}(d)$ to $(n, x) \in \textsf{CountDistinct}(1+d)$ and $n = d$
  • $f(x) \in \textsf{AllDifferent}(d)$ to $(d, f(x)) \in \textsf{CountDistinct}(1+d)$

Source node

AllDifferentToCountDistinctBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

AllDifferentToCountDistinctBridge creates:

source
MathOptInterface.Bridges.Constraint.ReifiedAllDifferentToCountDistinctBridgeType
ReifiedAllDifferentToCountDistinctBridge{T,F} <:
+Bridges.Constraint.AbstractBridge

ReifiedAllDifferentToCountDistinctBridge implements the following reformulations:

  • $r \iff x \in \textsf{AllDifferent}(d)$ to $r \iff (n, x) \in \textsf{CountDistinct}(1+d)$ and $n = d$
  • $r \iff f(x) \in \textsf{AllDifferent}(d)$ to $r \iff (d, f(x)) \in \textsf{CountDistinct}(1+d)$

Source node

ReifiedAllDifferentToCountDistinctBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

ReifiedAllDifferentToCountDistinctBridge creates:

source
MathOptInterface.Bridges.Constraint.BinPackingToMILPBridgeType
BinPackingToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

BinPackingToMILPBridge implements the following reformulation:

  • $x \in BinPacking(c, w)$ into a mixed-integer linear program.

Reformulation

The reformulation is non-trivial, and it depends on the finite domain of each variable $x_i$, which we as define $S_i = \{l_i,\ldots,u_i\}$.

First, we introduce new binary variables $z_{ij}$, which are $1$ if variable $x_i$ takes the value $j$ in the optimal solution and $0$ otherwise:

\[\begin{aligned} +z_{ij} \in \{0, 1\} & \;\; \forall i \in 1\ldots d, j \in S_i \\ +x_i - \sum\limits_{j\in S_i} j \cdot z_{ij} = 0 & \;\; \forall i \in 1\ldots d \\ +\sum\limits_{j\in S_i} z_{ij} = 1 & \;\; \forall i \in 1\ldots d \\ +\end{aligned}\]

Then, we add the capacity constraint for all possible bins $j$:

\[\sum\limits_{i} w_i z_{ij} \le c \forall j \in \bigcup_{i=1,\ldots,d} S_i\]

Source node

BinPackingToMILPBridge supports:

Target nodes

BinPackingToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.CircuitToMILPBridgeType
CircuitToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

CircuitToMILPBridge implements the following reformulation:

  • $x \in \textsf{Circuit}(d)$ to the Miller-Tucker-Zemlin formulation of the Traveling Salesperson Problem.

Source node

CircuitToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

CircuitToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.CountAtLeastToCountBelongsBridgeType
CountAtLeastToCountBelongsBridge{T,F} <: Bridges.Constraint.AbstractBridge

CountAtLeastToCountBelongsBridge implements the following reformulation:

  • $x \in \textsf{CountAtLeast}(n, d, \mathcal{S})$ to $(n_i, x_{d_i}) \in \textsf{CountBelongs}(1+d, \mathcal{S})$ and $n_i \ge n$ for all $i$.

Source node

CountAtLeastToCountBelongsBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

CountAtLeastToCountBelongsBridge creates:

source
MathOptInterface.Bridges.Constraint.CountBelongsToMILPBridgeType
CountBelongsToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

CountBelongsToMILPBridge implements the following reformulation:

  • $(n, x) \in \textsf{CountBelongs}(1+d, \mathcal{S})$ into a mixed-integer linear program.

Reformulation

The reformulation is non-trivial, and it depends on the finite domain of each variable $x_i$, which we as define $S_i = \{l_i,\ldots,u_i\}$.

First, we introduce new binary variables $z_{ij}$, which are $1$ if variable $x_i$ takes the value $j$ in the optimal solution and $0$ otherwise:

\[\begin{aligned} +z_{ij} \in \{0, 1\} & \;\; \forall i \in 1\ldots d, j \in S_i \\ +x_i - \sum\limits_{j\in S_i} j \cdot z_{ij} = 0 & \;\; \forall i \in 1\ldots d \\ +\sum\limits_{j\in S_i} z_{ij} = 1 & \;\; \forall i \in 1\ldots d \\ +\end{aligned}\]

Finally, $n$ is constrained to be the number of $z_{ij}$ elements that are in $\mathcal{S}$:

\[n - \sum\limits_{i\in 1\ldots d, j \in \mathcal{S}} z_{ij} = 0\]

Source node

CountBelongsToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

CountBelongsToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.CountDistinctToMILPBridgeType
CountDistinctToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

CountDistinctToMILPBridge implements the following reformulation:

  • $(n, x) \in \textsf{CountDistinct}(1+d)$ into a mixed-integer linear program.

Reformulation

The reformulation is non-trivial, and it depends on the finite domain of each variable $x_i$, which we as define $S_i = \{l_i,\ldots,u_i\}$.

First, we introduce new binary variables $z_{ij}$, which are $1$ if variable $x_i$ takes the value $j$ in the optimal solution and $0$ otherwise:

\[\begin{aligned} +z_{ij} \in \{0, 1\} & \;\; \forall i \in 1\ldots d, j \in S_i \\ +x_i - \sum\limits_{j\in S_i} j \cdot z_{ij} = 0 & \;\; \forall i \in 1\ldots d \\ +\sum\limits_{j\in S_i} z_{ij} = 1 & \;\; \forall i \in 1\ldots d \\ +\end{aligned}\]

Then, we introduce new binary variables $y_j$, which are $1$ if a variable takes the value $j$ in the optimal solution and $0$ otherwise.

\[\begin{aligned} +y_{j} \in \{0, 1\} & \;\; \forall j \in \bigcup_{i=1,\ldots,d} S_i \\ +y_j \le \sum\limits_{i \in 1\ldots d: j \in S_i} z_{ij} \le M y_j & \;\; \forall j \in \bigcup_{i=1,\ldots,d} S_i\\ +\end{aligned}\]

Finally, $n$ is constrained to be the number of $y_j$ elements that are non-zero:

\[n - \sum\limits_{j \in \bigcup_{i=1,\ldots,d} S_i} y_{j} = 0\]

Source node

CountDistinctToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

CountDistinctToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.ReifiedCountDistinctToMILPBridgeType
ReifiedCountDistinctToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

ReifiedCountDistinctToMILPBridge implements the following reformulation:

  • $r \iff (n, x) \in \textsf{CountDistinct}(1+d)$ into a mixed-integer linear program.

Reformulation

The reformulation is non-trivial, and it depends on the finite domain of each variable $x_i$, which we as define $S_i = \{l_i,\ldots,u_i\}$.

First, we introduce new binary variables $z_{ij}$, which are $1$ if variable $x_i$ takes the value $j$ in the optimal solution and $0$ otherwise:

\[\begin{aligned} +z_{ij} \in \{0, 1\} & \;\; \forall i \in 1\ldots d, j \in S_i \\ +x_i - \sum\limits_{j\in S_i} j \cdot z_{ij} = 0 & \;\; \forall i \in 1\ldots d \\ +\sum\limits_{j\in S_i} z_{ij} = 1 & \;\; \forall i \in 1\ldots d \\ +\end{aligned}\]

Then, we introduce new binary variables $y_j$, which are $1$ if a variable takes the value $j$ in the optimal solution and $0$ otherwise.

\[\begin{aligned} +y_{j} \in \{0, 1\} & \;\; \forall j \in \bigcup_{i=1,\ldots,d} S_i \\ +y_j \le \sum\limits_{i \in 1\ldots d: j \in S_i} z_{ij} \le M y_j & \;\; \forall j \in \bigcup_{i=1,\ldots,d} S_i\\ +\end{aligned}\]

Finally, $n$ is constrained to be the number of $y_j$ elements that are non-zero, with some slack:

\[n - \sum\limits_{j \in \bigcup_{i=1,\ldots,d} S_i} y_{j} = \delta^+ - \delta^-\]

And then the slack is constrained to respect the reif variable $r$:

\[\begin{aligned} +d_1 \le \delta^+ \le M d_1 \\ +d_2 \le \delta^- \le M d_s \\ +d_1 + d_2 + r = 1 \\ +d_1, d_2 \in \{0, 1\} +\end{aligned}\]

Source node

ReifiedCountDistinctToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

ReifiedCountDistinctToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.CountGreaterThanToMILPBridgeType
CountGreaterThanToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

CountGreaterThanToMILPBridge implements the following reformulation:

  • $(c, y, x) \in CountGreaterThan()$ into a mixed-integer linear program.

Source node

CountGreaterThanToMILPBridge supports:

Target nodes

CountGreaterThanToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.TableToMILPBridgeType
TableToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

TableToMILPBridge implements the following reformulation:

  • $x \in Table(t)$ into

    \[\begin{aligned} +z_{j} \in \{0, 1\} & \quad \forall i, j \\ +\sum\limits_{j=1}^n z_{j} = 1 \\ +\sum\limits_{j=1}^n t_{ij} z_{j} = x_i & \quad \forall i +\end{aligned}\]

Source node

TableToMILPBridge supports:

Target nodes

TableToMILPBridge creates:

source

Objective bridges

These bridges are subtypes of Bridges.Objective.AbstractBridge.

MathOptInterface.Bridges.Objective.QuadratizeBridgeType
QuadratizeBridge{T}

QuadratizeBridge implements the following reformulations:

  • $\min \{a^\top x + b\}$ into $\min\{x^\top \mathbf{0} x + a^\top x + b\}$
  • $\max \{a^\top x + b\}$ into $\max\{x^\top \mathbf{0} x + a^\top x + b\}$

where T is the coefficient type of 0.

Source node

QuadratizeBridge supports:

Target nodes

QuadratizeBridge creates:

source
MathOptInterface.Bridges.Objective.SlackBridgeType
SlackBridge{T,F,G}

SlackBridge implements the following reformulations:

  • $\min\{f(x)\}$ into $\min\{y\;|\; f(x) - y \le 0\}$
  • $\max\{f(x)\}$ into $\max\{y\;|\; f(x) - y \ge 0\}$

where F is the type of f(x) - y, G is the type of f(x), and T is the coefficient type of f(x).

Source node

SlackBridge supports:

Target nodes

SlackBridge creates:

Warning

When using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge, then set MOI.ObjectiveSense and re-add the objective.

source
MathOptInterface.Bridges.Objective.VectorSlackBridgeType
VectorSlackBridge{T,F,G}

VectorSlackBridge implements the following reformulations:

  • $\min\{f(x)\}$ into $\min\{y\;|\; y - f(x) \in \mathbb{R}_+ \}$
  • $\max\{f(x)\}$ into $\max\{y\;|\; f(x) - y \in \mathbb{R}_+ \}$

where F is the type of f(x) - y, G is the type of f(x), and T is the coefficient type of f(x).

Source node

VectorSlackBridge supports:

Target nodes

VectorSlackBridge creates:

Warning

When using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge, then set MOI.ObjectiveSense and re-add the objective.

source

Variable bridges

These bridges are subtypes of Bridges.Variable.AbstractBridge.

MathOptInterface.Bridges.Variable.RSOCtoPSDBridgeType
RSOCtoPSDBridge{T} <: Bridges.Variable.AbstractBridge

RSOCtoPSDBridge implements the following reformulation:

  • $||x||_2^2 \le 2tu$ where $t, u \ge 0$ into $Y \succeq 0$, with the substitution rule: $Y = \left[\begin{array}{c c}t & x^\top \\ x & 2u \mathbf{I}\end{array}\right].$

Additional bounds are added to ensure the off-diagonals of the $2uI$ submatrix are 0, and linear constraints are added to ennsure the diagonal of $2uI$ takes the same values.

As a special case, if $|x|| = 0$, then RSOCtoPSDBridge reformulates into $(t, u) \in \mathbb{R}_+$.

Source node

RSOCtoPSDBridge supports:

Target nodes

RSOCtoPSDBridge creates:

source
MathOptInterface.Bridges.Variable.RSOCtoSOCBridgeType
RSOCtoSOCBridge{T} <: Bridges.Variable.AbstractBridge

RSOCtoSOCBridge implements the following reformulation:

  • $||x||_2^2 \le 2tu$ into $||v||_2 \le w$, with the substitution rules $t = \frac{w}{\sqrt 2} + \frac{v_1}{\sqrt 2}$, $u = \frac{w}{\sqrt 2} - \frac{v_1}{\sqrt 2}$, and $x = (v_2,\ldots,v_N)$.

Source node

RSOCtoSOCBridge supports:

Target node

RSOCtoSOCBridge creates:

source
MathOptInterface.Bridges.Variable.SOCtoRSOCBridgeType
SOCtoRSOCBridge{T} <: Bridges.Variable.AbstractBridge

SOCtoRSOCBridge implements the following reformulation:

  • $||x||_2 \le t$ into $2uv \ge ||w||_2^2$, with the substitution rules $t = \frac{u}{\sqrt 2} + \frac{v}{\sqrt 2}$, $x = (\frac{u}{\sqrt 2} - \frac{v}{\sqrt 2}, w)$.

Assumptions

  • SOCtoRSOCBridge assumes that $|x| \ge 1$.

Source node

SOCtoRSOCBridge supports:

Target node

SOCtoRSOCBridge creates:

source
MathOptInterface.Bridges.Variable.VectorizeBridgeType
VectorizeBridge{T,S} <: Bridges.Variable.AbstractBridge

VectorizeBridge implements the following reformulations:

  • $x \ge a$ into $[y] \in \mathbb{R}_+$ with the substitution rule $x = a + y$
  • $x \le a$ into $[y] \in \mathbb{R}_-$ with the substitution rule $x = a + y$
  • $x == a$ into $[y] \in \{0\}$ with the substitution rule $x = a + y$

where T is the coefficient type of a + y.

Source node

VectorizeBridge supports:

Target nodes

VectorizeBridge creates:

source
MathOptInterface.Bridges.Variable.ZerosBridgeType
ZerosBridge{T} <: Bridges.Variable.AbstractBridge

ZerosBridge implements the following reformulation:

  • $x \in \{0\}$ into the substitution rule $x = 0$,

where T is the coefficient type of 0.

Source node

ZerosBridge supports:

Target nodes

ZerosBridge does not create target nodes. It replaces all instances of x with 0 via substitution. This means that no variables are created in the underlying model.

Caveats

The bridged variables are similar to parameters with zero values. Parameters with non-zero values can be created with constrained variables in MOI.EqualTo by combining a VectorizeBridge and this bridge.

However, functions modified by ZerosBridge cannot be unbridged. That is, for a given function, we cannot determine if the bridged variables were used.

A related implication is that this bridge does not support MOI.ConstraintDual. However, if a MOI.Utilities.CachingOptimizer is used, the dual can be determined by the bridged optimizer using MOI.Utilities.get_fallback because the caching optimizer records the unbridged function.

source
MathOptInterface.Bridges.Variable.HermitianToSymmetricPSDBridgeType
HermitianToSymmetricPSDBridge{T} <: Bridges.Variable.AbstractBridge

HermitianToSymmetricPSDBridge implements the following reformulation:

  • Hermitian positive semidefinite n x n complex matrix to a symmetric positive semidefinite 2n x 2n real matrix satisfying equality constraints described below.

Source node

HermitianToSymmetricPSDBridge supports:

Target node

HermitianToSymmetricPSDBridge creates:

Reformulation

The reformulation is best described by example.

The Hermitian matrix:

\[\begin{bmatrix} + x_{11} & x_{12} + y_{12}im & x_{13} + y_{13}im\\ + x_{12} - y_{12}im & x_{22} & x_{23} + y_{23}im\\ + x_{13} - y_{13}im & x_{23} - y_{23}im & x_{33} +\end{bmatrix}\]

is positive semidefinite if and only if the symmetric matrix:

\[\begin{bmatrix} + x_{11} & x_{12} & x_{13} & 0 & y_{12} & y_{13} \\ + & x_{22} & x_{23} & -y_{12} & 0 & y_{23} \\ + & & x_{33} & -y_{13} & -y_{23} & 0 \\ + & & & x_{11} & x_{12} & x_{13} \\ + & & & & x_{22} & x_{23} \\ + & & & & & x_{33} +\end{bmatrix}\]

is positive semidefinite.

The bridge achieves this reformulation by adding a new set of variables in MOI.PositiveSemidefiniteConeTriangle(6), and then adding three groups of equality constraints to:

  • constrain the two x blocks to be equal
  • force the diagonal of the y blocks to be 0
  • force the lower triangular of the y block to be the negative of the upper triangle.
source
diff --git a/previews/PR2274/submodules/Bridges/overview/index.html b/previews/PR2274/submodules/Bridges/overview/index.html new file mode 100644 index 0000000000..6e04c30937 --- /dev/null +++ b/previews/PR2274/submodules/Bridges/overview/index.html @@ -0,0 +1,53 @@ + +Overview · MathOptInterface

The Bridges submodule

The Bridges module simplifies the process of converting models between equivalent formulations.

Tip

Read our paper for more details on how bridges are implemented.

Why bridges?

A constraint can often be written in a number of equivalent formulations. For example, the constraint $l \le a^\top x \le u$ (ScalarAffineFunction-in-Interval) could be re-formulated as two constraints: $a^\top x \ge l$ (ScalarAffineFunction-in-GreaterThan) and $a^\top x \le u$ (ScalarAffineFunction-in-LessThan). An alternative re-formulation is to add a dummy variable y with the constraints $l \le y \le u$ (VariableIndex-in-Interval) and $a^\top x - y = 0$ (ScalarAffineFunction-in-EqualTo).

To avoid each solver having to code these transformations manually, MathOptInterface provides bridges.

A bridge is a small transformation from one constraint type to another (potentially collection of) constraint type.

Because these bridges are included in MathOptInterface, they can be re-used by any optimizer. Some bridges also implement constraint modifications and constraint primal and dual translations.

Several bridges can be used in combination to transform a single constraint into a form that the solver may understand. Choosing the bridges to use takes the form of finding a shortest path in the hyper-graph of bridges. The methodology is detailed in the MOI paper.

The three types of bridges

There are three types of bridges in MathOptInterface:

  1. Constraint bridges
  2. Variable bridges
  3. Objective bridges

Constraint bridges

Constraint bridges convert constraints formulated by the user into an equivalent form supported by the solver. Constraint bridges are subtypes of Bridges.Constraint.AbstractBridge.

The equivalent formulation may add constraints (and possibly also variables) in the underlying model.

In particular, constraint bridges can focus on rewriting the function of a constraint, and do not change the set. Function bridges are subtypes of Bridges.Constraint.AbstractFunctionConversionBridge.

Read the list of implemented constraint bridges for more details on the types of transformations that are available. Function bridges are Bridges.Constraint.ScalarFunctionizeBridge and Bridges.Constraint.VectorFunctionizeBridge.

Variable bridges

Variable bridges convert variables added by the user, either free with add_variable/add_variables, or constrained with add_constrained_variable/add_constrained_variables, into an equivalent form supported by the solver. Variable bridges are subtypes of Bridges.Variable.AbstractBridge.

The equivalent formulation may add constraints (and possibly also variables) in the underlying model.

Read the list of implemented variable bridges for more details on the types of transformations that are available.

Objective bridges

Objective bridges convert the ObjectiveFunction set by the user into an equivalent form supported by the solver. Objective bridges are subtypes of Bridges.Objective.AbstractBridge.

The equivalent formulation may add constraints (and possibly also variables) in the underlying model.

Read the list of implemented objective bridges for more details on the types of transformations that are available.

Bridges.full_bridge_optimizer

Tip

Unless you have an advanced use-case, this is probably the only function you need to care about.

To enable the full power of MathOptInterface's bridges, wrap an optimizer in a Bridges.full_bridge_optimizer.

julia> inner_optimizer = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> optimizer = MOI.Bridges.full_bridge_optimizer(inner_optimizer, Float64)
+MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}
+with 0 variable bridges
+with 0 constraint bridges
+with 0 objective bridges
+with inner model MOIU.Model{Float64}

Now, use optimizer as normal, and bridging will happen lazily behind the scenes. By lazily, we mean that bridging will happen if and only if the constraint is not supported by the inner_optimizer.

Info

Most bridges are added by default in Bridges.full_bridge_optimizer. However, for technical reasons, some bridges are not added by default. Three examples include Bridges.Constraint.SOCtoPSDBridge, Bridges.Constraint.SOCtoNonConvexQuadBridge and Bridges.Constraint.RSOCtoNonConvexQuadBridge. See the docs of those bridges for more information.

Add a single bridge

If you don't want to use Bridges.full_bridge_optimizer, you can wrap an optimizer in a single bridge.

However, this will force the constraint to be bridged, even if the inner_optimizer supports it.

julia> inner_optimizer = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> optimizer = MOI.Bridges.Constraint.SplitInterval{Float64}(inner_optimizer)
+MOIB.Constraint.SingleBridgeOptimizer{MOIB.Constraint.SplitIntervalBridge{Float64}, MOIU.Model{Float64}}
+with 0 constraint bridges
+with inner model MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(optimizer)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(optimizer, x, MOI.Interval(0.0, 1.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
+
+julia> MOI.get(optimizer, MOI.ListOfConstraintTypesPresent())
+1-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})
+
+julia> MOI.get(inner_optimizer, MOI.ListOfConstraintTypesPresent())
+2-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64})
+ (MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64})

Bridges.LazyBridgeOptimizer

If you don't want to use Bridges.full_bridge_optimizer, but you need more than a single bridge (or you want the bridging to happen lazily), you can manually construct a Bridges.LazyBridgeOptimizer.

First, wrap an inner optimizer:

julia> inner_optimizer = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> optimizer = MOI.Bridges.LazyBridgeOptimizer(inner_optimizer)
+MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}
+with 0 variable bridges
+with 0 constraint bridges
+with 0 objective bridges
+with inner model MOIU.Model{Float64}

Then use Bridges.add_bridge to add individual bridges:

julia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Constraint.SplitIntervalBridge{Float64})
+
+julia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Objective.FunctionizeBridge{Float64})

Now the constraints will be bridged only if needed:

julia> x = MOI.add_variable(optimizer)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(optimizer, x, MOI.Interval(0.0, 1.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
+
+julia> MOI.get(optimizer, MOI.ListOfConstraintTypesPresent())
+1-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})
+
+julia> MOI.get(inner_optimizer, MOI.ListOfConstraintTypesPresent())
+1-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})
diff --git a/previews/PR2274/submodules/Bridges/reference/index.html b/previews/PR2274/submodules/Bridges/reference/index.html new file mode 100644 index 0000000000..c3b3ae36d0 --- /dev/null +++ b/previews/PR2274/submodules/Bridges/reference/index.html @@ -0,0 +1,195 @@ + +API Reference · MathOptInterface

Bridges

AbstractBridge API

MathOptInterface.Bridges.AbstractBridgeType
abstract type AbstractBridge end

An abstract type representing a bridged constraint or variable in a MOI.Bridges.AbstractBridgeOptimizer.

All bridges must implement:

Subtypes of AbstractBridge may have additional requirements. Consult their docstrings for details.

In addition, all subtypes may optionally implement the following constraint attributes with the bridge in place of the constraint index:

source
MathOptInterface.Bridges.added_constrained_variable_typesFunction
added_constrained_variable_types(
+    BT::Type{<:AbstractBridge},
+)::Vector{Tuple{Type}}

Return a list of the types of constrained variables that bridges of concrete type BT add.

Implementation notes

  • This method depends only on the type of the bridge, not the runtime value. If the bridge may add a constrained variable, the type must be included in the return vector.
  • If the bridge adds a free variable via MOI.add_variable or MOI.add_variables, the return vector must include (MOI.Reals,).

Example

julia> MOI.Bridges.added_constrained_variable_types(
+           MOI.Bridges.Variable.NonposToNonnegBridge{Float64},
+       )
+1-element Vector{Tuple{Type}}:
+ (MathOptInterface.Nonnegatives,)
source
MathOptInterface.Bridges.added_constraint_typesFunction
added_constraint_types(
+    BT::Type{<:AbstractBridge},
+)::Vector{Tuple{Type,Type}}

Return a list of the types of constraints that bridges of concrete type BT add.

Implementation notes

  • This method depends only on the type of the bridge, not the runtime value. If the bridge may add a constraint, the type must be included in the return vector.

Example

julia> MOI.Bridges.added_constraint_types(
+           MOI.Bridges.Constraint.ZeroOneBridge{Float64},
+       )
+2-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.Interval{Float64})
+ (MathOptInterface.VariableIndex, MathOptInterface.Integer)
source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64

Return the number of variables created by the bridge b in the model.

See also MOI.NumberOfConstraints.

Implementation notes

  • There is a default fallback, so you need only implement this if the bridge adds new variables.
source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)

Return the list of variables created by the bridge b.

See also MOI.ListOfVariableIndices.

Implementation notes

  • There is a default fallback, so you need only implement this if the bridge adds new variables.
source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}

Return the number of constraints of the type F-in-S created by the bridge b.

See also MOI.NumberOfConstraints.

Implementation notes

  • There is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.
source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}

Return a Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-in-S created by the bride b.

See also MOI.ListOfConstraintIndices.

Implementation notes

  • There is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.
source
MathOptInterface.Bridges.final_touchFunction
final_touch(bridge::AbstractBridge, model::MOI.ModelLike)::Nothing

A function that is called immediately prior to MOI.optimize! to allow bridges to modify their reformulations with repsect to other variables and constraints in model.

For example, if the correctness of bridge depends on the bounds of a variable or the fact that variables are integer, then the bridge can implement final_touch to check assumptions immediately before a call to MOI.optimize!.

If you implement this method, you must also implement needs_final_touch.

source
MathOptInterface.Bridges.bridging_costFunction
bridging_cost(b::AbstractBridgeOptimizer, S::Type{<:MOI.AbstractSet}})

Return the cost of bridging variables constrained in S on creation, is_bridged(b, S) is assumed to be true.

bridging_cost(
+    b::AbstractBridgeOptimizer,
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet},
+)

Return the cost of bridging F-in-S constraints.

is_bridged(b, S) is assumed to be true.

source

Constraint bridge API

MathOptInterface.supports_constraintMethod
MOI.supports_constraint(
+    BT::Type{<:AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet},
+)::Bool

Return a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.

Implementation notes

  • This method depends only on the type of the inputs, not the runtime values.
  • There is a default fallback, so you need only implement this method for constraint types that the bridge implements.
source
MathOptInterface.Bridges.Constraint.concrete_bridge_typeFunction
concrete_bridge_type(
+    BT::Type{<:AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet}
+)::Type

Return the concrete type of the bridge supporting F-in-S constraints.

This function can only be called if MOI.supports_constraint(BT, F, S) is true.

Example

The SplitIntervalBridge bridges a MOI.VariableIndex-in-MOI.Interval constraint into a MOI.VariableIndex-in-MOI.GreaterThan and a MOI.VariableIndex-in-MOI.LessThan constraint.

julia> MOI.Bridges.Constraint.concrete_bridge_type(
+           MOI.Bridges.Constraint.SplitIntervalBridge{Float64},
+           MOI.VariableIndex,
+           MOI.Interval{Float64},
+       )
+MathOptInterface.Bridges.Constraint.SplitIntervalBridge{Float64, MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}, MathOptInterface.GreaterThan{Float64}, MathOptInterface.LessThan{Float64}}
source
MathOptInterface.Bridges.Constraint.bridge_constraintFunction
bridge_constraint(
+    BT::Type{<:AbstractBridge},
+    model::MOI.ModelLike,
+    func::AbstractFunction,
+    set::MOI.AbstractSet,
+)::BT

Bridge the constraint func-in-set using bridge BT to model and returns a bridge object of type BT.

Implementation notes

  • The bridge type BT should be a concrete type, that is, all the type parameters of the bridge must be set.
source
MathOptInterface.Bridges.Constraint.SingleBridgeOptimizerType
SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)

Return AbstractBridgeOptimizer that always bridges any objective function supported by the bridge BT.

This is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the objective function if it is supported by the bridge BT and unsupported by model.

Example

julia> struct MyNewBridge{T} <: MOI.Bridges.Constraint.AbstractBridge end
+
+julia> bridge = MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}}(
+           MOI.Utilities.Model{Float64}(),
+       )
+MOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 constraint bridges
+with inner model MOIU.Model{Float64}

Implementation notes

All bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.

julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =
+           MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{T},OT};

This enables users to create bridged models as follows:

julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())
+MOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 constraint bridges
+with inner model MOIU.Model{Float64}
source
MathOptInterface.Bridges.Constraint.SetMapBridgeType
abstract type SetMapBridge{T,S2,S1,F,G} <: AbstractBridge end

Consider two type of sets, S1 and S2, and a linear mapping A such that the image of a set of type S1 under A is a set of type S2.

A SetMapBridge{T,S2,S1,F,G} is a bridge that maps G-in-S1 constraints into F-in-S2 by mapping the function through A.

The linear map A is described by;

Implementing a method for these two functions is sufficient to bridge constraints. However, in order for the getters and setters of attributes such as dual solutions and starting values to work as well, a method for the following functions must be implemented:

See the docstrings of each function to see which feature would be missing if it was not implemented for a given bridge.

source

Objective bridge API

MathOptInterface.Bridges.Objective.supports_objective_functionFunction
supports_objective_function(
+    BT::Type{<:MOI.Bridges.Objective.AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+)::Bool

Return a Bool indicating whether the bridges of type BT support bridging objective functions of type F.

Implementation notes

  • This method depends only on the type of the inputs, not the runtime values.
  • There is a default fallback, so you need only implement this method For objective functions that the bridge implements.
source
MathOptInterface.Bridges.set_objective_function_typeFunction
set_objective_function_type(
+    BT::Type{<:Objective.AbstractBridge},
+)::Type{<:MOI.AbstractFunction}

Return the type of objective function that bridges of concrete type BT set.

Implementation notes

  • This method depends only on the type of the bridge, not the runtime value.

Example

julia> MOI.Bridges.set_objective_function_type(
+           MOI.Bridges.Objective.FunctionizeBridge{Float64},
+       )
+MathOptInterface.ScalarAffineFunction{Float64}
source
MathOptInterface.Bridges.Objective.concrete_bridge_typeFunction
concrete_bridge_type(
+    BT::Type{<:MOI.Bridges.Objective.AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+)::Type

Return the concrete type of the bridge supporting objective functions of type F.

This function can only be called if MOI.supports_objective_function(BT, F) is true.

source
MathOptInterface.Bridges.Objective.bridge_objectiveFunction
bridge_objective(
+    BT::Type{<:MOI.Bridges.Objective.AbstractBridge},
+    model::MOI.ModelLike,
+    func::MOI.AbstractFunction,
+)::BT

Bridge the objective function func using bridge BT to model and returns a bridge object of type BT.

Implementation notes

  • The bridge type BT must be a concrete type, that is, all the type parameters of the bridge must be set.
source
MathOptInterface.Bridges.Objective.SingleBridgeOptimizerType
SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)

Return AbstractBridgeOptimizer that always bridges any objective function supported by the bridge BT.

This is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the objective function if it is supported by the bridge BT and unsupported by model.

Example

julia> struct MyNewBridge{T} <: MOI.Bridges.Objective.AbstractBridge end
+
+julia> bridge = MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}}(
+           MOI.Utilities.Model{Float64}(),
+       )
+MOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 objective bridges
+with inner model MOIU.Model{Float64}

Implementation notes

All bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.

julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =
+           MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{T},OT};

This enables users to create bridged models as follows:

julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())
+MOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 objective bridges
+with inner model MOIU.Model{Float64}
source

Variable bridge API

MathOptInterface.Bridges.Variable.supports_constrained_variableFunction
supports_constrained_variable(
+    BT::Type{<:AbstractBridge},
+    S::Type{<:MOI.AbstractSet},
+)::Bool

Return a Bool indicating whether the bridges of type BT support bridging constrained variables in S. That is, it returns true if the bridge of type BT converts constrained variables of type S into a form supported by the solver.

Implementation notes

  • This method depends only on the type of the bridge and set, not the runtime values.
  • There is a default fallback, so you need only implement this method for sets that the bridge implements.

Example

julia> MOI.Bridges.Variable.supports_constrained_variable(
+           MOI.Bridges.Variable.NonposToNonnegBridge{Float64},
+           MOI.Nonpositives,
+       )
+true
+
+julia> MOI.Bridges.Variable.supports_constrained_variable(
+           MOI.Bridges.Variable.NonposToNonnegBridge{Float64},
+           MOI.Nonnegatives,
+       )
+false
source
MathOptInterface.Bridges.Variable.concrete_bridge_typeFunction
concrete_bridge_type(
+    BT::Type{<:AbstractBridge},
+    S::Type{<:MOI.AbstractSet},
+)::Type

Return the concrete type of the bridge supporting variables in S constraints.

This function can only be called if MOI.supports_constrained_variable(BT, S) is true.

Examples

As a variable in MOI.GreaterThan is bridged into variables in MOI.Nonnegatives by the VectorizeBridge:

julia> MOI.Bridges.Variable.concrete_bridge_type(
+           MOI.Bridges.Variable.VectorizeBridge{Float64},
+           MOI.GreaterThan{Float64},
+       )
+MathOptInterface.Bridges.Variable.VectorizeBridge{Float64, MathOptInterface.Nonnegatives}
source
MathOptInterface.Bridges.Variable.bridge_constrained_variableFunction
bridge_constrained_variable(
+    BT::Type{<:AbstractBridge},
+    model::MOI.ModelLike,
+    set::MOI.AbstractSet,
+)::BT

Bridge the constrained variable in set using bridge BT to model and returns a bridge object of type BT.

Implementation notes

  • The bridge type BT must be a concrete type, that is, all the type parameters of the bridge must be set.
source
MathOptInterface.Bridges.Variable.SingleBridgeOptimizerType
SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)

Return MOI.Bridges.AbstractBridgeOptimizer that always bridges any variables constrained on creation supported by the bridge BT.

This is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the variables constrained on creation if they are supported by the bridge BT and unsupported by model.

Warning

Two SingleBridgeOptimizers cannot be used together as both of them assume that the underlying model only returns variable indices with nonnegative values. Use MOI.Bridges.LazyBridgeOptimizer instead.

Example

julia> struct MyNewBridge{T} <: MOI.Bridges.Variable.AbstractBridge end
+
+julia> bridge = MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}}(
+           MOI.Utilities.Model{Float64}(),
+       )
+MOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 variable bridges
+with inner model MOIU.Model{Float64}

Implementation notes

All bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.

julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =
+           MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{T},OT};

This enables users to create bridged models as follows:

julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())
+MOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 variable bridges
+with inner model MOIU.Model{Float64}
source
MathOptInterface.Bridges.Variable.SetMapBridgeType
abstract type SetMapBridge{T,S1,S2} <: AbstractBridge end

Consider two type of sets, S1 and S2, and a linear mapping A such that the image of a set of type S1 under A is a set of type S2.

A SetMapBridge{T,S1,S2} is a bridge that substitutes constrained variables in S2 into the image through A of constrained variables in S1.

The linear map A is described by:

Implementing a method for these two functions is sufficient to bridge constrained variables. However, in order for the getters and setters of attributes such as dual solutions and starting values to work as well, a method for the following functions must be implemented:

See the docstrings of each function to see which feature would be missing if it was not implemented for a given bridge.

source
MathOptInterface.Bridges.Variable.unbridged_mapFunction
unbridged_map(
+   bridge::MOI.Bridges.Variable.AbstractBridge,
+    vi::MOI.VariableIndex,
+)

For a bridged variable in a scalar set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vi.

unbridged_map(
+    bridge::MOI.Bridges.Variable.AbstractBridge,
+    vis::Vector{MOI.VariableIndex},
+)

For a bridged variable in a vector set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vis. If this method is not implemented, it falls back to calling the following method for every variable of vis.

unbridged_map(
+    bridge::MOI.Bridges.Variable.AbstractBridge,
+    vi::MOI.VariableIndex,
+    i::MOI.Bridges.IndexInVector,
+)

For a bridged variable in a vector set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vi corresponding to the ith variable of the vector.

If there is no way to recover the expression in terms of the bridged variable(s) vi(s), return nothing. See ZerosBridge for an example of bridge returning nothing.

source

AbstractBridgeOptimizer API

MathOptInterface.Bridges.bridged_variable_functionFunction
bridged_variable_function(
+    b::AbstractBridgeOptimizer,
+    vi::MOI.VariableIndex,
+)

Return a MOI.AbstractScalarFunction of variables of b.model that equals vi. That is, if the variable vi is bridged, it returns its expression in terms of the variables of b.model. Otherwise, it returns vi.

source
MathOptInterface.Bridges.unbridged_variable_functionFunction
unbridged_variable_function(
+    b::AbstractBridgeOptimizer,
+    vi::MOI.VariableIndex,
+)

Return a MOI.AbstractScalarFunction of variables of b that equals vi. That is, if the variable vi is an internal variable of b.model created by a bridge but not visible to the user, it returns its expression in terms of the variables of bridged variables. Otherwise, it returns vi.

source
MathOptInterface.Bridges.recursive_modelFunction
recursive_model(b::AbstractBridgeOptimizer)

If a variable, constraint, or objective is bridged, return the context of the inner variables. For most optimizers, this should be b.model.

source

LazyBridgeOptimizer API

MathOptInterface.Bridges.LazyBridgeOptimizerType
LazyBridgeOptimizer(model::MOI.ModelLike)

The LazyBridgeOptimizer is a bridge optimizer that supports multiple bridges, and only bridges things which are not supported by the internal model.

Internally, the LazyBridgeOptimizer solves a shortest hyper-path problem to determine which bridges to use.

In general, you should use full_bridge_optimizer instead of this constructor because full_bridge_optimizer automatically adds a large number of supported bridges.

See also: add_bridge, remove_bridge, has_bridge and full_bridge_optimizer.

Example

julia> model = MOI.Bridges.LazyBridgeOptimizer(MOI.Utilities.Model{Float64}())
+MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}
+with 0 variable bridges
+with 0 constraint bridges
+with 0 objective bridges
+with inner model MOIU.Model{Float64}
+
+julia> MOI.Bridges.add_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64})
+
+julia> MOI.Bridges.has_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64})
+true
source
MathOptInterface.Bridges.full_bridge_optimizerFunction
full_bridge_optimizer(model::MOI.ModelLike, ::Type{T}) where {T}

Returns a LazyBridgeOptimizer bridging model for every bridge defined in this package (see below for the few exceptions) and for the coefficient type T, as well as the bridges in the list returned by the ListOfNonstandardBridges attribute.

Example

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> bridged_model = MOI.Bridges.full_bridge_optimizer(model, Float64);

Exceptions

The following bridges are not added by full_bridge_optimizer, except if they are in the list returned by the ListOfNonstandardBridges attribute:

See the docstring of the each bridge for the reason they are not added.

source
MathOptInterface.Bridges.ListOfNonstandardBridgesType
ListOfNonstandardBridges{T}() <: MOI.AbstractOptimizerAttribute

Any optimizer can be wrapped in a LazyBridgeOptimizer using full_bridge_optimizer. However, by default LazyBridgeOptimizer uses a limited set of bridges that are:

  1. implemented in MOI.Bridges
  2. generally applicable for all optimizers.

For some optimizers however, it is useful to add additional bridges, such as those that are implemented in external packages (e.g., within the solver package itself) or only apply in certain circumstances (e.g., Constraint.SOCtoNonConvexQuadBridge).

Such optimizers should implement the ListOfNonstandardBridges attribute to return a vector of bridge types that are added by full_bridge_optimizer in addition to the list of default bridges.

Note that optimizers implementing ListOfNonstandardBridges may require package-specific functions or sets to be used if the non-standard bridges are not added. Therefore, you are recommended to use model = MOI.instantiate(Package.Optimizer; with_bridge_type = T) instead of model = MOI.instantiate(Package.Optimizer). See MOI.instantiate.

Examples

An optimizer using a non-default bridge in MOI.Bridges

Solvers supporting MOI.ScalarQuadraticFunction can support MOI.SecondOrderCone and MOI.RotatedSecondOrderCone by defining:

function MOI.get(::MyQuadraticOptimizer, ::ListOfNonstandardBridges{Float64})
+    return Type[
+        MOI.Bridges.Constraint.SOCtoNonConvexQuadBridge{Float64},
+        MOI.Bridges.Constraint.RSOCtoNonConvexQuadBridge{Float64},
+    ]
+end

An optimizer defining an internal bridge

Suppose an optimizer can exploit specific structure of a constraint, e.g., it can exploit the structure of the matrix A in the linear system of equations A * x = b.

The optimizer can define the function:

struct MatrixAffineFunction{T} <: MOI.AbstractVectorFunction
+    A::SomeStructuredMatrixType{T}
+    b::Vector{T}
+end

and then a bridge

struct MatrixAffineFunctionBridge{T} <: MOI.Constraint.AbstractBridge
+    # ...
+end
+# ...

from VectorAffineFunction{T} to the MatrixAffineFunction. Finally, it defines:

function MOI.get(::Optimizer{T}, ::ListOfNonstandardBridges{T}) where {T}
+    return Type[MatrixAffineFunctionBridge{T}]
+end
source
MathOptInterface.Bridges.print_active_bridgesFunction
print_active_bridges([io::IO=stdout,] b::MOI.Bridges.LazyBridgeOptimizer)

Print the set of bridges that are active in the model b.

source
print_active_bridges(
+    [io::IO=stdout,]
+    b::MOI.Bridges.LazyBridgeOptimizer,
+    F::Type{<:MOI.AbstractFunction}
+)

Print the set of bridges required for an objective function of type F.

source
print_active_bridges(
+    [io::IO=stdout,]
+    b::MOI.Bridges.LazyBridgeOptimizer,
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet},
+)

Print the set of bridges required for a constraint of type F-in-S.

source
print_active_bridges(
+    [io::IO=stdout,]
+    b::MOI.Bridges.LazyBridgeOptimizer,
+    S::Type{<:MOI.AbstractSet}
+)

Print the set of bridges required for a variable constrained to set S.

source
MathOptInterface.Bridges.print_graphFunction
print_graph([io::IO = stdout,] b::LazyBridgeOptimizer)

Print the hyper-graph containing all variable, constraint, and objective types that could be obtained by bridging the variables, constraints, and objectives that are present in the model by all the bridges added to b.

Each node in the hyper-graph corresponds to a variable, constraint, or objective type.

  • Variable nodes are indicated by [ ]
  • Constraint nodes are indicated by ( )
  • Objective nodes are indicated by | |

The number inside each pair of brackets is an index of the node in the hyper-graph.

Note that this hyper-graph is the full list of possible transformations. When the bridged model is created, we select the shortest hyper-path(s) from this graph, so many nodes may be un-used.

To see which nodes are used, call print_active_bridges.

For more information, see Legat, B., Dowson, O., Garcia, J., and Lubin, M. (2020). "MathOptInterface: a data structure for mathematical optimization problems." URL: https://arxiv.org/abs/2002.03447

source

SetMap API

MathOptInterface.Bridges.map_functionFunction
map_function(::Type{BT}, func) where {BT}

Return the image of func through the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintPrimal of variable bridges. For constraint bridges, this is used for bridging the constraint, setting the MOI.ConstraintFunction and MOI.ConstraintPrimalStart and modifying the function with MOI.modify.

map_function(::Type{BT}, func, i::IndexInVector) where {BT}

Return the scalar function at the ith index of the vector function that would be returned by map_function(BT, func) except that it may compute the ith element. This is used by bridged_function and for getting the MOI.VariablePrimal and MOI.VariablePrimalStart of variable bridges.

source

Bridging graph API

MathOptInterface.Bridges.GraphType
Graph()

A type-stable datastructure for computing the shortest hyperpath problem.

Nodes

There are three types of nodes in the graph:

Add nodes to the graph using add_node.

Edges

There are two types of edges in the graph:

Add edges to the graph using add_edge.

For the ability to add a variable constrained on creation as a free variable followed by a constraint, use set_variable_constraint_node.

Optimal hyper-edges

Use bridge_index to compute the minimum-cost bridge leaving a node.

Note that bridge_index lazy runs a Bellman-Ford algorithm to compute the set of minimum cost edges. Thus, the first call to bridge_index after adding new nodes or edges will take longer than subsequent calls.

source
MathOptInterface.Bridges.add_nodeFunction
add_node(graph::Graph, ::Type{VariableNode})::VariableNode
+add_node(graph::Graph, ::Type{ConstraintNode})::ConstraintNode
+add_node(graph::Graph, ::Type{ObjectiveNode})::ObjectiveNode

Add a new node to graph.

source
MathOptInterface.Bridges.add_edgeFunction
add_edge(graph::Graph, node::VariableNode, edge::Edge)::Nothing
+add_edge(graph::Graph, node::ConstraintNode, edge::Edge)::Nothing
+add_edge(graph::Graph, node::ObjectiveNode, edge::ObjectiveEdge)::Nothing

Add edge to graph, where edge starts at node and connects to the nodes defined in edge.

source
MathOptInterface.Bridges.set_variable_constraint_nodeFunction
set_variable_constraint_node(
+    graph::Graph,
+    variable_node::VariableNode,
+    constraint_node::ConstraintNode,
+    cost::Int,
+)

As an alternative to variable_node, add a virtual edge to graph that represents adding a free variable, followed by a constraint of type constraint_node, with bridging cost cost.

Why is this needed?

Variables can either be added as a variable constrained on creation, or as a free variable which then has a constraint added to it.

source
MathOptInterface.Bridges.bridge_indexFunction
bridge_index(graph::Graph, node::VariableNode)::Int
+bridge_index(graph::Graph, node::ConstraintNode)::Int
+bridge_index(graph::Graph, node::ObjectiveNode)::Int

Return the optimal index of the bridge to chose from node.

source
MathOptInterface.Bridges.is_variable_edge_bestFunction
is_variable_edge_best(graph::Graph, node::VariableNode)::Bool

Return a Bool indicating whether node should be added as a variable constrained on creation, or as a free variable followed by a constraint.

source
diff --git a/previews/PR2274/submodules/FileFormats/overview/index.html b/previews/PR2274/submodules/FileFormats/overview/index.html new file mode 100644 index 0000000000..54147cde73 --- /dev/null +++ b/previews/PR2274/submodules/FileFormats/overview/index.html @@ -0,0 +1,137 @@ + +Overview · MathOptInterface

The FileFormats submodule

The FileFormats module provides functions for reading and writing MOI models using write_to_file and read_from_file.

Supported file types

You must read and write files to a FileFormats.Model object. Specific the file-type by passing a FileFormats.FileFormat enum. For example:

The Conic Benchmark Format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF)
+A Conic Benchmark Format (CBF) model

The LP file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_LP)
+A .LP-file model

The MathOptFormat file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)
+A MathOptFormat Model

The MPS file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)
+A Mathematical Programming System (MPS) model

The NL file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_NL)
+An AMPL (.nl) model

The REW file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_REW)
+A Mathematical Programming System (MPS) model

Note that the REW format is identical to the MPS file format, except that all names are replaced with generic identifiers.

The SDPA file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_SDPA)
+A SemiDefinite Programming Algorithm Format (SDPA) model

Write to file

To write a model src to a MathOptFormat file, use:

julia> src = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> MOI.add_variable(src)
+MOI.VariableIndex(1)
+
+julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)
+A MathOptFormat Model
+
+julia> MOI.copy_to(dest, src)
+MathOptInterface.Utilities.IndexMap with 1 entry:
+  MOI.VariableIndex(1) => MOI.VariableIndex(1)
+
+julia> MOI.write_to_file(dest, "file.mof.json")
+
+julia> print(read("file.mof.json", String))
+{
+  "name": "MathOptFormat Model",
+  "version": {
+    "major": 1,
+    "minor": 5
+  },
+  "variables": [
+    {
+      "name": "x1"
+    }
+  ],
+  "objective": {
+    "sense": "feasibility"
+  },
+  "constraints": []
+}

Read from file

To read a MathOptFormat file, use:

julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)
+A MathOptFormat Model
+
+julia> MOI.read_from_file(dest, "file.mof.json")
+
+julia> MOI.get(dest, MOI.ListOfVariableIndices())
+1-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+
+julia> rm("file.mof.json")  # Clean up after ourselves.

Detecting the file-type automatically

Instead of the format keyword, you can also use the filename keyword argument to FileFormats.Model. This will attempt to automatically guess the format from the file extension. For example:

julia> src = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> dest = MOI.FileFormats.Model(filename = "file.cbf.gz")
+A Conic Benchmark Format (CBF) model
+
+julia> MOI.copy_to(dest, src)
+MathOptInterface.Utilities.IndexMap()
+
+julia> MOI.write_to_file(dest, "file.cbf.gz")
+
+julia> src_2 = MOI.FileFormats.Model(filename = "file.cbf.gz")
+A Conic Benchmark Format (CBF) model
+
+julia> src = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> dest = MOI.FileFormats.Model(filename = "file.cbf.gz")
+A Conic Benchmark Format (CBF) model
+
+julia> MOI.copy_to(dest, src)
+MathOptInterface.Utilities.IndexMap()
+
+julia> MOI.write_to_file(dest, "file.cbf.gz")
+
+julia> src_2 = MOI.FileFormats.Model(filename = "file.cbf.gz")
+A Conic Benchmark Format (CBF) model
+
+julia> MOI.read_from_file(src_2, "file.cbf.gz")
+
+julia> rm("file.cbf.gz")  # Clean up after ourselves.

Note how the compression format (GZip) is also automatically detected from the filename.

Unsupported constraints

In some cases src may contain constraints that are not supported by the file format (for example, the CBF format supports integer variables but not binary). If so, copy src to a bridged model using Bridges.full_bridge_optimizer:

src = MOI.Utilities.Model{Float64}()
+x = MOI.add_variable(model)
+MOI.add_constraint(model, x, MOI.ZeroOne())
+dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF)
+bridged = MOI.Bridges.full_bridge_optimizer(dest, Float64)
+MOI.copy_to(bridged, src)
+MOI.write_to_file(dest, "my_model.cbf")
Note

Even after bridging, it may still not be possible to write the model to file because of unsupported constraints (for example, PSD variables in the LP file format).

Read and write to io

In addition to write_to_file and read_from_file, you can read and write directly from IO streams using Base.write and Base.read!:

julia> src = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)
+A Mathematical Programming System (MPS) model
+
+julia> MOI.copy_to(dest, src)
+MathOptInterface.Utilities.IndexMap()
+
+julia> io = IOBuffer();
+
+julia> write(io, dest)
+
+julia> seekstart(io);
+
+julia> src_2 = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)
+A Mathematical Programming System (MPS) model
+
+julia> read!(io, src_2);

Validating MOF files

MathOptFormat files are governed by a schema. Use JSONSchema.jl to check if a .mof.json file satisfies the schema.

First, construct the schema object as follows:

julia> import JSON, JSONSchema
+
+julia> schema = JSONSchema.Schema(JSON.parsefile(MOI.FileFormats.MOF.SCHEMA_PATH))
+A JSONSchema

Then, check if a model file is valid using isvalid:

julia> good_model = JSON.parse("""
+       {
+         "version": {
+           "major": 1,
+           "minor": 5
+         },
+         "variables": [{"name": "x"}],
+         "objective": {"sense": "feasibility"},
+         "constraints": []
+       }
+       """);
+
+julia> isvalid(schema, good_model)
+true

If we construct an invalid file, for example by mis-typing name as NaMe, the validation fails:

julia> bad_model = JSON.parse("""
+       {
+         "version": {
+           "major": 1,
+           "minor": 5
+         },
+         "variables": [{"NaMe": "x"}],
+         "objective": {"sense": "feasibility"},
+         "constraints": []
+       }
+       """);
+
+julia> isvalid(schema, bad_model)
+false

Use JSONSchema.validate to obtain more insight into why the validation failed:

julia> JSONSchema.validate(schema, bad_model)
+Validation failed:
+path:         [variables][1]
+instance:     Dict{String, Any}("NaMe" => "x")
+schema key:   required
+schema value: Any["name"]
diff --git a/previews/PR2274/submodules/FileFormats/reference/index.html b/previews/PR2274/submodules/FileFormats/reference/index.html new file mode 100644 index 0000000000..0d22564f4c --- /dev/null +++ b/previews/PR2274/submodules/FileFormats/reference/index.html @@ -0,0 +1,18 @@ + +API Reference · MathOptInterface

File Formats

Functions to help read and write MOI models to/from various file formats. See The FileFormats submodule for more details.

MathOptInterface.FileFormats.ModelFunction
Model(
+    ;
+    format::FileFormat = FORMAT_AUTOMATIC,
+    filename::Union{Nothing, String} = nothing,
+    kwargs...
+)

Return model corresponding to the FileFormat format, or, if format == FORMAT_AUTOMATIC, guess the format from filename.

The filename argument is only needed if format == FORMAT_AUTOMATIC.

kwargs are passed to the underlying model constructor.

source
MathOptInterface.FileFormats.FileFormatType
FileFormat

List of accepted export formats.

  • FORMAT_AUTOMATIC: try to detect the file format based on the file name
  • FORMAT_CBF: the Conic Benchmark format
  • FORMAT_LP: the LP file format
  • FORMAT_MOF: the MathOptFormat file format
  • FORMAT_MPS: the MPS file format
  • FORMAT_NL: the AMPL .nl file format
  • FORMAT_REW: the .rew file format, which is MPS with generic names
  • FORMAT_SDPA: the SemiDefinite Programming Algorithm format
source
MathOptInterface.FileFormats.LP.ModelType
Model(; kwargs...)

Create an empty instance of FileFormats.LP.Model.

Keyword arguments are:

  • maximum_length::Int=255: the maximum length for the name of a variable. lp_solve 5.0 allows only 16 characters, while CPLEX 12.5+ allow 255.

  • warn::Bool=false: print a warning when variables or constraints are renamed.

source
MathOptInterface.FileFormats.MOF.ModelType
Model(; kwargs...)

Create an empty instance of FileFormats.MOF.Model.

Keyword arguments are:

  • print_compact::Bool=false: print the JSON file in a compact format without spaces or newlines.
  • warn::Bool=false: print a warning when variables or constraints are renamed
  • differentiation_backend::MOI.Nonlinear.AbstractAutomaticDifferentiation = MOI.Nonlinear.SparseReverseMode(): automatic differentiation backend to use when reading models with nonlinear constraints and objectives.
source
MathOptInterface.FileFormats.MPS.ModelType
Model(; kwargs...)

Create an empty instance of FileFormats.MPS.Model.

Keyword arguments are:

  • warn::Bool=false: print a warning when variables or constraints are renamed.
  • print_objsense::Bool=false: print the OBJSENSE section when writing
  • generic_names::Bool=false: strip all names in the model and replace them with the generic names C$i and R$i for the i'th column and row respectively.
  • quadratic_format::QuadraticFormat = kQuadraticFormatGurobi: specify the solver-specific extension used when writing the quadratic components of the model. Options are kQuadraticFormatGurobi, kQuadraticFormatCPLEX, and kQuadraticFormatMosek.
source
MathOptInterface.FileFormats.SDPA.ModelType
Model(; number_type::Type = Float64)

Create an empty instance of FileFormats.SDPA.Model{number_type}.

It is important to be aware that the SDPA file format is interpreted in geometric form and not standard conic form. The standard conic form and geometric conic form are two dual standard forms for semidefinite programs (SDPs). The geometric conic form of an SDP is as follows:

\[\begin{align} +& \min_{y \in \mathbb{R}^m} & b^T y +\\ +& \;\;\text{s.t.} & \sum_{i=1}^m A_i y_i - C & \in \mathbb{K} +\end{align}\]

where $\mathcal{K}$ is a cartesian product of nonnegative orthant and positive semidefinite matrices that align with a block diagonal structure shared with the matrices A_i and C.

In other words, the geometric conic form contains free variables and affine constraints in either the nonnegative orthant or the positive semidefinite cone. That is, in the MathOptInterface's terminology, MOI.VectorAffineFunction-in-MOI.Nonnegatives and MOI.VectorAffineFunction-in-MOI.PositiveSemidefiniteConeTriangle constraints.

The corresponding standard conic form of the dual SDP is as follows:

\[\begin{align} +& \max_{X \in \mathbb{K}} & \text{tr}(CX) +\\ +& \;\;\text{s.t.} & \text{tr}(A_iX) & = b_i & i = 1, \ldots, m. +\end{align}\]

In other words, the standard conic form contains nonnegative and positive semidefinite variables with equality constraints. That is, in the MathOptInterface's terminology, MOI.VectorOfVariables-in-MOI.Nonnegatives, MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle and MOI.ScalarAffineFunction-in-MOI.EqualTo constraints.

If a model is in standard conic form, use Dualization.jl to transform it into the geometric conic form before writting it. Otherwise, the nonnegative (resp. positive semidefinite) variables will be bridged into free variables with affine constraints constraining them to belong to the nonnegative orthant (resp. positive semidefinite cone) by the MOI.Bridges.Constraint.VectorFunctionizeBridge. Moreover, equality constraints will be bridged into pairs of affine constraints in the nonnegative orthant by the MOI.Bridges.Constraint.SplitIntervalBridge and then the MOI.Bridges.Constraint.VectorizeBridge.

If a solver is in standard conic form, use Dualization.jl to transform the model read into standard conic form before copying it to the solver. Otherwise, the free variables will be bridged into pairs of variables in the nonnegative orthant by the MOI.Bridges.Variable.FreeBridge and affine constraints will be bridged into equality constraints by creating a slack variable by the MOI.Bridges.Constraint.VectorSlackBridge.

source

Other helpers

MathOptInterface.FileFormats.NL.SolFileResultsType
SolFileResults(filename::String, model::Model)

Parse the .sol file filename created by solving model and return a SolFileResults struct.

The returned struct supports the MOI.get API for querying result attributes such as MOI.TerminationStatus, MOI.VariablePrimal, and MOI.ConstraintDual.

source
SolFileResults(
+    raw_status::String,
+    termination_status::MOI.TerminationStatusCode,
+)

Return a SolFileResults struct with MOI.RawStatusString set to raw_status, MOI.TerminationStatus set to termination_status, and MOI.PrimalStatus and MOI.DualStatus set to NO_SOLUTION.

All other attributes are un-set.

source
diff --git a/previews/PR2274/submodules/Nonlinear/overview/index.html b/previews/PR2274/submodules/Nonlinear/overview/index.html new file mode 100644 index 0000000000..d2b1a9c323 --- /dev/null +++ b/previews/PR2274/submodules/Nonlinear/overview/index.html @@ -0,0 +1,183 @@ + +Overview · MathOptInterface

Nonlinear

Warning

The Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.

The Nonlinear submodule contains data structures and functions for working with a nonlinear optimization problem in the form of an expression graph. This page explains the API and describes the rationale behind its design.

Standard form

Nonlinear programs (NLPs) are a class of optimization problems in which some of the constraints or the objective function are nonlinear:

\[\begin{align} + \min_{x \in \mathbb{R}^n} & f_0(x) \\ + \;\;\text{s.t.} & l_j \le f_j(x) \le u_j & j = 1 \ldots m +\end{align}\]

There may be additional constraints, as well as things like variable bounds and integrality restrictions, but we do not consider them here because they are best dealt with by other components of MathOptInterface.

API overview

The core element of the Nonlinear submodule is Nonlinear.Model:

julia> const Nonlinear = MOI.Nonlinear;
+
+julia> model = Nonlinear.Model()
+A Nonlinear.Model with:
+ 0 objectives
+ 0 parameters
+ 0 expressions
+ 0 constraints

Nonlinear.Model is a mutable struct that stores all of the nonlinear information added to the model.

Decision variables

Decision variables are represented by VariableIndexes. The user is responsible for creating these using MOI.VariableIndex(i), where i is the column associated with the variable.

Expressions

The input data structure is a Julia Expr. The input expressions can incorporate VariableIndexes, but these must be interpolated into the expression with $:

julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> input = :(1 + sin($x)^2)
+:(1 + sin(MathOptInterface.VariableIndex(1)) ^ 2)

There are a number of restrictions on the input Expr:

  • It cannot contain macros
  • It cannot contain broadcasting
  • It cannot contain splatting (except in limited situations)
  • It cannot contain linear algebra, such as matrix-vector products
  • It cannot contain generator expressions, including sum(i for i in S)

Given an input expression, add an expression using Nonlinear.add_expression:

julia> expr = Nonlinear.add_expression(model, input)
+MathOptInterface.Nonlinear.ExpressionIndex(1)

The return value, expr, is a Nonlinear.ExpressionIndex that can then be interpolated into other input expressions.

Looking again at model, we see:

julia> model
+A Nonlinear.Model with:
+ 0 objectives
+ 0 parameters
+ 1 expression
+ 0 constraints

Parameters

In addition to constant literals like 1 or 1.23, you can create parameters. Parameters are placeholders whose values can change before passing the expression to the solver. Create a parameter using Nonlinear.add_parameter, which accepts a default value:

julia> p = Nonlinear.add_parameter(model, 1.23)
+MathOptInterface.Nonlinear.ParameterIndex(1)

The return value, p, is a Nonlinear.ParameterIndex that can then be interpolated into other input expressions.

Looking again at model, we see:

julia> model
+A Nonlinear.Model with:
+ 0 objectives
+ 1 parameter
+ 1 expression
+ 0 constraints

Update a parameter as follows:

julia> model[p]
+1.23
+
+julia> model[p] = 4.56
+4.56
+
+julia> model[p]
+4.56

Objectives

Set a nonlinear objective using Nonlinear.set_objective:

julia> Nonlinear.set_objective(model, :($p + $expr + $x))
+
+julia> model
+A Nonlinear.Model with:
+ 1 objective
+ 1 parameter
+ 1 expression
+ 0 constraints

Clear a nonlinear objective by passing nothing:

julia> Nonlinear.set_objective(model, nothing)
+
+julia> model
+A Nonlinear.Model with:
+ 0 objectives
+ 1 parameter
+ 1 expression
+ 0 constraints

But we'll re-add the objective for later:

julia> Nonlinear.set_objective(model, :($p + $expr + $x));

Constraints

Add a constraint using Nonlinear.add_constraint:

julia> c = Nonlinear.add_constraint(model, :(1 + sqrt($x)), MOI.LessThan(2.0))
+MathOptInterface.Nonlinear.ConstraintIndex(1)
+
+julia> model
+A Nonlinear.Model with:
+ 1 objective
+ 1 parameter
+ 1 expression
+ 1 constraint

The return value, c, is a Nonlinear.ConstraintIndex that is a unique identifier for the constraint. Interval constraints are also supported:

julia> c2 = Nonlinear.add_constraint(model, :(1 + sqrt($x)), MOI.Interval(-1.0, 2.0))
+MathOptInterface.Nonlinear.ConstraintIndex(2)
+
+julia> model
+A Nonlinear.Model with:
+ 1 objective
+ 1 parameter
+ 1 expression
+ 2 constraints

Delete a constraint using Nonlinear.delete:

julia> Nonlinear.delete(model, c2)
+
+julia> model
+A Nonlinear.Model with:
+ 1 objective
+ 1 parameter
+ 1 expression
+ 1 constraint

User-defined operators

By default, Nonlinear supports a wide range of univariate and multivariate operators. However, you can also define your own operators by registering them.

Univariate operators

Register a univariate user-defined operator using Nonlinear.register_operator:

julia> f(x) = 1 + sin(x)^2
+f (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_f, 1, f)

Now, you can use :my_f in expressions:

julia> new_expr = Nonlinear.add_expression(model, :(my_f($x + 1)))
+MathOptInterface.Nonlinear.ExpressionIndex(2)

By default, Nonlinear will compute first- and second-derivatives of the registered operator using ForwardDiff.jl. Override this by passing functions which compute the respective derivative:

julia> f′(x) = 2 * sin(x) * cos(x)
+f′ (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_f2, 1, f, f′)

or

julia> f′′(x) = 2 * (cos(x)^2 - sin(x)^2)
+f′′ (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_f3, 1, f, f′, f′′)

Multivariate operators

Register a multivariate user-defined operator using Nonlinear.register_operator:

julia> g(x...) = x[1]^2 + x[1] * x[2] + x[2]^2
+g (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_g, 2, g)

Now, you can use :my_g in expressions:

julia> new_expr = Nonlinear.add_expression(model, :(my_g($x + 1, $x)))
+MathOptInterface.Nonlinear.ExpressionIndex(3)

By default, Nonlinear will compute the gradient of the registered operator using ForwardDiff.jl. (Hessian information is not supported.) Override this by passing a function to compute the gradient:

julia> function ∇g(ret, x...)
+           ret[1] = 2 * x[1] + x[2]
+           ret[2] = x[1] + 2 * x[2]
+           return
+       end
+∇g (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_g2, 2, g, ∇g)

MathOptInterface

MathOptInterface communicates the nonlinear portion of an optimization problem to solvers using concrete subtypes of AbstractNLPEvaluator, which implement the Nonlinear programming API.

Create an AbstractNLPEvaluator from Nonlinear.Model using Nonlinear.Evaluator.

Nonlinear.Evaluator requires an Nonlinear.AbstractAutomaticDifferentiation backend and an ordered list of the variables that are included in the model.

There following backends are available to choose from within MOI, although other packages may add more options by sub-typing Nonlinear.AbstractAutomaticDifferentiation:

julia> evaluator = Nonlinear.Evaluator(model, Nonlinear.ExprGraphOnly(), [x])
+Nonlinear.Evaluator with available features:
+  * :ExprGraph

The functions of the Nonlinear programming API implemented by Nonlinear.Evaluator depends upon the chosen Nonlinear.AbstractAutomaticDifferentiation backend.

The :ExprGraph feature means we can call objective_expr and constraint_expr to retrieve the expression graph of the problem. However, we cannot call gradient terms such as eval_objective_gradient because Nonlinear.ExprGraphOnly does not have the capability to differentiate a nonlinear expression.

If, instead, we pass Nonlinear.SparseReverseMode, then we get access to :Grad, the gradient of the objective function, :Jac, the Jacobian matrix of the constraints, :JacVec, the ability to compute Jacobian-vector products, and :ExprGraph.

julia> evaluator = Nonlinear.Evaluator(
+           model,
+           Nonlinear.SparseReverseMode(),
+           [x],
+       )
+Nonlinear.Evaluator with available features:
+  * :Grad
+  * :Jac
+  * :JacVec
+  * :ExprGraph

However, before using the evaluator, we need to call initialize:

julia> MOI.initialize(evaluator, [:Grad, :Jac, :JacVec, :ExprGraph])

Now we can call methods like eval_objective:

julia> x = [1.0]
+1-element Vector{Float64}:
+ 1.0
+
+julia> MOI.eval_objective(evaluator, x)
+7.268073418273571

and eval_objective_gradient:

julia> grad = [0.0]
+1-element Vector{Float64}:
+ 0.0
+
+julia> MOI.eval_objective_gradient(evaluator, grad, x)
+
+julia> grad
+1-element Vector{Float64}:
+ 1.909297426825682

Instead of passing Nonlinear.Evaluator directly to solvers, solvers query the NLPBlock attribute, which returns an NLPBlockData. This object wraps an Nonlinear.Evaluator and includes other information such as constraint bounds and whether the evaluator has a nonlinear objective. Create and set NLPBlockData as follows:

julia> block = MOI.NLPBlockData(evaluator);
+
+julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}());
+
+julia> MOI.set(model, MOI.NLPBlock(), block);
Warning

Only call NLPBlockData once you have finished modifying the problem in model.

Putting everything together, you can create a nonlinear optimization problem in MathOptInterface as follows:

import MathOptInterface as MOI
+
+function build_model(
+    model::MOI.ModelLike;
+    backend::MOI.Nonlinear.AbstractAutomaticDifferentiation,
+)
+    x = MOI.add_variable(model)
+    y = MOI.add_variable(model)
+    MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
+    nl_model = MOI.Nonlinear.Model()
+    MOI.Nonlinear.set_objective(nl_model, :($x^2 + $y^2))
+    evaluator = MOI.Nonlinear.Evaluator(nl_model, backend, [x, y])
+    MOI.set(model, MOI.NLPBlock(), MOI.NLPBlockData(evaluator))
+    return
+end
+
+# Replace `model` and `backend` with your optimizer and backend of choice.
+model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
+build_model(model; backend = MOI.Nonlinear.SparseReverseMode())

Expression-graph representation

Nonlinear.Model stores nonlinear expressions in Nonlinear.Expressions. This section explains the design of the expression graph data structure in Nonlinear.Expression.

Given a nonlinear function like f(x) = sin(x)^2 + x, a conceptual aid for thinking about the graph representation of the expression is to convert it into Polish prefix notation:

f(x, y) = (+ (^ (sin x) 2) x)

This format identifies each operator (function), as well as a list of arguments. Operators can be univariate, like sin, or multivariate, like +.

A common way of representing Polish prefix notation in code is as follows:

julia> x = MOI.VariableIndex(1);
+
+julia> struct ExprNode
+           op::Symbol
+           children::Vector{Union{ExprNode,Float64,MOI.VariableIndex}}
+       end
+
+julia> expr = ExprNode(:+, [ExprNode(:^, [ExprNode(:sin, [x]), 2.0]), x]);

This data structure follows our Polish prefix notation very closely, and we can easily identify the arguments to an operator. However, it has a significant draw-back: each node in the graph requires a Vector, which is heap-allocated and tracked by Julia's garbage collector (GC). For large models, we can expect to have millions of nodes in the expression graph, so this overhead quickly becomes prohibitive for computation.

An alternative is to record the expression as a linear tape:

julia> expr = Any[:+, 2, :^, 2, :sin, 1, x, 2.0, x]
+9-element Vector{Any}:
+  :+
+ 2
+  :^
+ 2
+  :sin
+ 1
+  MOI.VariableIndex(1)
+ 2.0
+  MOI.VariableIndex(1)

The Int after each operator Symbol specifies the number of arguments.

This data-structure is a single vector, which resolves our problem with the GC, but each element is the abstract type, Any, and so any operations on it will lead to slower dynamic dispatch. It's also hard to identify the children of each operation without reading the entire tape.

To summarize, representing expression graphs in Julia has the following challenges:

  • Nodes in the expression graph should not contain a heap-allocated object
  • All data-structures should be concretely typed
  • It should be easy to identify the children of a node

Sketch of the design in Nonlinear

Nonlinear overcomes these problems by decomposing the data structure into a number of different concrete-typed vectors.

First, we create vectors of the supported uni- and multivariate operators.

julia> const UNIVARIATE_OPERATORS = [:sin];
+
+julia> const MULTIVARIATE_OPERATORS = [:+, :^];

In practice, there are many more supported operations than the ones listed here.

Second, we create an enum to represent the different types of nodes present in the expression graph:

julia> @enum(
+           NodeType,
+           NODE_CALL_MULTIVARIATE,
+           NODE_CALL_UNIVARIATE,
+           NODE_VARIABLE,
+           NODE_VALUE,
+       )

In practice, there are node types other than the ones listed here.

Third, we create two concretely typed structs as follows:

julia> struct Node
+           type::NodeType
+           parent::Int
+           index::Int
+       end
+
+julia> struct Expression
+           nodes::Vector{Node}
+           values::Vector{Float64}
+       end

For each node node in the .nodes field, if node.type is:

  • NODE_CALL_MULTIVARIATE, we look up MULTIVARIATE_OPERATORS[node.index] to retrieve the operator
  • NODE_CALL_UNIVARIATE, we look up UNIVARIATE_OPERATORS[node.index] to retrieve the operator
  • NODE_VARIABLE, we create MOI.VariableIndex(node.index)
  • NODE_VALUE, we look up values[node.index]

The .parent field of each node is the integer index of the parent node in .nodes. For the first node, the parent is -1 by convention.

Therefore, we can represent our function as:

julia> expr = Expression(
+           [
+               Node(NODE_CALL_MULTIVARIATE, -1, 1),
+               Node(NODE_CALL_MULTIVARIATE, 1, 2),
+               Node(NODE_CALL_UNIVARIATE, 2, 1),
+               Node(NODE_VARIABLE, 3, 1),
+               Node(NODE_VALUE, 2, 1),
+               Node(NODE_VARIABLE, 1, 1),
+           ],
+           [2.0],
+       );

This is less readable than the other options, but does this data structure meet our design goals?

Instead of a heap-allocated object for each node, we only have two Vectors for each expression, nodes and values, as well as two constant vectors for the OPERATORS. In addition, all fields are concretely typed, and there are no Union or Any types.

For our third goal, it is not easy to identify the children of a node, but it is easy to identify the parent of any node. Therefore, we can use Nonlinear.adjacency_matrix to compute a sparse matrix that maps parents to their children.

The tape is also ordered topologically, so that a reverse pass of the nodes evaluates all children nodes before their parent.

The design in practice

In practice, Node and Expression are exactly Nonlinear.Node and Nonlinear.Expression. However, Nonlinear.NodeType has more fields to account for comparison operators such as :>= and :<=, logic operators such as :&& and :||, nonlinear parameters, and nested subexpressions.

Moreover, instead of storing the operators as global constants, they are stored in Nonlinear.OperatorRegistry, and it also stores a vector of logic operators and a vector of comparison operators. In addition to Nonlinear.DEFAULT_UNIVARIATE_OPERATORS and Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS, you can register user-defined functions using Nonlinear.register_operator.

Nonlinear.Model is a struct that stores the Nonlinear.OperatorRegistry, as well as a list of parameters and subexpressions in the model.

ReverseAD

Nonlinear.ReverseAD is a submodule for computing derivatives of a nonlinear optimization problem using sparse reverse-mode automatic differentiation (AD).

This section does not attempt to explain how sparse reverse-mode AD works, but instead explains why MOI contains its own implementation, and highlights notable differences from similar packages.

Warning

Don't use the API in ReverseAD to compute derivatives. Instead, create a Nonlinear.Evaluator object with Nonlinear.SparseReverseMode as the backend, and then query the MOI API methods.

Design goals

The JuliaDiff organization maintains a list of packages for doing AD in Julia. At last count, there were at least ten packages——not including ReverseAD——for reverse-mode AD in Julia. ReverseAD exists because it has a different set of design goals.

  • Goal: handle scale and sparsity. The types of nonlinear optimization problems that MOI represents can be large scale (10^5 or more functions across 10^5 or more variables) with very sparse derivatives. The ability to compute a sparse Hessian matrix is essential. To the best of our knowledge, ReverseAD is the only reverse-mode AD system in Julia that handles sparsity by default.
  • Goal: limit the scope to improve robustness. Most other AD packages accept arbitrary Julia functions as input and then trace an expression graph using operator overloading. This means they must deal (or detect and ignore) with control flow, I/O, and other vagaries of Julia. In contrast, ReverseAD only accepts functions in the form of Nonlinear.Expression, which greatly limits the range of syntax that it must deal with. By reducing the scope of what we accept as input to functions relevant for mathematical optimization, we can provide a simpler implementation with various performance optimizations.
  • Goal: provide outputs which match what solvers expect. Other AD packages focus on differentiating individual Julia functions. In contrast, ReverseAD has a very specific use-case: to generate outputs needed by the MOI nonlinear API. This means it needs to efficiently compute sparse Hessians, and it needs subexpression handling to avoid recomputing subexpressions that are shared between functions.

History

ReverseAD started life as ReverseDiffSparse.jl, development of which began in early 2014(!). This was well before the other AD packages started development. Because we had a well-tested, working AD in JuMP, there was less motivation to contribute to and explore other AD packages. The lack of historical interaction also meant that other packages were not optimized for the types of problems that JuMP is built for (that is, large-scale sparse problems). When we first created MathOptInterface, we kept the AD in JuMP to simplify the transition, and post-poned the development of a first-class nonlinear interface in MathOptInterface.

Prior to the introduction of Nonlinear, JuMP's nonlinear implementation was a confusing mix of functions and types spread across the code base and in the private _Derivatives submodule. This made it hard to swap the AD system for another. The main motivation for refactoring JuMP to create the Nonlinear submodule in MathOptInterface was to abstract the interface between JuMP and the AD system, allowing us to swap-in and test new AD systems in the future.

diff --git a/previews/PR2274/submodules/Nonlinear/reference/index.html b/previews/PR2274/submodules/Nonlinear/reference/index.html new file mode 100644 index 0000000000..613b938224 --- /dev/null +++ b/previews/PR2274/submodules/Nonlinear/reference/index.html @@ -0,0 +1,147 @@ + +API Reference · MathOptInterface

Nonlinear Modeling

More information can be found in the Nonlinear section of the manual.

MathOptInterface.NonlinearModule
Nonlinear
Warning

The Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.

source
MathOptInterface.Nonlinear.ModelType
Model()

The core datastructure for representing a nonlinear optimization problem.

It has the following fields:

  • objective::Union{Nothing,Expression} : holds the nonlinear objective function, if one exists, otherwise nothing.
  • expressions::Vector{Expression} : a vector of expressions in the model.
  • constraints::OrderedDict{ConstraintIndex,Constraint} : a map from ConstraintIndex to the corresponding Constraint. An OrderedDict is used instead of a Vector to support constraint deletion.
  • parameters::Vector{Float64} : holds the current values of the parameters.
  • operators::OperatorRegistry : stores the operators used in the model.
source

Expressions

Parameters

MathOptInterface.Nonlinear.add_parameterFunction
add_parameter(model::Model, value::Float64)::ParameterIndex

Add a new parameter to model with the default value value. Returns a ParameterIndex that can be interpolated into other input expressions and used to modify the value of the parameter.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+p = add_parameter(model, 1.2)
+c = add_constraint(model, :($x^2 - $p), MOI.LessThan(0.0))
source

Objectives

MathOptInterface.Nonlinear.set_objectiveFunction
set_objective(model::Model, obj)::Nothing

Parse obj into a Expression and set as the objective function of model.

obj must be a type that is supported by parse_expression.

To remove the objective, pass nothing.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+set_objective(model, :($x^2 + 1))
+set_objective(model, x)
+set_objective(model, nothing)
source

Constraints

MathOptInterface.Nonlinear.add_constraintFunction
add_constraint(
+    model::Model,
+    func,
+    set::Union{
+        MOI.GreaterThan{Float64},
+        MOI.LessThan{Float64},
+        MOI.Interval{Float64},
+        MOI.EqualTo{Float64},
+    },
+)

Parse func and set into a Constraint and add to model. Returns a ConstraintIndex that can be used to delete the constraint or query solution information.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+c = add_constraint(model, :($x^2), MOI.LessThan(1.0))
source
MathOptInterface.Nonlinear.deleteFunction
delete(model::Model, c::ConstraintIndex)::Nothing

Delete the constraint index c from model.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+c = add_constraint(model, :($x^2), MOI.LessThan(1.0))
+delete(model, c)
source

User-defined operators

MathOptInterface.Nonlinear.DEFAULT_UNIVARIATE_OPERATORSConstant
DEFAULT_UNIVARIATE_OPERATORS

The list of univariate operators that are supported by default.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS
+72-element Vector{Symbol}:
+ :+
+ :-
+ :abs
+ :sqrt
+ :cbrt
+ :abs2
+ :inv
+ :log
+ :log10
+ :log2
+ ⋮
+ :airybi
+ :airyaiprime
+ :airybiprime
+ :besselj0
+ :besselj1
+ :bessely0
+ :bessely1
+ :erfcx
+ :dawson
source
MathOptInterface.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORSConstant
DEFAULT_MULTIVARIATE_OPERATORS

The list of multivariate operators that are supported by default.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS
+9-element Vector{Symbol}:
+ :+
+ :-
+ :*
+ :^
+ :/
+ :ifelse
+ :atan
+ :min
+ :max
source
MathOptInterface.Nonlinear.register_operatorFunction
register_operator(
+    model::Model,
+    op::Symbol,
+    nargs::Int,
+    f::Function,
+    [∇f::Function],
+    [∇²f::Function],
+)

Register the user-defined operator op with nargs input arguments in model.

Univariate functions

  • f(x::T)::T must be a function that takes a single input argument x and returns the function evaluated at x. If ∇f and ∇²f are not provided, f must support any Real input type T.
  • ∇f(x::T)::T is a function that takes a single input argument x and returns the first derivative of f with respect to x. If ∇²f is not provided, ∇f must support any Real input type T.
  • ∇²f(x::T)::T is a function that takes a single input argument x and returns the second derivative of f with respect to x.

Multivariate functions

  • f(x::T...)::T must be a function that takes a nargs input arguments x and returns the function evaluated at x. If ∇f and ∇²f are not provided, f must support any Real input type T.
  • ∇f(g::AbstractVector{T}, x::T...)::T is a function that takes a cache vector g of length length(x), and fills each element g[i] with the partial derivative of f with respect to x[i].
  • ∇²f(H::AbstractMatrix, x::T...)::T is a function that takes a matrix H and fills the lower-triangular components H[i, j] with the Hessian of f with respect to x[i] and x[j] for i >= j.

Notes for multivariate Hessians

  • H has size(H) == (length(x), length(x)), but you must not access elements H[i, j] for i > j.
  • H is dense, but you do not need to fill structural zeros.
source
MathOptInterface.Nonlinear.eval_multivariate_gradientFunction
eval_multivariate_gradient(
+    registry::OperatorRegistry,
+    op::Symbol,
+    g::AbstractVector{T},
+    x::AbstractVector{T},
+) where {T}

Evaluate the gradient of operator g .= ∇op(x), where op is a multivariate function in registry.

source
MathOptInterface.Nonlinear.eval_multivariate_hessianFunction
eval_multivariate_hessian(
+    registry::OperatorRegistry,
+    op::Symbol,
+    H::AbstractMatrix,
+    x::AbstractVector{T},
+) where {T}

Evaluate the Hessian of operator ∇²op(x), where op is a multivariate function in registry.

The Hessian is stored in the lower-triangular part of the matrix H.

Note

Implementations of the Hessian operators will not fill structural zeros. Therefore, before calling this function you should pre-populate the matrix H with 0.

source

Automatic-differentiation backends

MathOptInterface.Nonlinear.EvaluatorType
Evaluator(
+    model::Model,
+    backend::AbstractAutomaticDifferentiation,
+    ordered_variables::Vector{MOI.VariableIndex},
+)

Create Evaluator, a subtype of MOI.AbstractNLPEvaluator, from Model.

source
MathOptInterface.Nonlinear.SparseReverseModeType
SparseReverseMode() <: AbstractAutomaticDifferentiation

An implementation of AbstractAutomaticDifferentiation that uses sparse reverse-mode automatic differentiation to compute derivatives. Supports all features in the MOI nonlinear interface.

source

Data-structure

MathOptInterface.Nonlinear.NodeType
struct Node
+    type::NodeType
+    index::Int
+    parent::Int
+end

A single node in a nonlinear expression tree. Used by Expression.

See the MathOptInterface documentation for information on how the nodes and values form an expression tree.

source
MathOptInterface.Nonlinear.NodeTypeType
NodeType

An enum describing the possible node types. Each Node has a .index field, which should be interpreted as follows:

  • NODE_CALL_MULTIVARIATE: the index into operators.multivariate_operators
  • NODE_CALL_UNIVARIATE: the index into operators.univariate_operators
  • NODE_LOGIC: the index into operators.logic_operators
  • NODE_COMPARISON: the index into operators.comparison_operators
  • NODE_MOI_VARIABLE: the value of MOI.VariableIndex(index) in the user's space of the model.
  • NODE_VARIABLE: the 1-based index of the internal vector
  • NODE_VALUE: the index into the .values field of Expression
  • NODE_PARAMETER: the index into data.parameters
  • NODE_SUBEXPRESSION: the index into data.expressions
source
MathOptInterface.Nonlinear.ExpressionType
struct Expression
+    nodes::Vector{Node}
+    values::Vector{Float64}
+end

The core type that represents a nonlinear expression. See the MathOptInterface documentation for information on how the nodes and values form an expression tree.

source
MathOptInterface.Nonlinear.ConstraintType
struct Constraint
+    expression::Expression
+    set::Union{
+        MOI.LessThan{Float64},
+        MOI.GreaterThan{Float64},
+        MOI.EqualTo{Float64},
+        MOI.Interval{Float64},
+    }
+end

A type to hold information relating to the nonlinear constraint f(x) in S, where f(x) is defined by .expression, and S is .set.

source
MathOptInterface.Nonlinear.adjacency_matrixFunction
adjacency_matrix(nodes::Vector{Node})

Compute the sparse adjacency matrix describing the parent-child relationships in nodes.

The element (i, j) is true if there is an edge from node[j] to node[i]. Since we get a column-oriented matrix, this gives us a fast way to look up the edges leaving any node (i.e., the children).

source
MathOptInterface.Nonlinear.parse_expressionFunction
parse_expression(data::Model, input)::Expression

Parse input into a Expression.

source
parse_expression(
+    data::Model,
+    expr::Expression,
+    input::Any,
+    parent_index::Int,
+)::Expression

Parse input into a Expression, and add it to expr as a child of expr.nodes[parent_index]. Existing subexpressions and parameters are stored in data.

You can extend parsing support to new types of objects by overloading this method with a different type on input::Any.

source
MathOptInterface.Nonlinear.convert_to_exprFunction
convert_to_expr(data::Model, expr::Expression)

Convert the Expression expr into a Julia Expr.

source
convert_to_expr(
+    evaluator::Evaluator,
+    expr::Expression;
+    moi_output_format::Bool,
+)

Convert the Expression expr into a Julia Expr.

If moi_output_format = true:

  • subexpressions will be converted to Julia Expr and substituted into the output expression.
  • the current value of each parameter will be interpolated into the expression
  • variables will be represented in the form x[MOI.VariableIndex(i)]

If moi_output_format = false:

Warning

To use moi_output_format = true, you must have first called MOI.initialize with :ExprGraph as a requested feature.

source
MathOptInterface.Nonlinear.ordinal_indexFunction
ordinal_index(evaluator::Evaluator, c::ConstraintIndex)::Int

Return the 1-indexed value of the constraint index c in evaluator.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+c1 = add_constraint(model, :($x^2), MOI.LessThan(1.0))
+c2 = add_constraint(model, :($x^2), MOI.LessThan(1.0))
+evaluator = Evaluator(model)
+MOI.initialize(evaluator, Symbol[])
+ordinal_index(evaluator, c2)  # Returns 2
+delete(model, c1)
+evaluator = Evaluator(model)
+MOI.initialize(evaluator, Symbol[])
+ordinal_index(model, c2)  # Returns 1
source
diff --git a/previews/PR2274/submodules/Test/overview/index.html b/previews/PR2274/submodules/Test/overview/index.html new file mode 100644 index 0000000000..c8c05c1be7 --- /dev/null +++ b/previews/PR2274/submodules/Test/overview/index.html @@ -0,0 +1,166 @@ + +Overview · MathOptInterface

The Test submodule

The Test submodule provides tools to help solvers implement unit tests in order to ensure they implement the MathOptInterface API correctly, and to check for solver-correctness.

We use a centralized repository of tests, so that if we find a bug in one solver, instead of adding a test to that particular repository, we add it here so that all solvers can benefit.

How to test a solver

The skeleton below can be used for the wrapper test file of a solver named FooBar.

# ============================ /test/MOI_wrapper.jl ============================
+module TestFooBar
+
+import FooBar
+using Test
+
+import MathOptInterface as MOI
+
+const OPTIMIZER = MOI.instantiate(
+    MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true),
+)
+
+const BRIDGED = MOI.instantiate(
+    MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true),
+    with_bridge_type = Float64,
+)
+
+# See the docstring of MOI.Test.Config for other arguments.
+const CONFIG = MOI.Test.Config(
+    # Modify tolerances as necessary.
+    atol = 1e-6,
+    rtol = 1e-6,
+    # Use MOI.LOCALLY_SOLVED for local solvers.
+    optimal_status = MOI.OPTIMAL,
+    # Pass attributes or MOI functions to `exclude` to skip tests that
+    # rely on this functionality.
+    exclude = Any[MOI.VariableName, MOI.delete],
+)
+
+"""
+    runtests()
+
+This function runs all functions in the this Module starting with `test_`.
+"""
+function runtests()
+    for name in names(@__MODULE__; all = true)
+        if startswith("$(name)", "test_")
+            @testset "$(name)" begin
+                getfield(@__MODULE__, name)()
+            end
+        end
+    end
+end
+
+"""
+    test_runtests()
+
+This function runs all the tests in MathOptInterface.Test.
+
+Pass arguments to `exclude` to skip tests for functionality that is not
+implemented or that your solver doesn't support.
+"""
+function test_runtests()
+    MOI.Test.runtests(
+        BRIDGED,
+        CONFIG,
+        exclude = [
+            "test_attribute_NumberOfThreads",
+            "test_quadratic_",
+        ],
+        # This argument is useful to prevent tests from failing on future
+        # releases of MOI that add new tests. Don't let this number get too far
+        # behind the current MOI release though. You should periodically check
+        # for new tests to fix bugs and implement new features.
+        exclude_tests_after = v"0.10.5",
+    )
+    return
+end
+
+"""
+    test_SolverName()
+
+You can also write new tests for solver-specific functionality. Write each new
+test as a function with a name beginning with `test_`.
+"""
+function test_SolverName()
+    @test MOI.get(FooBar.Optimizer(), MOI.SolverName()) == "FooBar"
+    return
+end
+
+end # module TestFooBar
+
+# This line at tne end of the file runs all the tests!
+TestFooBar.runtests()

Then modify your runtests.jl file to include the MOI_wrapper.jl file:

# ============================ /test/runtests.jl ============================
+
+using Test
+
+@testset "MOI" begin
+    include("test/MOI_wrapper.jl")
+end
Info

The optimizer BRIDGED constructed with instantiate automatically bridges constraints that are not supported by OPTIMIZER using the bridges listed in Bridges. It is recommended for an implementation of MOI to only support constraints that are natively supported by the solver and let bridges transform the constraint to the appropriate form. For this reason it is expected that tests may not pass if OPTIMIZER is used instead of BRIDGED.

How to debug a failing test

When writing a solver, it's likely that you will initially fail many tests. Some failures will be bugs, but other failures you may choose to exclude.

There are two ways to exclude tests:

  • Exclude tests whose names contain a string using:

    MOI.Test.runtests(
    +    model,
    +    config;
    +    exclude = String["test_to_exclude", "test_conic_"],
    +)

    This will exclude tests whose name contains either of the two strings provided.

  • Exclude tests which rely on specific functionality using:

    MOI.Test.Config(exclude = Any[MOI.VariableName, MOI.optimize!])

    This will exclude tests which use the MOI.VariableName attribute, or which call MOI.optimize!.

Each test that fails can be independently called as:

model = FooBar.Optimizer()
+config = MOI.Test.Config()
+MOI.empty!(model)
+MOI.Test.test_category_name_that_failed(model, config)

You can look-up the source code of the test that failed by searching for it in the src/Test/test_category.jl file.

Tip

Each test function also has a docstring that explains what the test is for. Use ? MOI.Test.test_category_name_that_failed from the REPL to read it.

Periodically, you should re-run excluded tests to see if they now pass. The easiest way to do this is to swap the exclude keyword argument of runtests to include. For example:

MOI.Test.runtests(
+    model,
+    config;
+    exclude = String["test_to_exclude", "test_conic_"],
+)

becomes

MOI.Test.runtests(
+    model,
+    config;
+    include = String["test_to_exclude", "test_conic_"],
+)

How to add a test

To detect bugs in solvers, we add new tests to MOI.Test.

As an example, ECOS errored calling optimize! twice in a row. (See ECOS.jl PR #72.) We could add a test to ECOS.jl, but that would only stop us from re-introducing the bug to ECOS.jl in the future, but it would not catch other solvers in the ecosystem with the same bug. Instead, if we add a test to MOI.Test, then all solvers will also check that they handle a double optimize call.

For this test, we care about correctness, rather than performance. therefore, we don't expect solvers to efficiently decide that they have already solved the problem, only that calling optimize! twice doesn't throw an error or give the wrong answer.

Step 1

Install the MathOptInterface julia package in dev mode:

julia> ]
+(@v1.6) pkg> dev MathOptInterface

Step 2

From here on, proceed with making the following changes in the ~/.julia/dev/MathOptInterface folder (or equivalent dev path on your machine).

Step 3

Since the double-optimize error involves solving an optimization problem, add a new test to src/Test/test_solve.jl:

"""
+    test_unit_optimize!_twice(model::MOI.ModelLike, config::Config)
+
+Test that calling `MOI.optimize!` twice does not error.
+
+This problem was first detected in ECOS.jl PR#72:
+https://github.com/jump-dev/ECOS.jl/pull/72
+"""
+function test_unit_optimize!_twice(
+    model::MOI.ModelLike,
+    config::Config{T},
+) where {T}
+    # Use the `@requires` macro to check conditions that the test function
+    # requires to run. Models failing this `@requires` check will silently skip
+    # the test.
+    @requires MOI.supports_constraint(
+        model,
+        MOI.VariableIndex,
+        MOI.GreaterThan{Float64},
+    )
+    @requires _supports(config, MOI.optimize!)
+    # If needed, you can test that the model is empty at the start of the test.
+    # You can assume that this will be the case for tests run via `runtests`.
+    # User's calling tests individually need to call `MOI.empty!` themselves.
+    @test MOI.is_empty(model)
+    # Create a simple model. Try to make this as simple as possible so that the
+    # majority of solvers can run the test.
+    x = MOI.add_variable(model)
+    MOI.add_constraint(model, x, MOI.GreaterThan(one(T)))
+    MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
+    MOI.set(
+        model,
+        MOI.ObjectiveFunction{MOI.VariableIndex}(),
+        x,
+    )
+    # The main component of the test: does calling `optimize!` twice error?
+    MOI.optimize!(model)
+    MOI.optimize!(model)
+    # Check we have a solution.
+    @test MOI.get(model, MOI.TerminationStatus()) == MOI.OPTIMAL
+    # There is a three-argument version of `Base.isapprox` for checking
+    # approximate equality based on the tolerances defined in `config`:
+    @test isapprox(MOI.get(model, MOI.VariablePrimal(), x), one(T), config)
+    # For code-style, these tests should always `return` `nothing`.
+    return
+end
Info

Make sure the function is agnostic to the number type T; don't assume it is a Float64 capable solver.

We also need to write a test for the test. Place this function immediately below the test you just wrote in the same file:

function setup_test(
+    ::typeof(test_unit_optimize!_twice),
+    model::MOI.Utilities.MockOptimizer,
+    ::Config,
+)
+    MOI.Utilities.set_mock_optimize!(
+        model,
+        (mock::MOI.Utilities.MockOptimizer) -> MOIU.mock_optimize!(
+            mock,
+            MOI.OPTIMAL,
+            (MOI.FEASIBLE_POINT, [1.0]),
+        ),
+    )
+    return
+end

Finally, you also need to implement Test.version_added. If we added this test when the latest released version of MOI was v0.10.5, define:

version_added(::typeof(test_unit_optimize!_twice)) = v"0.10.6"

Step 6

Commit the changes to git from ~/.julia/dev/MathOptInterface and submit the PR for review.

Tip

If you need help writing a test, open an issue on GitHub, or ask the Developer Chatroom.

diff --git a/previews/PR2274/submodules/Test/reference/index.html b/previews/PR2274/submodules/Test/reference/index.html new file mode 100644 index 0000000000..62af007f2d --- /dev/null +++ b/previews/PR2274/submodules/Test/reference/index.html @@ -0,0 +1,50 @@ + +API Reference · MathOptInterface

The Test submodule

Functions to help test implementations of MOI. See The Test submodule for more details.

MathOptInterface.Test.ConfigType
Config(
+    ::Type{T} = Float64;
+    atol::Real = Base.rtoldefault(T),
+    rtol::Real = Base.rtoldefault(T),
+    optimal_status::MOI.TerminationStatusCode = MOI.OPTIMAL,
+    infeasible_status::MOI.TerminationStatusCode = MOI.INFEASIBLE,
+    exclude::Vector{Any} = Any[],
+) where {T}

Return an object that is used to configure various tests.

Configuration arguments

  • atol::Real = Base.rtoldefault(T): Control the absolute tolerance used when comparing solutions.
  • rtol::Real = Base.rtoldefault(T): Control the relative tolerance used when comparing solutions.
  • optimal_status = MOI.OPTIMAL: Set to MOI.LOCALLY_SOLVED if the solver cannot prove global optimality.
  • infeasible_status = MOI.INFEASIBLE: Set to MOI.LOCALLY_INFEASIBLE if the solver cannot prove global infeasibility.
  • exclude = Vector{Any}: Pass attributes or functions to exclude to skip parts of tests that require certain functionality. Common arguments include:
    • MOI.delete to skip deletion-related tests
    • MOI.optimize! to skip optimize-related tests
    • MOI.ConstraintDual to skip dual-related tests
    • MOI.VariableName to skip setting variable names
    • MOI.ConstraintName to skip setting constraint names

Examples

For a nonlinear solver that finds local optima and does not support finding dual variables or constraint names:

Config(
+    Float64;
+    optimal_status = MOI.LOCALLY_SOLVED,
+    exclude = Any[
+        MOI.ConstraintDual,
+        MOI.VariableName,
+        MOI.ConstraintName,
+        MOI.delete,
+    ],
+)
source
MathOptInterface.Test.runtestsFunction
runtests(
+    model::MOI.ModelLike,
+    config::Config;
+    include::Vector{Union{String,Regex}} = String[],
+    exclude::Vector{Union{String,Regex}} = String[],
+    warn_unsupported::Bool = false,
+    exclude_tests_after::VersionNumber = v"999.0.0",
+)

Run all tests in MathOptInterface.Test on model.

Configuration arguments

  • config is a Test.Config object that can be used to modify the behavior of tests.
  • If include is not empty, only run tests if an element from include occursin the name of the test.
  • If exclude is not empty, skip tests if an element from exclude occursin the name of the test.
  • exclude takes priority over include.
  • If warn_unsupported is false, runtests will silently skip tests that fail with a MOI.NotAllowedError, MOI.UnsupportedError, or RequirementUnmet error. (The latter is thrown when an @requires statement returns false.) When warn_unsupported is true, a warning will be printed. For most cases the default behavior, false, is what you want, since these tests likely test functionality that is not supported by model. However, it can be useful to run warn_unsupported = true to check you are not skipping tests due to a missing supports_constraint method or equivalent.
  • exclude_tests_after is a version number that excludes any tests to MOI added after that version number. This is useful for solvers who can declare a fixed set of tests, and not cause their tests to break if a new patch of MOI is released with a new test.

See also: setup_test.

Example

config = MathOptInterface.Test.Config()
+MathOptInterface.Test.runtests(
+    model,
+    config;
+    include = ["test_linear_", r"^test_model_Name$"],
+    exclude = ["VariablePrimalStart"],
+    warn_unsupported = true,
+    exclude_tests_after = v"0.10.5",
+)
source
MathOptInterface.Test.setup_testFunction
setup_test(::typeof(f), model::MOI.ModelLike, config::Config)

Overload this method to modify model before running the test function f on model with config. You can also modify the fields in config (e.g., to loosen the default tolerances).

This function should either return nothing, or return a function which, when called with zero arguments, undoes the setup to return the model to its previous state. You do not need to undo any modifications to config.

This function is most useful when writing new tests of the tests for MOI, but it can also be used to set test-specific tolerances, etc.

See also: runtests

Example

function MOI.Test.setup_test(
+    ::typeof(MOI.Test.test_linear_VariablePrimalStart_partial),
+    mock::MOIU.MockOptimizer,
+    ::MOI.Test.Config,
+)
+    MOIU.set_mock_optimize!(
+        mock,
+        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 0.0]),
+    )
+    mock.eval_variable_constraint_dual = false
+
+    function reset_function()
+        mock.eval_variable_constraint_dual = true
+        return
+    end
+    return reset_function
+end
source
MathOptInterface.Test.version_addedFunction
version_added(::typeof(function_name))

Returns the version of MOI in which the test function_name was added.

This method should be implemented for all new tests.

See the exclude_tests_after keyword of runtests for more details.

source
MathOptInterface.Test.@requiresMacro
@requires(x)

Check that the condition x is true. Otherwise, throw an RequirementUnmet error to indicate that the model does not support something required by the test function.

Examples

@requires MOI.supports(model, MOI.Silent())
+@test MOI.get(model, MOI.Silent())
source
diff --git a/previews/PR2274/submodules/Utilities/overview/index.html b/previews/PR2274/submodules/Utilities/overview/index.html new file mode 100644 index 0000000000..b247a70f84 --- /dev/null +++ b/previews/PR2274/submodules/Utilities/overview/index.html @@ -0,0 +1,250 @@ + +Overview · MathOptInterface

The Utilities submodule

The Utilities submodule provides a variety of functions and datastructures for managing MOI.ModelLike objects.

Utilities.Model

Utilities.Model provides an implementation of a ModelLike that efficiently supports all functions and sets defined within MOI. However, given the extensibility of MOI, this might not cover all use cases.

Create a model as follows:

julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}

Utilities.UniversalFallback

Utilities.UniversalFallback is a layer that sits on top of any ModelLike and provides non-specialized (slower) fallbacks for constraints and attributes that the underlying ModelLike does not support.

For example, Utilities.Model doesn't support some variable attributes like VariablePrimalStart, so JuMP uses a combination of Universal fallback and Utilities.Model as a generic problem cache:

julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
+MOIU.UniversalFallback{MOIU.Model{Float64}}
+fallback for MOIU.Model{Float64}
Warning

Adding a UniversalFallback means that your model will now support all constraints, even if the inner-model does not. This can lead to unexpected behavior.

Utilities.@model

For advanced use cases that need efficient support for functions and sets defined outside of MOI (but still known at compile time), we provide the Utilities.@model macro.

The @model macro takes a name (for a new type, which must not exist yet), eight tuples specifying the types of constraints that are supported, and then a Bool indicating the type is a subtype of MOI.AbstractOptimizer (if true) or MOI.ModelLike (if false).

The eight tuples are in the following order:

  1. Un-typed scalar sets, for example, Integer
  2. Typed scalar sets, for example, LessThan
  3. Un-typed vector sets, for example, Nonnegatives
  4. Typed vector sets, for example, PowerCone
  5. Un-typed scalar functions, for example, VariableIndex
  6. Typed scalar functions, for example, ScalarAffineFunction
  7. Un-typed vector functions, for example, VectorOfVariables
  8. Typed vector functions, for example, VectorAffineFunction

The tuples can contain more than one element. Typed-sets must be specified without their type parameter, for example, MOI.LessThan, not MOI.LessThan{Float64}.

Here is an example:

julia> MOI.Utilities.@model(
+           MyNewModel,
+           (MOI.Integer,),                  # Un-typed scalar sets
+           (MOI.GreaterThan,),              # Typed scalar sets
+           (MOI.Nonnegatives,),             # Un-typed vector sets
+           (MOI.PowerCone,),                # Typed vector sets
+           (MOI.VariableIndex,),            # Un-typed scalar functions
+           (MOI.ScalarAffineFunction,),     # Typed scalar functions
+           (MOI.VectorOfVariables,),        # Un-typed vector functions
+           (MOI.VectorAffineFunction,),     # Typed vector functions
+           true,                            # <:MOI.AbstractOptimizer?
+       )
+MathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, MyNewModelFunctionConstraints{T}} where T
+
+julia> model = MyNewModel{Float64}()
+MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MyNewModelFunctionConstraints{Float64}}
Warning

MyNewModel supports every VariableIndex-in-Set constraint, as well as VariableIndex, ScalarAffineFunction, and ScalarQuadraticFunction objective functions. Implement MOI.supports as needed to forbid constraint and objective function combinations.

As another example, PATHSolver, which only supports VectorAffineFunction-in-Complements defines its optimizer as:

julia> MOI.Utilities.@model(
+           PathOptimizer,
+           (),  # Scalar sets
+           (),  # Typed scalar sets
+           (MOI.Complements,),  # Vector sets
+           (),  # Typed vector sets
+           (),  # Scalar functions
+           (),  # Typed scalar functions
+           (),  # Vector functions
+           (MOI.VectorAffineFunction,),  # Typed vector functions
+           true,  # is_optimizer
+       )
+MathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{T}, MathOptInterface.Complements}} where T

However, PathOptimizer does not support some VariableIndex-in-Set constraints, so we must explicitly define:

julia> function MOI.supports_constraint(
+           ::PathOptimizer,
+           ::Type{MOI.VariableIndex},
+           ::Type{Union{<:MOI.Semiinteger,MOI.Semicontinuous,MOI.ZeroOne,MOI.Integer}}
+       )
+           return false
+       end

Finally, PATH doesn't support an objective function, so we need to add:

julia> MOI.supports(::PathOptimizer, ::MOI.ObjectiveFunction) = false
Warning

This macro creates a new type, so it must be called from the top-level of a module, for example, it cannot be called from inside a function.

Utilities.CachingOptimizer

A [Utilities.CachingOptimizer] is an MOI layer that abstracts the difference between solvers that support incremental modification (for example, they support adding variables one-by-one), and solvers that require the entire problem in a single API call (for example, they only accept the A, b and c matrices of a linear program).

It has two parts:

  1. A cache, where the model can be built and modified incrementally
  2. An optimizer, which is used to solve the problem
julia> model = MOI.Utilities.CachingOptimizer(
+           MOI.Utilities.Model{Float64}(),
+           PathOptimizer{Float64}(),
+       )
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state EMPTY_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}

A Utilities.CachingOptimizer may be in one of three possible states:

  • NO_OPTIMIZER: The CachingOptimizer does not have any optimizer.
  • EMPTY_OPTIMIZER: The CachingOptimizer has an empty optimizer, and it is not synchronized with the cached model. Modifications are forwarded to the cache, but not to the optimizer.
  • ATTACHED_OPTIMIZER: The CachingOptimizer has an optimizer, and it is synchronized with the cached model. Modifications are forwarded to the optimizer. If the optimizer does not support modifications, and error will be thrown.

Use Utilities.attach_optimizer to go from EMPTY_OPTIMIZER to ATTACHED_OPTIMIZER:

julia> MOI.Utilities.attach_optimizer(model)
+
+julia> model
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state ATTACHED_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}
Info

You must be in ATTACHED_OPTIMIZER to use optimize!.

Use Utilities.reset_optimizer to go from ATTACHED_OPTIMIZER to EMPTY_OPTIMIZER:

julia> MOI.Utilities.reset_optimizer(model)
+
+julia> model
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state EMPTY_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}
Info

Calling MOI.empty!(model) also resets the state to EMPTY_OPTIMIZER. So after emptying a model, the modification will only be applied to the cache.

Use Utilities.drop_optimizer to go from any state to NO_OPTIMIZER:

julia> MOI.Utilities.drop_optimizer(model)
+
+julia> model
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state NO_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer nothing

Pass an empty optimizer to Utilities.reset_optimizer to go from NO_OPTIMIZER to EMPTY_OPTIMIZER:

julia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}())
+
+julia> model
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state EMPTY_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}

Deciding when to attach and reset the optimizer is tedious, and you will often write code like this:

try
+    # modification
+catch
+    MOI.Utilities.reset_optimizer(model)
+    # Re-try modification
+end

To make this easier, Utilities.CachingOptimizer has two modes of operation:

  • AUTOMATIC: The CachingOptimizer changes its state when necessary. Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to EMPTY_OPTIMIZER mode.
  • MANUAL: The user must change the state of the CachingOptimizer. Attempting to perform an operation in the incorrect state results in an error.

By default, AUTOMATIC mode is chosen. However, you can create a CachingOptimizer in MANUAL mode as follows:

julia> model = MOI.Utilities.CachingOptimizer(
+           MOI.Utilities.Model{Float64}(),
+           MOI.Utilities.MANUAL,
+       )
+MOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}}
+in state NO_OPTIMIZER
+in mode MANUAL
+with model cache MOIU.Model{Float64}
+with optimizer nothing
+
+julia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}())
+
+julia> model
+MOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}}
+in state EMPTY_OPTIMIZER
+in mode MANUAL
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}

Printing

Use print to print the formulation of the model.

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.set(model, MOI.VariableName(), x, "x_var")
+
+julia> MOI.add_constraint(model, x, MOI.ZeroOne())
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)
+
+julia> MOI.set(model, MOI.ObjectiveFunction{typeof(x)}(), x)
+
+julia> MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
+
+julia> print(model)
+Maximize VariableIndex:
+ x_var
+
+Subject to:
+
+VariableIndex-in-ZeroOne
+ x_var ∈ {0, 1}

Use Utilities.latex_formulation to display the model in LaTeX form:

julia> MOI.Utilities.latex_formulation(model)
+$$ \begin{aligned}
+\max\quad & x\_var \\
+\text{Subject to}\\
+ & \text{VariableIndex-in-ZeroOne} \\
+ & x\_var \in \{0, 1\} \\
+\end{aligned} $$
Tip

In IJulia, calling print or ending a cell with Utilities.latex_formulation will render the model in LaTeX.

Utilities.PenaltyRelaxation

Pass Utilities.PenaltyRelaxation to modify to relax the problem by adding penalized slack variables to the constraints. This is helpful when debugging sources of infeasible models.

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> MOI.set(model, MOI.VariableName(), x, "x")
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 2.0)));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 2.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 x - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> map[c]
+0.0 + 1.0 MOI.VariableIndex(2)

You can also modify a single constraint using Utilities.ScalarPenaltyRelaxation:

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> MOI.set(model, MOI.VariableName(), x, "x")
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 2.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 x - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> f
+0.0 + 1.0 MOI.VariableIndex(2)

Utilities.MatrixOfConstraints

The constraints of Utilities.Model are stored as a vector of tuples of function and set in a Utilities.VectorOfConstraints. Other representations can be used by parameterizing the type Utilities.GenericModel (resp. Utilities.GenericOptimizer). For instance, if all non-VariableIndex constraints are affine, the coefficients of all the constraints can be stored in a single sparse matrix using Utilities.MatrixOfConstraints. The constraints storage can even be customized up to a point where it exactly matches the storage of the solver of interest, in which case copy_to can be implemented for the solver by calling copy_to to this custom model.

For instance, Clp defines the following model:

MOI.Utilities.@product_of_scalar_sets(LP, MOI.EqualTo{T}, MOI.LessThan{T}, MOI.GreaterThan{T})
+const Model = MOI.Utilities.GenericModel{
+    Float64,
+    MOI.Utilities.MatrixOfConstraints{
+        Float64,
+        MOI.Utilities.MutableSparseMatrixCSC{Float64,Cint,MOI.Utilities.ZeroBasedIndexing},
+        MOI.Utilities.Hyperrectangle{Float64},
+        LP{Float64},
+    },
+}

The copy_to operation can now be implemented as follows:

function _copy_to(dest::Optimizer, src::Model)
+    @assert MOI.is_empty(dest)
+    A = src.constraints.coefficients
+    row_bounds = src.constraints.constants
+    Clp_loadProblem(
+        dest,
+        A.n,
+        A.m,
+        A.colptr,
+        A.rowval,
+        A.nzval,
+        src.lower_bound,
+        src.upper_bound,
+        # (...) objective vector (omitted),
+        row_bounds.lower,
+        row_bounds.upper,
+    )
+    # Set objective sense and constant (omitted)
+    return
+end
+
+function MOI.copy_to(dest::Optimizer, src::Model)
+    _copy_to(dest, src)
+    return MOI.Utilities.identity_index_map(src)
+end
+
+function MOI.copy_to(
+    dest::Optimizer,
+    src::MOI.Utilities.UniversalFallback{Model},
+)
+    # Copy attributes from `src` to `dest` and error in case any unsupported
+    # constraints or attributes are set in `UniversalFallback`.
+    return MOI.copy_to(dest, src.model)
+end
+
+function MOI.copy_to(
+    dest::Optimizer,
+    src::MOI.ModelLike,
+)
+    model = Model()
+    index_map = MOI.copy_to(model, src)
+    _copy_to(dest, model)
+    return index_map
+end

ModelFilter

Utilities provides Utilities.ModelFilter as a useful tool to copy a subset of a model. For example, given an infeasible model, we can copy the irreducible infeasible subsystem (for models implementing ConstraintConflictStatus) as follows:

my_filter(::Any) = true
+function my_filter(ci::MOI.ConstraintIndex)
+    status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)
+    return status != MOI.NOT_IN_CONFLICT
+end
+filtered_src = MOI.Utilities.ModelFilter(my_filter, src)
+index_map = MOI.copy_to(dest, filtered_src)

Fallbacks

The value of some attributes can be inferred from the value of other attributes.

For example, the value of ObjectiveValue can be computed using ObjectiveFunction and VariablePrimal.

When a solver gives direct access to an attribute, it is better to return this value. However, if this is not the case, Utilities.get_fallback can be used instead. For example:

function MOI.get(model::Optimizer, attr::MOI.ObjectiveFunction)
+    return MOI.Utilities.get_fallback(model, attr)
+end

DoubleDicts

When writing MOI interfaces, we often need to handle situations in which we map ConstraintIndexs to different values. For example, to a string for ConstraintName.

One option is to use a dictionary like Dict{MOI.ConstraintIndex,String}. However, this incurs a performance cost because the key is not a concrete type.

The DoubleDicts submodule helps this situation by providing two types main types Utilities.DoubleDicts.DoubleDict and Utilities.DoubleDicts.IndexDoubleDict. These types act like normal dictionaries, but internally they use more efficient dictionaries specialized to the type of the function-set pair.

The most common usage of a DoubleDict is in the index_map returned by copy_to. Performance can be improved, by using a function barrier. That is, instead of code like:

index_map = MOI.copy_to(dest, src)
+for (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())
+    for ci in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())
+        dest_ci = index_map[ci]
+        # ...
+    end
+end

use instead:

function function_barrier(
+    dest,
+    src,
+    index_map::MOI.Utilities.DoubleDicts.IndexDoubleDictInner{F,S},
+) where {F,S}
+    for ci in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())
+        dest_ci = index_map[ci]
+        # ...
+    end
+    return
+end
+
+index_map = MOI.copy_to(dest, src)
+for (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())
+    function_barrier(dest, src, index_map[F, S])
+end
diff --git a/previews/PR2274/submodules/Utilities/reference/index.html b/previews/PR2274/submodules/Utilities/reference/index.html new file mode 100644 index 0000000000..b500ec8636 --- /dev/null +++ b/previews/PR2274/submodules/Utilities/reference/index.html @@ -0,0 +1,289 @@ + +API Reference · MathOptInterface

Utilities.Model

MathOptInterface.Utilities.ModelType

An implementation of ModelLike that supports all functions and sets defined in MOI. It is parameterized by the coefficient type.

Examples

model = Model{Float64}()
+x = add_variable(model)
source

Utilities.UniversalFallback

MathOptInterface.Utilities.UniversalFallbackType
UniversalFallback

The UniversalFallback can be applied on a MOI.ModelLike model to create the model UniversalFallback(model) supporting any constraint and attribute. This allows to have a specialized implementation in model for performance critical constraints and attributes while still supporting other attributes with a small performance penalty. Note that model is unaware of constraints and attributes stored by UniversalFallback so this is not appropriate if model is an optimizer (for this reason, MOI.optimize! has not been implemented). In that case, optimizer bridges should be used instead.

source

Utilities.@model

MathOptInterface.Utilities.@modelMacro
macro model(
+    model_name,
+    scalar_sets,
+    typed_scalar_sets,
+    vector_sets,
+    typed_vector_sets,
+    scalar_functions,
+    typed_scalar_functions,
+    vector_functions,
+    typed_vector_functions,
+    is_optimizer = false
+)

Creates a type model_name implementing the MOI model interface and containing scalar_sets scalar sets typed_scalar_sets typed scalar sets, vector_sets vector sets, typed_vector_sets typed vector sets, scalar_functions scalar functions, typed_scalar_functions typed scalar functions, vector_functions vector functions and typed_vector_functions typed vector functions. To give no set/function, write (), to give one set S, write (S,).

The function MOI.VariableIndex should not be given in scalar_functions. The model supports MOI.VariableIndex-in-S constraints where S is MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval, MOI.Integer, MOI.ZeroOne, MOI.Semicontinuous or MOI.Semiinteger. The sets supported with the MOI.VariableIndex cannot be controlled from the macro, use the UniversalFallback to support more sets.

This macro creates a model specialized for specific types of constraint, by defining specialized structures and methods. To create a model that, in addition to be optimized for specific constraints, also support arbitrary constraints and attributes, use UniversalFallback.

If is_optimizer = true, the resulting struct is a of GenericOptimizer, which is a subtype of MOI.AbstractOptimizer, otherwise, it is a GenericModel, which is a subtype of MOI.ModelLike.

Examples

The model describing an linear program would be:

@model(LPModel,                                                   # Name of model
+      (),                                                         # untyped scalar sets
+      (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval), #   typed scalar sets
+      (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives),            # untyped vector sets
+      (),                                                         #   typed vector sets
+      (),                                                         # untyped scalar functions
+      (MOI.ScalarAffineFunction,),                                #   typed scalar functions
+      (MOI.VectorOfVariables,),                                   # untyped vector functions
+      (MOI.VectorAffineFunction,),                                #   typed vector functions
+      false
+    )

Let MOI denote MathOptInterface, MOIU denote MOI.Utilities. The macro would create the following types with struct_of_constraint_code:

struct LPModelScalarConstraints{T, C1, C2, C3, C4} <: MOIU.StructOfConstraints
+    moi_equalto::C1
+    moi_greaterthan::C2
+    moi_lessthan::C3
+    moi_interval::C4
+end
+struct LPModelVectorConstraints{T, C1, C2, C3} <: MOIU.StructOfConstraints
+    moi_zeros::C1
+    moi_nonnegatives::C2
+    moi_nonpositives::C3
+end
+struct LPModelFunctionConstraints{T} <: MOIU.StructOfConstraints
+    moi_scalaraffinefunction::LPModelScalarConstraints{
+        T,
+        MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.EqualTo{T}},
+        MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.GreaterThan{T}},
+        MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.LessThan{T}},
+        MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.Interval{T}}
+    }
+    moi_vectorofvariables::LPModelVectorConstraints{
+        T,
+        MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Zeros},
+        MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Nonnegatives},
+        MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Nonpositives}
+    }
+    moi_vectoraffinefunction::LPModelVectorConstraints{
+        T,
+        MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Zeros},
+        MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Nonnegatives},
+        MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Nonpositives}
+    }
+end
+const LPModel{T} = MOIU.GenericModel{T,MOIU.ObjectiveContainer{T},MOIU.VariablesContainer{T},LPModelFunctionConstraints{T}}

The type LPModel implements the MathOptInterface API except methods specific to optimizers like optimize! or get with VariablePrimal.

source
MathOptInterface.Utilities.GenericModelType
mutable struct GenericModel{T,O,V,C} <: AbstractModelLike{T}

Implements a model supporting coefficients of type T and:

  • An objective function stored in .objective::O
  • Variables and VariableIndex constraints stored in .variable_bounds::V
  • F-in-S constraints (excluding VariableIndex constraints) stored in .constraints::C

All interactions should take place via the MOI interface, so the types O, V, and C should implement the API as needed for their functionality.

source
MathOptInterface.Utilities.GenericOptimizerType
mutable struct GenericOptimizer{T,O,V,C} <: AbstractOptimizer{T}

Implements a model supporting coefficients of type T and:

  • An objective function stored in .objective::O
  • Variables and VariableIndex constraints stored in .variable_bounds::V
  • F-in-S constraints (excluding VariableIndex constraints) stored in .constraints::C

All interactions should take place via the MOI interface, so the types O, V, and C should implement the API as needed for their functionality.

source

.objective

.variables

MathOptInterface.Utilities.VariablesContainerType
struct VariablesContainer{T} <: AbstractVectorBounds
+    set_mask::Vector{UInt16}
+    lower::Vector{T}
+    upper::Vector{T}
+end

A struct for storing variables and VariableIndex-related constraints. Used in MOI.Utilities.Model by default.

source
MathOptInterface.Utilities.FreeVariablesType
mutable struct FreeVariables <: MOI.ModelLike
+    n::Int64
+    FreeVariables() = new(0)
+end

A struct for storing free variables that can be used as the variables field of GenericModel or GenericModel. It represents a model that does not support any constraint nor objective function.

Example

The following model type represents a conic model in geometric form. As opposed to VariablesContainer, FreeVariables does not support constraint bounds so they are bridged into an affine constraint in the MOI.Nonnegatives cone as expected for the geometric conic form.

julia> MOI.Utilities.@product_of_sets(
+    Cones,
+    MOI.Zeros,
+    MOI.Nonnegatives,
+    MOI.SecondOrderCone,
+    MOI.PositiveSemidefiniteConeTriangle,
+);
+
+julia> const ConicModel{T} = MOI.Utilities.GenericOptimizer{
+    T,
+    MOI.Utilities.ObjectiveContainer{T},
+    MOI.Utilities.FreeVariables,
+    MOI.Utilities.MatrixOfConstraints{
+        T,
+        MOI.Utilities.MutableSparseMatrixCSC{
+            T,
+            Int,
+            MOI.Utilities.OneBasedIndexing,
+        },
+        Vector{T},
+        Cones{T},
+    },
+};
+
+julia> model = MOI.instantiate(ConicModel{Float64}, with_bridge_type=Float64);
+
+julia> x = MOI.add_variable(model)
+MathOptInterface.VariableIndex(1)
+
+julia> c = MOI.add_constraint(model, x, MOI.GreaterThan(1.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)
+
+julia> MOI.Bridges.is_bridged(model, c)
+true
+
+julia> bridge = MOI.Bridges.bridge(model, c)
+MathOptInterface.Bridges.Constraint.VectorizeBridge{Float64, MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives, MathOptInterface.VariableIndex}(MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1), 1.0)
+
+julia> bridge.vector_constraint
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
+
+julia> MOI.Bridges.is_bridged(model, bridge.vector_constraint)
+false
source

.constraints

MathOptInterface.Utilities.VectorOfConstraintsType
mutable struct VectorOfConstraints{
+    F<:MOI.AbstractFunction,
+    S<:MOI.AbstractSet,
+} <: MOI.ModelLike
+    constraints::CleverDicts.CleverDict{
+        MOI.ConstraintIndex{F,S},
+        Tuple{F,S},
+        typeof(CleverDicts.key_to_index),
+        typeof(CleverDicts.index_to_key),
+    }
+end

A struct storing F-in-S constraints as a mapping between the constraint indices to the corresponding tuple of function and set.

source
MathOptInterface.Utilities.@struct_of_constraints_by_function_typesMacro
Utilities.@struct_of_constraints_by_function_types(name, func_types...)

Given a vector of n function types (F1, F2,..., Fn) in func_types, defines a subtype of StructOfConstraints of name name and which type parameters {T, C1, C2, ..., Cn}. It contains n field where the ith field has type Ci and stores the constraints of function type Fi.

The expression Fi can also be a union in which case any constraint for which the function type is in the union is stored in the field with type Ci.

source
MathOptInterface.Utilities.@struct_of_constraints_by_set_typesMacro
Utilities.@struct_of_constraints_by_set_types(name, func_types...)

Given a vector of n set types (S1, S2,..., Sn) in func_types, defines a subtype of StructOfConstraints of name name and which type parameters {T, C1, C2, ..., Cn}. It contains n field where the ith field has type Ci and stores the constraints of set type Si. The expression Si can also be a union in which case any constraint for which the set type is in the union is stored in the field with type Ci. This can be useful if Ci is a MatrixOfConstraints in order to concatenate the coefficients of constraints of several different set types in the same matrix.

source
MathOptInterface.Utilities.struct_of_constraint_codeFunction
struct_of_constraint_code(struct_name, types, field_types = nothing)

Given a vector of n Union{SymbolFun,_UnionSymbolFS{SymbolFun}} or Union{SymbolSet,_UnionSymbolFS{SymbolSet}} in types, defines a subtype of StructOfConstraints of name name and which type parameters {T, F1, F2, ..., Fn} if field_types is nothing and a {T} otherwise. It contains n field where the ith field has type Ci if field_types is nothing and type field_types[i] otherwise. If types is vector of Union{SymbolFun,_UnionSymbolFS{SymbolFun}} (resp. Union{SymbolSet,_UnionSymbolFS{SymbolSet}}) then the constraints of that function (resp. set) type are stored in the corresponding field.

This function is used by the macros @model, @struct_of_constraints_by_function_types and @struct_of_constraints_by_set_types.

source

Caching optimizer

MathOptInterface.Utilities.CachingOptimizerType
CachingOptimizer

CachingOptimizer is an intermediate layer that stores a cache of the model and links it with an optimizer. It supports incremental model construction and modification even when the optimizer doesn't.

Constructors

    CachingOptimizer(cache::MOI.ModelLike, optimizer::AbstractOptimizer)

Creates a CachingOptimizer in AUTOMATIC mode, with the optimizer optimizer.

The type of the optimizer returned is CachingOptimizer{typeof(optimizer), typeof(cache)} so it does not support the function reset_optimizer(::CachingOptimizer, new_optimizer) if the type of new_optimizer is different from the type of optimizer.

    CachingOptimizer(cache::MOI.ModelLike, mode::CachingOptimizerMode)

Creates a CachingOptimizer in the NO_OPTIMIZER state and mode mode.

The type of the optimizer returned is CachingOptimizer{MOI.AbstractOptimizer,typeof(cache)} so it does support the function reset_optimizer(::CachingOptimizer, new_optimizer) if the type of new_optimizer is different from the type of optimizer.

About the type

States

A CachingOptimizer may be in one of three possible states (CachingOptimizerState):

  • NO_OPTIMIZER: The CachingOptimizer does not have any optimizer.
  • EMPTY_OPTIMIZER: The CachingOptimizer has an empty optimizer. The optimizer is not synchronized with the cached model.
  • ATTACHED_OPTIMIZER: The CachingOptimizer has an optimizer, and it is synchronized with the cached model.

Modes

A CachingOptimizer has two modes of operation (CachingOptimizerMode):

  • MANUAL: The only methods that change the state of the CachingOptimizer are Utilities.reset_optimizer, Utilities.drop_optimizer, and Utilities.attach_optimizer. Attempting to perform an operation in the incorrect state results in an error.
  • AUTOMATIC: The CachingOptimizer changes its state when necessary. For example, optimize! will automatically call attach_optimizer (an optimizer must have been previously set). Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to EMPTY_OPTIMIZER mode.
source
MathOptInterface.Utilities.attach_optimizerFunction
attach_optimizer(model::CachingOptimizer)

Attaches the optimizer to model, copying all model data into it. Can be called only from the EMPTY_OPTIMIZER state. If the copy succeeds, the CachingOptimizer will be in state ATTACHED_OPTIMIZER after the call, otherwise an error is thrown; see MOI.copy_to for more details on which errors can be thrown.

source
MathOptInterface.Utilities.reset_optimizerFunction
reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer)

Sets or resets m to have the given empty optimizer optimizer.

Can be called from any state. An assertion error will be thrown if optimizer is not empty.

The CachingOptimizer m will be in state EMPTY_OPTIMIZER after the call.

source
reset_optimizer(m::CachingOptimizer)

Detaches and empties the current optimizer. Can be called from ATTACHED_OPTIMIZER or EMPTY_OPTIMIZER state. The CachingOptimizer will be in state EMPTY_OPTIMIZER after the call.

source

Mock optimizer

Printing

MathOptInterface.Utilities.latex_formulationFunction
latex_formulation(model::MOI.ModelLike; kwargs...)

Wrap model in a type so that it can be pretty-printed as text/latex in a notebook like IJulia, or in Documenter.

To render the model, end the cell with latex_formulation(model), or call display(latex_formulation(model)) in to force the display of the model from inside a function.

Possible keyword arguments are:

  • simplify_coefficients : Simplify coefficients if possible by omitting them or removing trailing zeros.
  • default_name : The name given to variables with an empty name.
  • print_types : Print the MOI type of each function and set for clarity.
source

Copy utilities

MathOptInterface.Utilities.ModelFilterType
ModelFilter(filter::Function, model::MOI.ModelLike)

A layer to filter out various components of model.

The filter function takes a single argument, which is each element from the list returned by the attributes below. It returns true if the element should be visible in the filtered model and false otherwise.

The components that are filtered are:

  • Entire constraint types via:
    • MOI.ListOfConstraintTypesPresent
  • Individual constraints via:
    • MOI.ListOfConstraintIndices{F,S}
  • Specific attributes via:
    • MOI.ListOfModelAttributesSet
    • MOI.ListOfConstraintAttributesSet
    • MOI.ListOfVariableAttributesSet
Warning

The list of attributes filtered may change in a future release. You should write functions that are generic and not limited to the five types listed above. Thus, you should probably define a fallback filter(::Any) = true.

See below for examples of how this works.

Note

This layer has a limited scope. It is intended by be used in conjunction with MOI.copy_to.

Example: copy model excluding integer constraints

Use the do syntax to provide a single function.

filtered_src = MOI.Utilities.ModelFilter(src) do item
+    return item != (MOI.VariableIndex, MOI.Integer)
+end
+MOI.copy_to(dest, filtered_src)

Example: copy model excluding names

Use type dispatch to simplify the implementation:

my_filter(::Any) = true  # Note the generic fallback!
+my_filter(::MOI.VariableName) = false
+my_filter(::MOI.ConstraintName) = false
+filtered_src = MOI.Utilities.ModelFilter(my_filter, src)
+MOI.copy_to(dest, filtered_src)

Example: copy irreducible infeasible subsystem

my_filter(::Any) = true  # Note the generic fallback!
+function my_filter(ci::MOI.ConstraintIndex)
+    status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)
+    return status != MOI.NOT_IN_CONFLICT
+end
+filtered_src = MOI.Utilities.ModelFilter(my_filter, src)
+MOI.copy_to(dest, filtered_src)
source

Penalty relaxation

MathOptInterface.Utilities.PenaltyRelaxationType
PenaltyRelaxation(
+    penalties = Dict{MOI.ConstraintIndex,Float64}();
+    default::Union{Nothing,T} = 1.0,
+)

A problem modifier that, when passed to MOI.modify, destructively modifies the model in-place to create a penalized relaxation of the constraints.

Warning

This is a destructive routine that modifies the model in-place. If you don't want to modify the original model, use JuMP.copy_model to create a copy before calling MOI.modify.

Reformulation

See Utilities.ScalarPenaltyRelaxation for details of the reformulation.

For each constraint ci, the penalty passed to Utilities.ScalarPenaltyRelaxation is get(penalties, ci, default). If the value is nothing, because ci does not exist in penalties and default = nothing, then the constraint is skipped.

Return value

MOI.modify(model, PenaltyRelaxation()) returns a Dict{MOI.ConstraintIndex,MOI.ScalarAffineFunction} that maps each constraint index to the corresponding y + z as a MOI.ScalarAffineFunction. In an optimal solution, query the value of these functions to compute the violation of each constraint.

Relax a subset of constraints

To relax a subset of constraints, pass a penalties dictionary and set default = nothing.

Supported constraint types

The penalty relaxation is currently limited to modifying MOI.ScalarAffineFunction and MOI.ScalarQuadraticFunction constraints in the linear sets MOI.LessThan, MOI.GreaterThan, MOI.EqualTo and MOI.Interval.

It does not include variable bound or integrality constraints, because these cannot be modified in-place.

To modify variable bounds, rewrite them as linear constraints.

Examples

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(default = 2.0));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 2.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> map[c] isa MOI.ScalarAffineFunction{Float64}
+true
julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 3.0)));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 3.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> map[c] isa MOI.ScalarAffineFunction{Float64}
+true
source
MathOptInterface.Utilities.ScalarPenaltyRelaxationType
ScalarPenaltyRelaxation(penalty::T) where {T}

A problem modifier that, when passed to MOI.modify, destructively modifies the constraint in-place to create a penalized relaxation of the constraint.

Warning

This is a destructive routine that modifies the constraint in-place. If you don't want to modify the original model, use JuMP.copy_model to create a copy before calling MOI.modify.

Reformulation

The penalty relaxation modifies constraints of the form $f(x) \in S$ into $f(x) + y - z \in S$, where $y, z \ge 0$, and then it introduces a penalty term into the objective of $a \times (y + z)$ (if minimizing, else $-a$), where $a$ is penalty

When S is MOI.LessThan or MOI.GreaterThan, we omit y or z respectively as a performance optimization.

Return value

MOI.modify(model, ci, ScalarPenaltyRelaxation(penalty)) returns y + z as a MOI.ScalarAffineFunction. In an optimal solution, query the value of this function to compute the violation of the constraint.

Examples

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 2.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> f isa MOI.ScalarAffineFunction{Float64}
+true
source

MatrixOfConstraints

MathOptInterface.Utilities.MatrixOfConstraintsType
mutable struct MatrixOfConstraints{T,AT,BT,ST} <: MOI.ModelLike
+    coefficients::AT
+    constants::BT
+    sets::ST
+    caches::Vector{Any}
+    are_indices_mapped::Vector{BitSet}
+    final_touch::Bool
+end

Represent ScalarAffineFunction and VectorAffinefunction constraints in a matrix form where the linear coefficients of the functions are stored in the coefficients field, the constants of the functions or sets are stored in the constants field. Additional information about the sets are stored in the sets field.

This model can only be used as the constraints field of a MOI.Utilities.AbstractModel.

When the constraints are added, they are stored in the caches field. They are only loaded in the coefficients and constants fields once MOI.Utilities.final_touch is called. For this reason, MatrixOfConstraints should not be used by an incremental interface. Use MOI.copy_to instead.

The constraints can be added in two different ways:

  1. With add_constraint, in which case a canonicalized copy of the function is stored in caches.
  2. With pass_nonvariable_constraints, in which case the functions and sets are stored themselves in caches without mapping the variable indices. The corresponding index in caches is added in are_indices_mapped. This avoids doing a copy of the function in case the getter of CanonicalConstraintFunction does not make a copy for the source model, e.g., this is the case of VectorOfConstraints.

We illustrate this with an example. Suppose a model is copied from a src::MOI.Utilities.Model to a bridged model with a MatrixOfConstraints. For all the types that are not bridged, the constraints will be copied with pass_nonvariable_constraints. Hence the functions stored in caches are exactly the same as the ones stored in src. This is ok since this is only during the copy_to operation during which src cannot be modified. On the other hand, for the types that are bridged, the functions added may contain duplicates even if the functions did not contain duplicates in src so duplicates are removed with MOI.Utilities.canonical.

Interface

The .coefficients::AT type must implement:

The .constants::BT type must implement:

The .sets::ST type must implement:

source

.coefficients

MathOptInterface.Utilities.load_termsFunction
load_terms(coefficients, index_map, func, offset)::Nothing

Loads the terms of func to coefficients, mapping the variable indices with index_map.

The ith dimension of func is loaded at the (offset + i)th row of coefficients.

The function must be allocated first with allocate_terms.

The function func must be canonicalized, see is_canonical.

source
MathOptInterface.Utilities.final_touchFunction
final_touch(coefficients)::Nothing

Informs the coefficients that all functions have been added with load_terms. No more modification is allowed unless MOI.empty! is called.

final_touch(sets)::Nothing

Informs the sets that all functions have been added with add_set. No more modification is allowed unless MOI.empty! is called.

source
MathOptInterface.Utilities.extract_functionFunction
extract_function(coefficients, row::Integer, constant::T) where {T}

Return the MOI.ScalarAffineFunction{T} function corresponding to row row in coefficients.

extract_function(
+    coefficients,
+    rows::UnitRange,
+    constants::Vector{T},
+) where{T}

Return the MOI.VectorAffineFunction{T} function corresponding to rows rows in coefficients.

source
MathOptInterface.Utilities.MutableSparseMatrixCSCType
mutable struct MutableSparseMatrixCSC{Tv,Ti<:Integer,I<:AbstractIndexing}
+    indexing::I
+    m::Int
+    n::Int
+    colptr::Vector{Ti}
+    rowval::Vector{Ti}
+    nzval::Vector{Tv}
+    nz_added::Vector{Ti}
+end

Matrix type loading sparse matrices in the Compressed Sparse Column format. The indexing used is indexing, see AbstractIndexing. The other fields have the same meaning than for SparseArrays.SparseMatrixCSC except that the indexing is different unless indexing is OneBasedIndexing. In addition, nz_added is used to cache the number of non-zero terms that have been added to each column due to the incremental nature of load_terms.

The matrix is loaded in 5 steps:

  1. MOI.empty! is called.
  2. MOI.Utilities.add_column and MOI.Utilities.allocate_terms are called in any order.
  3. MOI.Utilities.set_number_of_rows is called.
  4. MOI.Utilities.load_terms is called for each affine function.
  5. MOI.Utilities.final_touch is called.
source
MathOptInterface.Utilities.ZeroBasedIndexingType
struct ZeroBasedIndexing <: AbstractIndexing end

Zero-based indexing: the ith row or column has index i - 1. This is useful when the vectors of row and column indices need to be communicated to a library using zero-based indexing such as C libraries.

source

.constants

MathOptInterface.Utilities.load_constantsFunction
load_constants(constants, offset, func_or_set)::Nothing

This function loads the constants of func_or_set in constants at an offset of offset. Where offset is the sum of the dimensions of the constraints already loaded. The storage should be preallocated with resize! before calling this function.

This function should be implemented to be usable as storage of constants for MatrixOfConstraints.

The constants are loaded in three steps:

  1. Base.empty! is called.
  2. Base.resize! is called with the sum of the dimensions of all constraints.
  3. MOI.Utilities.load_constants is called for each function for vector constraint or set for scalar constraint.
source

.sets

MathOptInterface.Utilities.set_indexFunction
set_index(sets, ::Type{S})::Union{Int,Nothing} where {S<:MOI.AbstractSet}

Return an integer corresponding to the index of the set type in the list given by set_types.

If S is not part of the list, return nothing.

source
MathOptInterface.Utilities.add_setFunction
add_set(sets, i)::Int64

Add a scalar set of type index i.

add_set(sets, i, dim)::Int64

Add a vector set of type index i and dimension dim.

Both methods return a unique Int64 of the set that can be used to reference this set.

source
MathOptInterface.Utilities.rowsFunction
rows(sets, ci::MOI.ConstraintIndex)::Union{Int,UnitRange{Int}}

Return the rows in 1:MOI.dimension(sets) corresponding to the set of id ci.value.

For scalar sets, this returns an Int. For vector sets, this returns an UnitRange{Int}.

source
MathOptInterface.Utilities.num_rowsFunction
num_rows(sets::OrderedProductOfSets, ::Type{S}) where {S}

Return the number of rows corresponding to a set of type S. That is, it is the sum of the dimensions of the sets of type S.

source

Fallbacks

MathOptInterface.Utilities.get_fallbackFunction
get_fallback(model::MOI.ModelLike, ::MOI.ObjectiveValue)

Compute the objective function value using the VariablePrimal results and the ObjectiveFunction value.

source
get_fallback(model::MOI.ModelLike, ::MOI.DualObjectiveValue, T::Type)::T

Compute the dual objective value of type T using the ConstraintDual results and the ConstraintFunction and ConstraintSet values. Note that the nonlinear part of the model is ignored.

source
get_fallback(model::MOI.ModelLike, ::MOI.ConstraintPrimal,
+             constraint_index::MOI.ConstraintIndex)

Compute the value of the function of the constraint of index constraint_index using the VariablePrimal results and the ConstraintFunction values.

source
get_fallback(model::MOI.ModelLike, attr::MOI.ConstraintDual,
+             ci::MOI.ConstraintIndex{Union{MOI.VariableIndex,
+                                           MOI.VectorOfVariables}})

Compute the dual of the constraint of index ci using the ConstraintDual of other constraints and the ConstraintFunction values. Throws an error if some constraints are quadratic or if there is one another MOI.VariableIndex-in-S or MOI.VectorOfVariables-in-S constraint with one of the variables in the function of the constraint ci.

source

Function utilities

The following utilities are available for functions:

MathOptInterface.Utilities.eval_variablesFunction
eval_variables(value_fn::Function, f::MOI.AbstractFunction)

Returns the value of function f if each variable index vi is evaluated as value_fn(vi).

Note that value_fn must return a Number. See substitute_variables for a similar function where value_fn returns an MOI.AbstractScalarFunction.

Warning

The two-argument version of eval_variables is deprecated and may be removed in MOI v2.0.0. Use the three-argument method eval_variables(::Function, ::MOI.ModelLike, ::MOI.AbstractFunction) instead.

source
MathOptInterface.Utilities.map_indicesFunction
map_indices(index_map::Function, attr::MOI.AnyAttribute, x::X)::X where {X}

Substitute any MOI.VariableIndex (resp. MOI.ConstraintIndex) in x by the MOI.VariableIndex (resp. MOI.ConstraintIndex) of the same type given by index_map(x).

When to implement this method for new types X

This function is used by implementations of MOI.copy_to on constraint functions, attribute values and submittable values. If you define a new attribute whose values x::X contain variable or constraint indices, you must also implement this function.

source
map_indices(
+    variable_map::AbstractDict{T,T},
+    x::X,
+)::X where {T<:MOI.Index,X}

Shortcut for map_indices(vi -> variable_map[vi], x).

source
MathOptInterface.Utilities.substitute_variablesFunction
substitute_variables(variable_map::Function, x)

Substitute any MOI.VariableIndex in x by variable_map(x). The variable_map function returns either MOI.VariableIndex or MOI.ScalarAffineFunction, see eval_variables for a similar function where variable_map returns a number.

This function is used by bridge optimizers on constraint functions, attribute values and submittable values when at least one variable bridge is used hence it needs to be implemented for custom types that are meant to be used as attribute or submittable value.

Note

When implementing a new method, don't use substitute_variables(::Function, because Julia will not specialize on it. Use instead substitute_variables(::F, ...) where {F<:Function}.

source
MathOptInterface.Utilities.filter_variablesFunction
filter_variables(keep::Function, f::AbstractFunction)

Return a new function f with the variable vi such that !keep(vi) removed.

WARNING: Don't define filter_variables(::Function, ...) because Julia will not specialize on this. Define instead filter_variables(::F, ...) where {F<:Function}.

source
MathOptInterface.Utilities.remove_variableFunction
remove_variable(f::AbstractFunction, vi::VariableIndex)

Return a new function f with the variable vi removed.

source
remove_variable(f::MOI.AbstractFunction, s::MOI.AbstractSet, vi::MOI.VariableIndex)

Return a tuple (g, t) representing the constraint f-in-s with the variable vi removed. That is, the terms containing the variable vi in the function f are removed and the dimension of the set s is updated if needed (e.g. when f is a VectorOfVariables with vi being one of the variables).

source
MathOptInterface.Utilities.all_coefficientsFunction
all_coefficients(p::Function, f::MOI.AbstractFunction)

Determine whether predicate p returns true for all coefficients of f, returning false as soon as the first coefficient of f for which p returns false is encountered (short-circuiting). Similar to all.

source
MathOptInterface.Utilities.unsafe_addFunction
unsafe_add(t1::MOI.ScalarAffineTerm, t2::MOI.ScalarAffineTerm)

Sums the coefficients of t1 and t2 and returns an output MOI.ScalarAffineTerm. It is unsafe because it uses the variable of t1 as the variable of the output without checking that it is equal to that of t2.

source
unsafe_add(t1::MOI.ScalarQuadraticTerm, t2::MOI.ScalarQuadraticTerm)

Sums the coefficients of t1 and t2 and returns an output MOI.ScalarQuadraticTerm. It is unsafe because it uses the variable's of t1 as the variable's of the output without checking that they are the same (up to permutation) to those of t2.

source
unsafe_add(t1::MOI.VectorAffineTerm, t2::MOI.VectorAffineTerm)

Sums the coefficients of t1 and t2 and returns an output MOI.VectorAffineTerm. It is unsafe because it uses the output_index and variable of t1 as the output_index and variable of the output term without checking that they are equal to those of t2.

source
MathOptInterface.Utilities.isapprox_zeroFunction
isapprox_zero(f::MOI.AbstractFunction, tol)

Return a Bool indicating whether the function f is approximately zero using tol as a tolerance.

Important note

This function assumes that f does not contain any duplicate terms, you might want to first call canonical if that is not guaranteed. For instance, given

f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([1, -1], [x, x]), 0)

then isapprox_zero(f) is false but isapprox_zero(MOIU.canonical(f)) is true.

source
MathOptInterface.Utilities.zero_with_output_dimensionFunction
zero_with_output_dimension(::Type{T}, output_dimension::Integer) where {T}

Create an instance of type T with the output dimension output_dimension.

This is mostly useful in Bridges, when code needs to be agnostic to the type of vector-valued function that is passed in.

source

The following functions can be used to canonicalize a function:

MathOptInterface.Utilities.is_canonicalFunction
is_canonical(f::Union{ScalarAffineFunction, VectorAffineFunction})

Returns a Bool indicating whether the function is in canonical form. See canonical.

source
is_canonical(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})

Returns a Bool indicating whether the function is in canonical form. See canonical.

source
MathOptInterface.Utilities.canonicalFunction
canonical(f::MOI.AbstractFunction)

Returns the function in a canonical form, i.e.

  • A term appear only once.
  • The coefficients are nonzero.
  • The terms appear in increasing order of variable where there the order of the variables is the order of their value.
  • For a AbstractVectorFunction, the terms are sorted in ascending order of output index.

The output of canonical can be assumed to be a copy of f, even for VectorOfVariables.

Examples

If x (resp. y, z) is VariableIndex(1) (resp. 2, 3). The canonical representation of ScalarAffineFunction([y, x, z, x, z], [2, 1, 3, -2, -3], 5) is ScalarAffineFunction([x, y], [-1, 2], 5).

source
MathOptInterface.Utilities.canonicalize!Function
canonicalize!(f::Union{ScalarAffineFunction, VectorAffineFunction})

Convert a function to canonical form in-place, without allocating a copy to hold the result. See canonical.

source
canonicalize!(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})

Convert a function to canonical form in-place, without allocating a copy to hold the result. See canonical.

source

The following functions can be used to manipulate functions with basic algebra:

MathOptInterface.Utilities.scalarizeFunction
scalarize(func::MOI.VectorOfVariables, ignore_constants::Bool = false)

Returns a vector of scalar functions making up the vector function in the form of a Vector{MOI.SingleVariable}.

See also eachscalar.

source
scalarize(func::MOI.VectorAffineFunction{T}, ignore_constants::Bool = false)

Returns a vector of scalar functions making up the vector function in the form of a Vector{MOI.ScalarAffineFunction{T}}.

See also eachscalar.

source
scalarize(func::MOI.VectorQuadraticFunction{T}, ignore_constants::Bool = false)

Returns a vector of scalar functions making up the vector function in the form of a Vector{MOI.ScalarQuadraticFunction{T}}.

See also eachscalar.

source
MathOptInterface.Utilities.promote_operationFunction
promote_operation(
+    op::Function,
+    ::Type{T},
+    ArgsTypes::Type{<:Union{T,AbstractVector{T},MOI.AbstractFunction}}...,
+) where {T<:Number}

Compute the return type of the call operate(op, T, args...), where the types of the arguments args are ArgsTypes.

One assumption is that the element type T is invariant under each operation. That is, op(::T, ::T)::T where op is a +, -, *, and /.

There are six methods for which we implement Utilities.promote_operation:

  1. + a. promote_operation(::typeof(+), ::Type{T}, ::Type{F1}, ::Type{F2})
  2. - a. promote_operation(::typeof(-), ::Type{T}, ::Type{F}) b. promote_operation(::typeof(-), ::Type{T}, ::Type{F1}, ::Type{F2})
  3. * a. promote_operation(::typeof(*), ::Type{T}, ::Type{T}, ::Type{F}) b. promote_operation(::typeof(*), ::Type{T}, ::Type{F}, ::Type{T}) c. promote_operation(::typeof(*), ::Type{T}, ::Type{F1}, ::Type{F2}) where F1 and F2 are VariableIndex or ScalarAffineFunction d. promote_operation(::typeof(*), ::Type{T}, ::Type{<:Diagonal{T}}, ::Type{F}
  4. / a. promote_operation(::typeof(/), ::Type{T}, ::Type{F}, ::Type{T})
  5. vcat a. promote_operation(::typeof(vcat), ::Type{T}, ::Type{F}...)
  6. imag a. promote_operation(::typeof(imag), ::Type{T}, ::Type{F}) where F is VariableIndex or VectorOfVariables

In each case, F (or F1 and F2) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define promote_operation(-, T, F1, F2) where F1 is a scalar-valued function and F2 is a vector-valued function. The ten supported types are:

  1. ::T
  2. ::VariableIndex
  3. ::ScalarAffineFunction{T}
  4. ::ScalarQuadraticFunction{T}
  5. ::ScalarNonlinearFunction
  6. ::AbstractVector{T}
  7. ::VectorOfVariables
  8. ::VectorAffineFunction{T}
  9. ::VectorQuadraticFunction{T}
  10. ::VectorNonlinearFunction
source
MathOptInterface.Utilities.operateFunction
operate(
+    op::Function,
+    ::Type{T},
+    args::Union{T,MOI.AbstractFunction}...,
+)::MOI.AbstractFunction where {T<:Number}

Returns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T.

No argument can be modified.

Methods

  1. + a. operate(::typeof(+), ::Type{T}, ::F1) b. operate(::typeof(+), ::Type{T}, ::F1, ::F2) c. operate(::typeof(+), ::Type{T}, ::F1...)
  2. - a. operate(::typeof(-), ::Type{T}, ::F) b. operate(::typeof(-), ::Type{T}, ::F1, ::F2)
  3. * a. operate(::typeof(*), ::Type{T}, ::T, ::F) b. operate(::typeof(*), ::Type{T}, ::F, ::T) c. operate(::typeof(*), ::Type{T}, ::F1, ::F2) where F1 and F2 are VariableIndex or ScalarAffineFunction d. operate(::typeof(*), ::Type{T}, ::Diagonal{T}, ::F)
  4. / a. operate(::typeof(/), ::Type{T}, ::F, ::T)
  5. vcat a. operate(::typeof(vcat), ::Type{T}, ::F...)
  6. imag a. operate(::typeof(imag), ::Type{T}, ::F) where F is VariableIndex or VectorOfVariables

One assumption is that the element type T is invariant under each operation. That is, op(::T, ::T)::T where op is a +, -, *, and /.

In each case, F (or F1 and F2) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define promote_operation(-, T, F1, F2) where F1 is a scalar-valued function and F2 is a vector-valued function. The ten supported types are:

  1. ::T
  2. ::VariableIndex
  3. ::ScalarAffineFunction{T}
  4. ::ScalarQuadraticFunction{T}
  5. ::ScalarNonlinearFunction
  6. ::AbstractVector{T}
  7. ::VectorOfVariables
  8. ::VectorAffineFunction{T}
  9. ::VectorQuadraticFunction{T}
  10. ::VectorNonlinearFunction
source
MathOptInterface.Utilities.operate!Function
operate!(
+    op::Function,
+    ::Type{T},
+    args::Union{T,MOI.AbstractFunction}...,
+)::MOI.AbstractFunction where {T<:Number}

Returns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T.

The first argument may be modified, in which case the return value is identical to the first argument. For operations which cannot be implemented in-place, this function returns a new object.

source
MathOptInterface.Utilities.operate_output_index!Function
operate_output_index!(
+    op::Union{typeof(+),typeof(-)},
+    ::Type{T},
+    output_index::Integer,
+    f::Union{AbstractVector{T},MOI.AbstractVectorFunction}
+    g::Union{T,MOI.AbstractScalarFunction}...
+) where {T<:Number}

Return an MOI.AbstractVectorFunction in which the scalar function in row output_index is the result of op(f[output_index], g).

The functions at output index different to output_index are the same as the functions at the same output index in func. The first argument may be modified.

Methods

  1. + a. operate_output_index!(+, ::Type{T}, ::Int, ::VectorF, ::ScalarF)
  2. - a. operate_output_index!(-, ::Type{T}, ::Int, ::VectorF, ::ScalarF)
source
MathOptInterface.Utilities.vectorizeFunction
vectorize(x::AbstractVector{<:Number})

Returns x.

source
vectorize(x::AbstractVector{MOI.VariableIndex})

Returns the vector of scalar affine functions in the form of a MOI.VectorAffineFunction{T}.

source
vectorize(funcs::AbstractVector{MOI.ScalarAffineFunction{T}}) where T

Returns the vector of scalar affine functions in the form of a MOI.VectorAffineFunction{T}.

source
vectorize(funcs::AbstractVector{MOI.ScalarQuadraticFunction{T}}) where T

Returns the vector of scalar quadratic functions in the form of a MOI.VectorQuadraticFunction{T}.

source

Constraint utilities

The following utilities are available for moving the function constant to the set for scalar constraints:

MathOptInterface.Utilities.shift_constantFunction
shift_constant(set::MOI.AbstractScalarSet, offset)

Returns a new scalar set new_set such that func-in-set is equivalent to func + offset-in-new_set.

Only define this function if it makes sense to!

Use supports_shift_constant to check if the set supports shifting:

if supports_shift_constant(typeof(old_set))
+    new_set = shift_constant(old_set, offset)
+    f.constant = 0
+    add_constraint(model, f, new_set)
+else
+    add_constraint(model, f, old_set)
+end

See also supports_shift_constant.

Examples

The call shift_constant(MOI.Interval(-2, 3), 1) is equal to MOI.Interval(-1, 4).

source
MathOptInterface.Utilities.normalize_and_add_constraintFunction
normalize_and_add_constraint(
+    model::MOI.ModelLike,
+    func::MOI.AbstractScalarFunction,
+    set::MOI.AbstractScalarSet;
+    allow_modify_function::Bool = false,
+)

Adds the scalar constraint obtained by moving the constant term in func to the set in model. If allow_modify_function is true then the function func can be modified.

source

The following utility identifies those constraints imposing bounds on a given variable, and returns those bound values:

MathOptInterface.Utilities.get_boundsFunction
get_bounds(model::MOI.ModelLike, ::Type{T}, x::MOI.VariableIndex)

Return a tuple (lb, ub) of type Tuple{T, T}, where lb and ub are lower and upper bounds, respectively, imposed on x in model.

source

The following utilities are useful when working with symmetric matrix cones.

Set utilities

The following utilities are available for sets:

MathOptInterface.Utilities.ProjectionUpperBoundDistanceType
ProjectionUpperBoundDistance() <: AbstractDistance

An upper bound on the minimum distance between point and the closest feasible point in set.

Definition of distance

The minimum distance is computed as:

\[d(x, \mathcal{K}) = \min_{y \in \mathcal{K}} || x - y ||\]

where $x$ is point and $\mathcal{K}$ is set. The norm is computed as:

\[||x|| = \sqrt{f(x, x, \mathcal{K})}\]

where $f$ is Utilities.set_dot.

In the default case, where the set does not have a specialized method for Utilities.set_dot, the norm is equivalent to the Euclidean norm $||x|| = \sqrt{\sum x_i^2}$.

Why an upper bound?

In most cases, distance_to_set should return the smallest upper bound, but it may return a larger value if the smallest upper bound is expensive to compute.

For example, given an epigraph from of a conic set, $\{(t, x) | f(x) \le t\}$, it may be simpler to return $\delta$ such that $f(x) \le t + \delta$, rather than computing the nearest projection onto the set.

If the distance is not the smallest upper bound, the docstring of the appropriate distance_to_set method must describe the way that the distance is computed.

source
MathOptInterface.Utilities.distance_to_setFunction
distance_to_set(
+    [d::AbstractDistance = ProjectionUpperBoundDistance()],]
+    point::T,
+    set::MOI.AbstractScalarSet,
+) where {T}
+
+distance_to_set(
+    [d::AbstractDistance = ProjectionUpperBoundDistance(),]
+    point::AbstractVector{T},
+    set::MOI.AbstractVectorSet,
+) where {T}

Compute the distance between point and set using the distance metric d. If point is in the set set, this function must return zero(T).

If d is omitted, the default distance is Utilities.ProjectionUpperBoundDistance.

source
MathOptInterface.Utilities.set_dotFunction
set_dot(x::AbstractVector, y::AbstractVector, set::AbstractVectorSet)

Return the scalar product between a vector x of the set set and a vector y of the dual of the set s.

source
set_dot(x, y, set::AbstractScalarSet)

Return the scalar product between a number x of the set set and a number y of the dual of the set s.

source

DoubleDicts

MathOptInterface.Utilities.DoubleDicts.DoubleDictType
DoubleDict{V}

An optimized dictionary to map MOI.ConstraintIndex to values of type V.

Works as a AbstractDict{MOI.ConstraintIndex,V} with minimal differences.

If V is also a MOI.ConstraintIndex, use IndexDoubleDict.

Note that MOI.ConstraintIndex is not a concrete type, opposed to MOI.ConstraintIndex{MOI.VariableIndex, MOI.Integers}, which is a concrete type.

When looping through multiple keys of the same Function-in-Set type, use

inner = dict[F, S]

to return a type-stable DoubleDictInner.

source
MathOptInterface.Utilities.DoubleDicts.outer_keysFunction
outer_keys(d::AbstractDoubleDict)

Return an iterator over the outer keys of the AbstractDoubleDict d. Each outer key is a Tuple{Type,Type} so that a double loop can be easily used:

for (F, S) in DoubleDicts.outer_keys(dict)
+    for (k, v) in dict[F, S]
+        # ...
+    end
+end

For performance, it is recommended that the inner loop lies in a separate function to gurantee type-stability. Some outer keys (F, S) might lead to an empty dict[F, S]. If you want only nonempty dict[F, S], use nonempty_outer_keys.

source
MathOptInterface.Utilities.DoubleDicts.nonempty_outer_keysFunction
nonempty_outer_keys(d::AbstractDoubleDict)

Return a vector of outer keys of the AbstractDoubleDict d.

Only outer keys that have a nonempty set of inner keys will be returned.

Each outer key is a Tuple{Type,Type} so that a double loop can be easily used

for (F, S) in DoubleDicts.nonempty_outer_keys(dict)
+    for (k, v) in dict[F, S]
+        # ...
+    end
+end
+For performance, it is recommended that the inner loop lies in a separate
+function to gurantee type-stability.
+
+If you want an iterator of all current outer keys, use [`outer_keys`](@ref).
source
diff --git a/previews/PR2274/tutorials/bridging_constraint/index.html b/previews/PR2274/tutorials/bridging_constraint/index.html new file mode 100644 index 0000000000..4fc1d2a7cd --- /dev/null +++ b/previews/PR2274/tutorials/bridging_constraint/index.html @@ -0,0 +1,102 @@ + +Implementing a constraint bridge · MathOptInterface

Implementing a constraint bridge

This guide outlines the basic steps to create a new bridge from a constraint expressed in the formalism Function-in-Set.

Preliminaries

First, decide on the set you want to bridge. Then, study its properties: the most important one is whether the set is scalar or vector, which impacts the dimensionality of the functions that can be used with the set.

  • A scalar function only has one dimension. MOI defines three types of scalar functions: a variable (VariableIndex), an affine function (ScalarAffineFunction), or a quadratic function (ScalarQuadraticFunction).
  • A vector function has several dimensions (at least one). MOI defines three types of vector functions: several variables (VectorOfVariables), an affine function (VectorAffineFunction), or a quadratic function (VectorQuadraticFunction). The main difference with scalar functions is that the order of dimensions can be very important: for instance, in an indicator constraint (Indicator), the first dimension indicates whether the constraint about the second dimension is active.

To explain how to implement a bridge, we present the example of Bridges.Constraint.FlipSignBridge. This bridge maps <= (LessThan) constraints to >= (GreaterThan) constraints. This corresponds to reversing the sign of the inequality. We focus on scalar affine functions (we disregard the cases of a single variable or of quadratic functions). This example is a simplified version of the code included in MOI.

Four mandatory parts in a constraint bridge

The first part of a constraint bridge is a new concrete subtype of Bridges.Constraint.AbstractBridge. This type must have fields to store all the new variables and constraints that the bridge will add. Typically, these types are parametrized by the type of the coefficients in the model.

Then, three sets of functions must be defined:

  1. Bridges.Constraint.bridge_constraint: this function implements the bridge and creates the required variables and constraints.
  2. supports_constraint: these functions must return true when the combination of function and set is supported by the bridge. By default, the base implementation always returns false and the bridge does not have to provide this implementation.
  3. Bridges.added_constrained_variable_types and Bridges.added_constraint_types: these functions return the types of variables and constraints that this bridge adds. They are used to compute the set of other bridges that are required to use the one you are defining, if need be.

More functions can be implemented, for instance to retrieve properties from the bridge or deleting a bridged constraint.

1. Structure for the bridge

A typical struct behind a bridge depends on the type of the coefficients that are used for the model (typically Float64, but coefficients might also be integers or complex numbers).

This structure must hold a reference to all the variables and the constraints that are created as part of the bridge.

The type of this structure is used throughout MOI as an identifier for the bridge. It is passed as argument to most functions related to bridges.

The best practice is to have the name of this type end with Bridge.

In our example, the bridge maps any ScalarAffineFunction{T}-in-LessThan{T} constraint to a single ScalarAffineFunction{T}-in-GreaterThan{T} constraint. The affine function has coefficients of type T. The bridge is parametrized with T, so that the constraint that the bridge creates also has coefficients of type T.

struct SignBridge{T<:Number} <: Bridges.Constraint.AbstractBridge
+    constraint::ConstraintIndex{ScalarAffineFunction{T}, GreaterThan{T}}
+end

2. Bridge creation

The function Bridges.Constraint.bridge_constraint is called whenever the bridge is instantiated for a specific model, with the given function and set. The arguments to bridge_constraint are similar to add_constraint, with the exception of the first argument: it is the Type of the struct defined in the first step (for our example, Type{SignBridge{T}}).

bridge_constraint returns an instance of the struct defined in the first step. the first step.

In our example, the bridge constraint could be defined as:

function Bridges.Constraint.bridge_constraint(
+    ::Type{SignBridge{T}}, # Bridge to use.
+    model::ModelLike, # Model to which the constraint is being added.
+    f::ScalarAffineFunction{T}, # Function to rewrite.
+    s::LessThan{T}, # Set to rewrite.
+) where {T}
+    # Create the variables and constraints required for the bridge.
+    con = add_constraint(model, -f, GreaterThan(-s.upper))
+
+    # Return an instance of the bridge type with a reference to all the
+    # variables and constraints that were created in this function.
+    return SignBridge(con)
+end

3. Supported constraint types

The function supports_constraint determines whether the bridge type supports a given combination of function and set.

This function must closely match bridge_constraint, because it will not be called if supports_constraint returns false.

function supports_constraint(
+    ::Type{SignBridge{T}}, # Bridge to use.
+    ::Type{ScalarAffineFunction{T}}, # Function to rewrite.
+    ::Type{LessThan{T}}, # Set to rewrite.
+) where {T}
+    # Do some computation to ensure that the constraint is supported.
+    # Typically, you can directly return true.
+    return true
+end

4. Metadata about the bridge

To determine whether a bridge can be used, MOI uses a shortest-path algorithm that uses the variable types and the constraints that the bridge can create. This information is communicated from the bridge to MOI using the functions Bridges.added_constrained_variable_types and Bridges.added_constraint_types. Both return lists of tuples: either a list of 1-tuples containing the variable types (typically, ZeroOne or Integer) or a list of 2-tuples contained the functions and sets (like ScalarAffineFunction{T}-GreaterThan).

For our example, the bridge does not create any constrained variables, and only ScalarAffineFunction{T}-in-GreaterThan{T} constraints:

function Bridges.added_constrained_variable_types(::Type{SignBridge{T}}) where {T}
+    # The bridge does not create variables, return an empty list of tuples:
+    return Tuple{Type}[]
+end
+
+function Bridges.added_constraint_types(::Type{SignBridge{T}}) where {T}
+    return Tuple{Type,Type}[
+        # One element per F-in-S the bridge creates.
+        (ScalarAffineFunction{T}, GreaterThan{T}),
+    ]
+end

A bridge that creates binary variables would rather have this definition of added_constrained_variable_types:

function Bridges.added_constrained_variable_types(::Type{SomeBridge{T}}) where {T}
+    # The bridge only creates binary variables:
+    return Tuple{Type}[(ZeroOne,)]
+end
Warning

If you declare the creation of constrained variables in added_constrained_variable_types, the corresponding constraint type VariableIndex must not be indicated in added_constraint_types. This would restrict the use of the bridge to solvers that can add such a constraint after the variable is created.

More concretely, if you declare in added_constrained_variable_types that your bridge creates binary variables (ZeroOne), and if you never add such a constraint afterward (you do not call add_constraint(model, var, ZeroOne())), then you must not list (VariableIndex, ZeroOne) in added_constraint_types.

Typically, the function Bridges.Constraint.concrete_bridge_type does not have to be defined for most bridges.

Bridge registration

For a bridge to be used by MOI, it must be known by MOI.

SingleBridgeOptimizer

The first way to do so is to create a single-bridge optimizer. This type of optimizer wraps another optimizer and adds the possibility to use only one bridge. It is especially useful when unit testing bridges.

It is common practice to use the same name as the type defined for the bridge (SignBridge, in our example) without the suffix Bridge.

const Sign{T,OT<: ModelLike} =
+    SingleBridgeOptimizer{SignBridge{T}, OT}

In the context of unit tests, this bridge is used in conjunction with a Utilities.MockOptimizer:

mock = Utilities.MockOptimizer(
+    Utilities.UniversalFallback(Utilities.Model{Float64}()),
+)
+bridged_mock = Sign{Float64}(mock)

New bridge for a LazyBridgeOptimizer

Typical user-facing models for MOI are based on Bridges.LazyBridgeOptimizer. For instance, this type of model is returned by Bridges.full_bridge_optimizer. These models can be added more bridges by using Bridges.add_bridge:

inner_optimizer = Utilities.Model{Float64}()
+optimizer = Bridges.full_bridge_optimizer(inner_optimizer, Float64)
+Bridges.add_bridge(optimizer, SignBridge{Float64})

Bridge improvements

Attribute retrieval

Like models, bridges have attributes that can be retrieved using get and set. The most important ones are the number of variables and constraints, but also the lists of variables and constraints.

In our example, we only have one constraint and only have to implement the NumberOfConstraints and ListOfConstraintIndices attributes:

function get(
+    ::SignBridge{T},
+    ::NumberOfConstraints{
+        ScalarAffineFunction{T},
+        GreaterThan{T},
+    },
+) where {T}
+    return 1
+end
+
+function get(
+    bridge::SignBridge{T},
+    ::ListOfConstraintIndices{
+        ScalarAffineFunction{T},
+        GreaterThan{T},
+    },
+) where {T}
+    return [bridge.constraint]
+end

You must implement one such pair of functions for each type of constraint the bridge adds to the model.

Warning

Avoid returning a list from the bridge object without copying it. Users must be able to change the contents of the returned list without altering the bridge object.

For variables, the situation is simpler. If your bridge creates new variables, you must implement the NumberOfVariables and ListOfVariableIndices attributes. However, these attributes do not have parameters, unlike their constraint counterparts. Only two functions suffice:

function get(
+    ::SignBridge{T},
+    ::NumberOfVariables,
+) where {T}
+    return 0
+end
+
+function get(
+    ::SignBridge{T},
+    ::ListOfVariableIndices,
+) where {T}
+    return VariableIndex[]
+end

In order for the user to be able to access the function and set of the original constraint, the bridge needs to implement getters for the ConstraintFunction and ConstraintSet attributes:

function get(
+    model::MOI.ModelLike,
+    attr::MOI.ConstraintFunction,
+    bridge::SignBridge,
+)
+    return -MOI.get(model, attr, bridge.constraint)
+end
+
+function get(
+    model::MOI.ModelLike,
+    attr::MOI.ConstraintSet,
+    bridge::SignBridge,
+)
+    set = MOI.get(model, attr, bridge.constraint)
+    return MOI.LessThan(-set.lower)
+end
Warning

Alternatively, one could store the original function and set in SignBridge during Bridges.Constraint.bridge_constraint to make these getters simpler and more efficient. On the other hand, this will increase the memory footprint of the bridges as the garbage collector won't be able to delete that object. The convention is to not store the function in the bridge and not care too much about the efficiency of these getters. If the user needs efficient getters for ConstraintFunction then they should use a Utilities.CachingOptimizer.

Model modifications

To avoid copying the model when the user request to change a constraint, MOI provides modify. Bridges can also implement this API to allow certain changes, such as coefficient changes.

In our case, a modification of a coefficient in the original constraint (for example, replacing the value of the coefficient of a variable in the affine function) must be transmitted to the constraint created by the bridge, but with a sign change.

function modify(
+    model::ModelLike,
+    bridge::SignBridge,
+    change::ScalarCoefficientChange,
+)
+    modify(
+        model,
+        bridge.constraint,
+        ScalarCoefficientChange(change.variable, -change.new_coefficient),
+    )
+    return
+end

Bridge deletion

When a bridge is deleted, the constraints it added must be deleted too.

function delete(model::ModelLike, bridge::SignBridge)
+    delete(model, bridge.constraint)
+    return
+end
diff --git a/previews/PR2274/tutorials/example/index.html b/previews/PR2274/tutorials/example/index.html new file mode 100644 index 0000000000..78040e13b2 --- /dev/null +++ b/previews/PR2274/tutorials/example/index.html @@ -0,0 +1,45 @@ + +Solving a problem using MathOptInterface · MathOptInterface

Solving a problem using MathOptInterface

In this tutorial we demonstrate how to use MathOptInterface to solve the binary-constrained knapsack problem:

\[\begin{aligned} +\max \; & c^\top x \\ +s.t. \; & w^\top x \le C \\ + & x_i \in \{0,1\},\quad \forall i=1,\ldots,n +\end{aligned}\]

Required packages

Load the MathOptInterface module and define the shorthand MOI:

import MathOptInterface as MOI

As an optimizer, we choose GLPK:

using GLPK
+optimizer = GLPK.Optimizer()

Define the data

We first define the constants of the problem:

julia> c = [1.0, 2.0, 3.0]
+3-element Vector{Float64}:
+ 1.0
+ 2.0
+ 3.0
+
+julia> w = [0.3, 0.5, 1.0]
+3-element Vector{Float64}:
+ 0.3
+ 0.5
+ 1.0
+
+julia> C = 3.2
+3.2

Add the variables

julia> x = MOI.add_variables(optimizer, length(c));

Set the objective

julia> MOI.set(
+           optimizer,
+           MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
+           MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(c, x), 0.0),
+       );
+
+julia> MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)
Tip

MOI.ScalarAffineTerm.(c, x) is a shortcut for [MOI.ScalarAffineTerm(c[i], x[i]) for i = 1:3]. This is Julia's broadcast syntax in action, and is used quite often throughout MOI.

Add the constraints

We add the knapsack constraint and integrality constraints:

julia> MOI.add_constraint(
+           optimizer,
+           MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(w, x), 0.0),
+           MOI.LessThan(C),
+       );

Add integrality constraints:

julia> for x_i in x
+           MOI.add_constraint(optimizer, x_i, MOI.ZeroOne())
+       end

Optimize the model

julia> MOI.optimize!(optimizer)

Understand why the solver stopped

The first thing to check after optimization is why the solver stopped, for example, did it stop because of a time limit or did it stop because it found the optimal solution?

julia> MOI.get(optimizer, MOI.TerminationStatus())
+OPTIMAL::TerminationStatusCode = 1

Looks like we found an optimal solution.

Understand what solution was returned

julia> MOI.get(optimizer, MOI.ResultCount())
+1
+
+julia> MOI.get(optimizer, MOI.PrimalStatus())
+FEASIBLE_POINT::ResultStatusCode = 1
+
+julia> MOI.get(optimizer, MOI.DualStatus())
+NO_SOLUTION::ResultStatusCode = 0

Query the objective

What is its objective value?

julia> MOI.get(optimizer, MOI.ObjectiveValue())
+6.0

Query the primal solution

And what is the value of the variables x?

julia> MOI.get(optimizer, MOI.VariablePrimal(), x)
+3-element Vector{Float64}:
+ 1.0
+ 1.0
+ 1.0
diff --git a/previews/PR2274/tutorials/implementing/index.html b/previews/PR2274/tutorials/implementing/index.html new file mode 100644 index 0000000000..1cf2be4004 --- /dev/null +++ b/previews/PR2274/tutorials/implementing/index.html @@ -0,0 +1,114 @@ + +Implementing a solver interface · MathOptInterface

Implementing a solver interface

This guide outlines the basic steps to implement an interface to MathOptInterface for a new solver.

Danger

Implementing an interface to MathOptInterface for a new solver is a lot of work. Before starting, we recommend that you join the Developer chatroom and explain a little bit about the solver you are wrapping. If you have questions that are not answered by this guide, please ask them in the Developer chatroom so we can improve this guide.

A note on the API

The API of MathOptInterface is large and varied. In order to support the diversity of solvers and use-cases, we make heavy use of duck-typing. That is, solvers are not expected to implement the full API, nor is there a well-defined minimal subset of what must be implemented. Instead, you should implement the API as necessary to make the solver function as you require.

The main reason for using duck-typing is that solvers work in different ways and target different use-cases.

For example:

  • Some solvers support incremental problem construction, support modification after a solve, and have native support for things like variable names.
  • Other solvers are "one-shot" solvers that require all of the problem data to construct and solve the problem in a single function call. They do not support modification or things like variable names.
  • Other "solvers" are not solvers at all, but things like file readers. These may only support functions like read_from_file, and may not even support the ability to add variables or constraints directly.
  • Finally, some "solvers" are layers which take a problem as input, transform it according to some rules, and pass the transformed problem to an inner solver.

Preliminaries

Before starting on your wrapper, you should do some background research and make the solver accessible via Julia.

Decide if MathOptInterface is right for you

The first step in writing a wrapper is to decide whether implementing an interface is the right thing to do.

MathOptInterface is an abstraction layer for unifying constrained mathematical optimization solvers. If your solver doesn't fit in the category, for example, it implements a derivative-free algorithm for unconstrained objective functions, MathOptInterface may not be the right tool for the job.

Tip

If you're not sure whether you should write an interface, ask in the Developer chatroom.

Find a similar solver already wrapped

The next step is to find (if possible) a similar solver that is already wrapped. Although not strictly necessary, this will be a good place to look for inspiration when implementing your wrapper.

The JuMP documentation has a good list of solvers, along with the problem classes they support.

Tip

If you're not sure which solver is most similar, ask in the Developer chatroom.

Create a low-level interface

Before writing a MathOptInterface wrapper, you first need to be able to call the solver from Julia.

Wrapping solvers written in Julia

If your solver is written in Julia, there's nothing to do here. Go to the next section.

Wrapping solvers written in C

Julia is well suited to wrapping solvers written in C.

Info

This is not true for C++. If you have a solver written in C++, first write a C interface, then wrap the C interface.

Before writing a MathOptInterface wrapper, there are a few extra steps.

Create a JLL

If the C code is publicly available under an open source license, create a JLL package via Yggdrasil. The easiest way to do this is to copy an existing solver. Good examples to follow are the COIN-OR solvers.

Warning

Building the solver via Yggdrasil is non-trivial. Please ask the Developer chatroom for help.

If the code is commercial or not publicly available, the user will need to manually install the solver. See Gurobi.jl or CPLEX.jl for examples of how to structure this.

Use Clang.jl to wrap the C API

The next step is to use Clang.jl to automatically wrap the C API. The easiest way to do this is to follow an example. Good examples to follow are Cbc.jl and HiGHS.jl.

Sometimes, you will need to make manual modifications to the resulting files.

Solvers written in other languages

Ask the Developer chatroom for advice. You may be able to use one of the JuliaInterop packages to call out to the solver.

For example, SeDuMi.jl uses MATLAB.jl to call the SeDuMi solver written in MATLAB.

Structuring the package

Structure your wrapper as a Julia package. Consult the Julia documentation if you haven't done this before.

MOI solver interfaces may be in the same package as the solver itself (either the C wrapper if the solver is accessible through C, or the Julia code if the solver is written in Julia, for example), or in a separate package which depends on the solver package.

Note

The JuMP core contributors request that you do not use "JuMP" in the name of your package without prior consent.

Your package should have the following structure:

/.github
+    /workflows
+        ci.yml
+        format_check.yml
+        TagBot.yml
+/gen
+    gen.jl  # Code to wrap the C API
+/src
+    NewSolver.jl
+    /gen
+        libnewsolver_api.jl
+        libnewsolver_common.jl
+    /MOI_wrapper
+        MOI_wrapper.jl
+        other_files.jl
+/test
+    runtests.jl
+    /MOI_wrapper
+        MOI_wrapper.jl
+.gitignore
+.JuliaFormatter.toml
+README.md
+LICENSE.md
+Project.toml
  • The /.github folder contains the scripts for GitHub actions. The easiest way to write these is to copy the ones from an existing solver.
  • The /gen and /src/gen folders are only needed if you are wrapping a solver written in C.
  • The /src/MOI_wrapper folder contains the Julia code for the MOI wrapper.
  • The /test folder contains code for testing your package. See Setup tests for more information.
  • The .JuliaFormatter.toml and .github/workflows/format_check.yml enforce code formatting using JuliaFormatter.jl. Check existing solvers or JuMP.jl for details.

Documentation

Your package must include documentation explaining how to use the package. The easiest approach is to include documentation in your README.md. A more involved option is to use Documenter.jl.

Examples of packages with README-based documentation include:

Examples of packages with Documenter-based documentation include:

Setup tests

The best way to implement an interface to MathOptInterface is via test-driven development.

The MOI.Test submodule contains a large test suite to help check that you have implemented things correctly.

Follow the guide How to test a solver to set up the tests for your package.

Tip

Run the tests frequently when developing. However, at the start there is going to be a lot of errors. Start by excluding large classes of tests (for example, exclude = ["test_basic_", "test_model_"], implement any missing methods until the tests pass, then remove an exclusion and repeat.

Initial code

By this point, you should have a package setup with tests, formatting, and access to the underlying solver. Now it's time to start writing the wrapper.

The Optimizer object

The first object to create is a subtype of AbstractOptimizer. This type is going to store everything related to the problem.

By convention, these optimizers should not be exported and should be named PackageName.Optimizer.

import MathOptInterface as MOI
+
+struct Optimizer <: MOI.AbstractOptimizer
+    # Fields go here
+end

Optimizer objects for C solvers

Warning

This section is important if you wrap a solver written in C.

Wrapping a solver written in C will require the use of pointers, and for you to manually free the solver's memory when the Optimizer is garbage collected by Julia.

Never pass a pointer directly to a Julia ccall function.

Instead, store the pointer as a field in your Optimizer, and implement Base.cconvert and Base.unsafe_convert. Then you can pass Optimizer to any ccall function that expects the pointer.

In addition, make sure you implement a finalizer for each model you create.

If newsolver_createProblem() is the low-level function that creates the problem pointer in C, and newsolver_freeProblem(::Ptr{Cvoid}) is the low-level function that frees memory associated with the pointer, your Optimizer() function should look like this:

struct Optimizer <: MOI.AbstractOptimizer
+    ptr::Ptr{Cvoid}
+
+    function Optimizer()
+        ptr = newsolver_createProblem()
+        model = Optimizer(ptr)
+        finalizer(model) do m
+            newsolver_freeProblem(m)
+            return
+        end
+        return model
+    end
+end
+
+Base.cconvert(::Type{Ptr{Cvoid}}, model::Optimizer) = model
+Base.unsafe_convert(::Type{Ptr{Cvoid}}, model::Optimizer) = model.ptr

Implement methods for Optimizer

All Optimizers must implement the following methods:

Other methods, detailed below, are optional or depend on how you implement the interface.

Tip

For this and all future methods, read the docstrings to understand what each method does, what it expects as input, and what it produces as output. If it isn't clear, let us know and we will improve the docstrings. It is also very helpful to look at an existing wrapper for a similar solver.

You should also implement Base.show(::IO, ::Optimizer) to print a nice string when someone prints your model. For example

function Base.show(io::IO, model::Optimizer)
+    return print(io, "NewSolver with the pointer $(model.ptr)")
+end

Implement attributes

MathOptInterface uses attributes to manage different aspects of the problem.

For each attribute

  • get gets the current value of the attribute
  • set sets a new value of the attribute. Not all attributes can be set. For example, the user can't modify the SolverName.
  • supports returns a Bool indicating whether the solver supports the attribute.
Info

Use attribute_value_type to check the value expected by a given attribute. You should make sure that your get function correctly infers to this type (or a subtype of it).

Each column in the table indicates whether you need to implement the particular method for each attribute.

Attributegetsetsupports
SolverNameYesNoNo
SolverVersionYesNoNo
RawSolverYesNoNo
NameYesYesYes
SilentYesYesYes
TimeLimitSecYesYesYes
ObjectiveLimitYesYesYes
RawOptimizerAttributeYesYesYes
NumberOfThreadsYesYesYes
AbsoluteGapToleranceYesYesYes
RelativeGapToleranceYesYesYes

For example:

function MOI.get(model::Optimizer, ::MOI.Silent)
+    return # true if MOI.Silent is set
+end
+
+function MOI.set(model::Optimizer, ::MOI.Silent, v::Bool)
+    if v
+        # Set a parameter to turn off printing
+    else
+        # Restore the default printing
+    end
+    return
+end
+
+MOI.supports(::Optimizer, ::MOI.Silent) = true

Define supports_constraint

The next step is to define which constraints and objective functions you plan to support.

For each function-set constraint pair, define supports_constraint:

function MOI.supports_constraint(
+    ::Optimizer,
+    ::Type{MOI.VariableIndex},
+    ::Type{MOI.ZeroOne},
+)
+    return true
+end

To make this easier, you may want to use Unions:

function MOI.supports_constraint(
+    ::Optimizer,
+    ::Type{MOI.VariableIndex},
+    ::Type{<:Union{MOI.LessThan,MOI.GreaterThan,MOI.EqualTo}},
+)
+    return true
+end
Tip

Only support a constraint if your solver has native support for it.

The big decision: incremental modification?

Now you need to decide whether to support incremental modification or not.

Incremental modification means that the user can add variables and constraints one-by-one without needing to rebuild the entire problem, and they can modify the problem data after an optimize! call. Supporting incremental modification means implementing functions like add_variable and add_constraint.

The alternative is to accept the problem data in a single optimize! or copy_to function call. Because these functions see all of the data at once, it can typically call a more efficient function to load data into the underlying solver.

Good examples of solvers supporting incremental modification are MILP solvers like GLPK.jl and Gurobi.jl. Examples of non-incremental solvers are AmplNLWriter.jl and SCS.jl

It is possible for a solver to implement both approaches, but you should probably start with one for simplicity.

Tip

Only support incremental modification if your solver has native support for it.

In general, supporting incremental modification is more work, and it usually requires some extra book-keeping. However, it provides a more efficient interface to the solver if the problem is going to be resolved multiple times with small modifications. Moreover, once you've implemented incremental modification, it's usually not much extra work to add a copy_to interface. The converse is not true.

Tip

If this is your first time writing an interface, start with the one-shot optimize!.

The non-incremental interface

There are two ways to implement the non-incremental interface. The first uses a two-argument version of optimize!, the second implements copy_to followed by the one-argument version of optimize!.

If your solver does not support modification, and requires all data to solve the problem in a single function call, you should implement the "one-shot" optimize!.

If your solver separates data loading and the actual optimization into separate steps, implement the copy_to interface.

The incremental interface

Warning

Writing this interface is a lot of work. The easiest way is to consult the source code of a similar solver.

To implement the incremental interface, implement the following functions:

Info

Solvers do not have to support AbstractScalarFunction in GreaterThan, LessThan, EqualTo, or Interval with a nonzero constant in the function. Throw ScalarFunctionConstantNotZero if the function constant is not zero.

In addition, you should implement the following model attributes:

Attributegetsetsupports
ListOfModelAttributesSetYesNoNo
ObjectiveFunctionTypeYesNoNo
ObjectiveFunctionYesYesYes
ObjectiveSenseYesYesYes
NameYesYesYes

Variable-related attributes:

Attributegetsetsupports
ListOfVariableAttributesSetYesNoNo
NumberOfVariablesYesNoNo
ListOfVariableIndicesYesNoNo

Constraint-related attributes:

Attributegetsetsupports
ListOfConstraintAttributesSetYesNoNo
NumberOfConstraintsYesNoNo
ListOfConstraintTypesPresentYesNoNo
ConstraintFunctionYesYesNo
ConstraintSetYesYesNo

Modifications

If your solver supports modifying data in-place, implement modify for the following AbstractModifications:

Variables constrained on creation

Some solvers require variables be associated with a set when they are created. This conflicts with the incremental modification approach, since you cannot first add a free variable and then constrain it to the set.

If this is the case, implement:

By default, MathOptInterface assumes solvers support free variables. If your solver does not support free variables, define:

MOI.supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false

Incremental and copy_to

If you implement the incremental interface, you have the option of also implementing copy_to.

If you don't want to implement copy_to, for example, because the solver has no API for building the problem in a single function call, define the following fallback:

MOI.supports_incremental_interface(::Optimizer) = true
+
+function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
+    return MOI.Utilities.default_copy_to(dest, src)
+end

Names

Regardless of which interface you implement, you have the option of implementing the Name attribute for variables and constraints:

Attributegetsetsupports
VariableNameYesYesYes
ConstraintNameYesYesYes

If you implement names, you must also implement the following three methods:

function MOI.get(model::Optimizer, ::Type{MOI.VariableIndex}, name::String)
+    return # The variable named `name`.
+end
+
+function MOI.get(model::Optimizer, ::Type{MOI.ConstraintIndex}, name::String)
+    return # The constraint any type named `name`.
+end
+
+function MOI.get(
+    model::Optimizer,
+    ::Type{MOI.ConstraintIndex{F,S}},
+    name::String,
+) where {F,S}
+    return # The constraint of type F-in-S named `name`.
+end

These methods have the following rules:

  • If there is no variable or constraint with the name, return nothing
  • If there is a single variable or constraint with that name, return the variable or constraint
  • If there are multiple variables or constraints with the name, throw an error.
Warning

You should not implement ConstraintName for VariableIndex constraints. If you implement ConstraintName for other constraints, you can add the following two methods to disable ConstraintName for VariableIndex constraints.

function MOI.supports(
+    ::Optimizer,
+    ::MOI.ConstraintName,
+    ::Type{<:MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.AbstractScalarSet}},
+)
+    return throw(MOI.VariableIndexConstraintNameError())
+end
+function MOI.set(
+    ::Optimizer,
+    ::MOI.ConstraintName,
+    ::MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.AbstractScalarSet},
+    ::String,
+)
+    return throw(MOI.VariableIndexConstraintNameError())
+end

Solutions

Implement optimize! to solve the model:

All Optimizers must implement the following attributes:

Info

You only need to implement get for solution attributes. Don't implement set or supports.

Note

Solver wrappers should document how the low-level statuses map to the MOI statuses. Statuses like NEARLY_FEASIBLE_POINT and INFEASIBLE_POINT, are designed to be used when the solver explicitly indicates that relaxed tolerances are satisfied or the returned point is infeasible, respectively.

You should also implement the following attributes:

Tip

Attributes like VariablePrimal and ObjectiveValue are indexed by the result count. Use MOI.check_result_index_bounds(model, attr) to throw an error if the attribute is not available.

If your solver returns dual solutions, implement:

For integer solvers, implement:

If applicable, implement:

If your solver uses the Simplex method, implement:

If your solver accepts primal or dual warm-starts, implement:

Other tips

Here are some other points to be aware of when writing your wrapper.

Unsupported constraints at runtime

In some cases, your solver may support a particular type of constraint (for example, quadratic constraints), but only if the data meets some condition (for example, it is convex).

In this case, declare that you support the constraint, and throw AddConstraintNotAllowed.

Dealing with multiple variable bounds

MathOptInterface uses VariableIndex constraints to represent variable bounds. Defining multiple variable bounds on a single variable is not allowed.

Throw LowerBoundAlreadySet or UpperBoundAlreadySet if the user adds a constraint that results in multiple bounds.

Only throw if the constraints conflict. It is okay to add VariableIndex-in-GreaterThan and then VariableIndex-in-LessThan, but not VariableIndex-in-Interval and then VariableIndex-in-LessThan,

Expect duplicate coefficients

Solvers must expect that functions such as ScalarAffineFunction and VectorQuadraticFunction may contain duplicate coefficients.

For example, ScalarAffineFunction([ScalarAffineTerm(x, 1), ScalarAffineTerm(x, 1)], 0.0).

Use Utilities.canonical to return a new function with the duplicate coefficients aggregated together.

Don't modify user-data

All data passed to the solver must be copied immediately to internal data structures. Solvers may not modify any input vectors and must assume that input vectors will not be modified by users in the future.

This applies, for example, to the terms vector in ScalarAffineFunction. Vectors returned to the user, for example, via ObjectiveFunction or ConstraintFunction attributes, must not be modified by the solver afterwards. The in-place version of get! can be used by users to avoid extra copies in this case.

Column Generation

There is no special interface for column generation. If the solver has a special API for setting coefficients in existing constraints when adding a new variable, it is possible to queue modifications and new variables and then call the solver's API once all of the new coefficients are known.

Solver-specific attributes

You don't need to restrict yourself to the attributes defined in the MathOptInterface.jl package.

Solver-specific attributes should be specified by creating an appropriate subtype of AbstractModelAttribute, AbstractOptimizerAttribute, AbstractVariableAttribute, or AbstractConstraintAttribute.

For example, Gurobi.jl adds attributes for multiobjective optimization by defining:

struct NumberOfObjectives <: MOI.AbstractModelAttribute end
+
+function MOI.set(model::Optimizer, ::NumberOfObjectives, n::Integer)
+    # Code to set NumberOfObjectives
+    return
+end
+
+function MOI.get(model::Optimizer, ::NumberOfObjectives)
+    n = # Code to get NumberOfObjectives
+    return n
+end

Then, the user can write:

model = Gurobi.Optimizer()
+MOI.set(model, Gurobi.NumberofObjectives(), 3)
diff --git a/previews/PR2274/tutorials/latency/index.html b/previews/PR2274/tutorials/latency/index.html new file mode 100644 index 0000000000..77f8f0c53d --- /dev/null +++ b/previews/PR2274/tutorials/latency/index.html @@ -0,0 +1,129 @@ + +Latency · MathOptInterface

Latency

MathOptInterface suffers the "time-to-first-solve" problem of start-up latency.

This hurts both the user- and developer-experience of MathOptInterface. In the first case, because simple models have a multi-second delay before solving, and in the latter, because our tests take so long to run.

This page contains some advice on profiling and fixing latency-related problems in the MathOptInterface.jl repository.

Background

Before reading this part of the documentation, you should familiarize yourself with the reasons for latency in Julia and how to fix them.

Causes

There are three main causes of latency in MathOptInterface:

  1. A large number of types
  2. Lack of method ownership
  3. Type-instability in the bridge layer

A large number of types

Julia is very good at specializing method calls based on the input type. Each specialization has a compilation cost, but the benefit of faster run-time performance.

The best-case scenario is for a method to be called a large number of times with a single set of argument types. The worst-case scenario is for a method to be called a single time for a large set of argument types.

Because of MathOptInterface's function-in-set formulation, we fall into the worst-case situation.

This is a fundamental limitation of Julia, so there isn't much we can do about it. However, if we can precompile MathOptInterface, much of the cost can be shifted from start-up latency to the time it takes to precompile a package on installation.

However, there are two things which make MathOptInterface hard to precompile.

Lack of method ownership

Lack of method ownership happens when a call is made using a mix of structs and methods from different modules. Because of this, no single module "owns" the method that is being dispatched, and so it cannot be precompiled.

Tip

This is a slightly simplified explanation. Read the precompilation tutorial for a more in-depth discussion on back-edges.

Unfortunately, the design of MOI means that this is a frequent occurrence: we have a bunch of types in MOI.Utilities that wrap types defined in external packages (for example, the Optimizers), which implement methods of functions defined in MOI (for example, add_variable, add_constraint).

Here's a simple example of method-ownership in practice:

module MyMOI
+struct Wrapper{T}
+    inner::T
+end
+optimize!(x::Wrapper) = optimize!(x.inner)
+end  # MyMOI
+
+module MyOptimizer
+using ..MyMOI
+struct Optimizer end
+MyMOI.optimize!(x::Optimizer) = 1
+end  # MyOptimizer
+
+using SnoopCompile
+model = MyMOI.Wrapper(MyOptimizer.Optimizer())
+
+julia> tinf = @snoopi_deep MyMOI.optimize!(model)
+InferenceTimingNode: 0.008256/0.008543 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 1 direct children

The result is that there was one method that required type inference. If we visualize tinf:

using ProfileView
+ProfileView.view(flamegraph(tinf))

we see a flamegraph with a large red-bar indicating that the method MyMOI.optimize(MyMOI.Wrapper{MyOptimizer.Optimizer}) cannot be precompiled.

To fix this, we need to designate a module to "own" that method (that is, create a back-edge). The easiest way to do this is for MyOptimizer to call MyMOI.optimize(MyMOI.Wrapper{MyOptimizer.Optimizer}) during using MyOptimizer. Let's see that in practice:

module MyMOI
+struct Wrapper{T}
+    inner::T
+end
+optimize(x::Wrapper) = optimize(x.inner)
+end  # MyMOI
+
+module MyOptimizer
+using ..MyMOI
+struct Optimizer end
+MyMOI.optimize(x::Optimizer) = 1
+# The syntax of this let-while loop is very particular:
+#  * `let ... end` keeps everything local to avoid polluting the MyOptimizer
+#    namespace
+#  * `while true ... break end` runs the code once, and forces Julia to compile
+#    the inner loop, rather than interpret it.
+let
+    while true
+        model = MyMOI.Wrapper(Optimizer())
+        MyMOI.optimize(model)
+        break
+    end
+end
+end  # MyOptimizer
+
+using SnoopCompile
+model = MyMOI.Wrapper(MyOptimizer.Optimizer())
+
+julia> tinf = @snoopi_deep MyMOI.optimize(model)
+InferenceTimingNode: 0.006822/0.006822 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 0 direct children

There are now 0 direct children that required type inference because the method was already stored in MyOptimizer!

Unfortunately, this trick only works if the call-chain is fully inferrable. If there are breaks (due to type instability), then the benefit of doing this is reduced. And unfortunately for us, the design of MathOptInterface has a lot of type instabilities.

Type instability in the bridge layer

Most of MathOptInterface is pretty good at ensuring type-stability. However, a key component is not type stable, and that is the bridging layer.

In particular, the bridging layer defines Bridges.LazyBridgeOptimizer, which has fields like:

struct LazyBridgeOptimizer
+    constraint_bridge_types::Vector{Any}
+    constraint_node::Dict{Tuple{Type,Type},ConstraintNode}
+    constraint_types::Vector{Tuple{Type,Type}}
+end

This is because the LazyBridgeOptimizer needs to be able to deal with any function-in-set type passed to it, and we also allow users to pass additional bridges that they defined in external packages.

So to recap, MathOptInterface suffers package latency because:

  1. there are a large number of types and functions
  2. and these are split between multiple modules, including external packages
  3. and there are type-instabilities like those in the bridging layer.

Resolutions

There are no magic solutions to reduce latency. Issue #1313 tracks progress on reducing latency in MathOptInterface.

A useful script is the following (replace GLPK as needed):

import GLPK
+import MathOptInterface as MOI
+
+function example_diet(optimizer, bridge)
+    category_data = [
+        1800.0 2200.0;
+          91.0    Inf;
+           0.0   65.0;
+           0.0 1779.0
+    ]
+    cost = [2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59]
+    food_data = [
+        410 24 26 730;
+        420 32 10 1190;
+        560 20 32 1800;
+        380  4 19 270;
+        320 12 10 930;
+        320 15 12 820;
+        320 31 12 1230;
+        100  8 2.5 125;
+        330  8 10 180
+    ]
+    bridge_model = if bridge
+        MOI.instantiate(optimizer; with_bridge_type=Float64)
+    else
+        MOI.instantiate(optimizer)
+    end
+    model = MOI.Utilities.CachingOptimizer(
+        MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
+        MOI.Utilities.AUTOMATIC,
+    )
+    MOI.Utilities.reset_optimizer(model, bridge_model)
+    MOI.set(model, MOI.Silent(), true)
+    nutrition = MOI.add_variables(model, size(category_data, 1))
+    for (i, v) in enumerate(nutrition)
+        MOI.add_constraint(model, v, MOI.GreaterThan(category_data[i, 1]))
+        MOI.add_constraint(model, v, MOI.LessThan(category_data[i, 2]))
+    end
+    buy = MOI.add_variables(model, size(food_data, 1))
+    MOI.add_constraint.(model, buy, MOI.GreaterThan(0.0))
+    MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
+    f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(cost, buy), 0.0)
+    MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
+    for (j, n) in enumerate(nutrition)
+        f = MOI.ScalarAffineFunction(
+            MOI.ScalarAffineTerm.(food_data[:, j], buy),
+            0.0,
+        )
+        push!(f.terms, MOI.ScalarAffineTerm(-1.0, n))
+        MOI.add_constraint(model, f, MOI.EqualTo(0.0))
+    end
+    MOI.optimize!(model)
+    term_status = MOI.get(model, MOI.TerminationStatus())
+    @assert term_status == MOI.OPTIMAL
+    MOI.add_constraint(
+        model,
+        MOI.ScalarAffineFunction(
+            MOI.ScalarAffineTerm.(1.0, [buy[end-1], buy[end]]),
+            0.0,
+        ),
+        MOI.LessThan(6.0),
+    )
+    MOI.optimize!(model)
+    @assert MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
+    return
+end
+
+if length(ARGS) > 0
+    bridge = get(ARGS, 2, "") != "--no-bridge"
+    println("Running: $(ARGS[1]) $(get(ARGS, 2, ""))")
+    @time example_diet(GLPK.Optimizer, bridge)
+    @time example_diet(GLPK.Optimizer, bridge)
+    exit(0)
+end

You can create a flame-graph via

using SnoopComile
+tinf = @snoopi_deep example_diet(GLPK.Optimizer, true)
+using ProfileView
+ProfileView.view(flamegraph(tinf))

Here's how things looked in mid-August 2021: flamegraph

There are a few opportunities for improvement (non-red flames, particularly on the right). But the main problem is a large red (non-precompilable due to method ownership) flame.

diff --git a/previews/PR2274/tutorials/manipulating_expressions/index.html b/previews/PR2274/tutorials/manipulating_expressions/index.html new file mode 100644 index 0000000000..6d43e98c6c --- /dev/null +++ b/previews/PR2274/tutorials/manipulating_expressions/index.html @@ -0,0 +1,22 @@ + +Manipulating expressions · MathOptInterface

Manipulating expressions

This guide highlights a syntactically appealing way to build expressions at the MOI level, but also to look at their contents. It may be especially useful when writing models or bridge code.

Creating functions

This section details the ways to create functions with MathOptInterface.

Creating scalar affine functions

The simplest scalar function is simply a variable:

julia> x = MOI.add_variable(model) # Create the variable x
+MOI.VariableIndex(1)

This type of function is extremely simple; to express more complex functions, other types must be used. For instance, a ScalarAffineFunction is a sum of linear terms (a factor times a variable) and a constant. Such an object can be built using the standard constructor:

julia> f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1, x)], 2) # x + 2
+(2) + (1) MOI.VariableIndex(1)

However, you can also use operators to build the same scalar function:

julia> f = x + 2
+(2) + (1) MOI.VariableIndex(1)

Creating scalar quadratic functions

Scalar quadratic functions are stored in ScalarQuadraticFunction objects, in a way that is highly similar to scalar affine functions. You can obtain a quadratic function as a product of affine functions:

julia> 1 * x * x
+(0) + 1.0 MOI.VariableIndex(1)²
+
+julia> f * f  # (x + 2)²
+(4) + (2) MOI.VariableIndex(1) + (2) MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²
+
+julia> f^2  # (x + 2)² too
+(4) + (2) MOI.VariableIndex(1) + (2) MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²

Creating vector functions

A vector function is a function with several values, irrespective of the number of input variables. Similarly to scalar functions, there are three main types of vector functions: VectorOfVariables, VectorAffineFunction, and VectorQuadraticFunction.

The easiest way to create a vector function is to stack several scalar functions using Utilities.vectorize. It takes a vector as input, and the generated vector function (of the most appropriate type) has each dimension corresponding to a dimension of the vector.

julia> g = MOI.Utilities.vectorize([f, 2 * f])
+┌                              ┐
+│(2) + (1) MOI.VariableIndex(1)│
+│(4) + (2) MOI.VariableIndex(1)│
+└                              ┘
Warning

Utilities.vectorize only takes a vector of similar scalar functions: you cannot mix VariableIndex and ScalarAffineFunction, for instance. In practice, it means that Utilities.vectorize([x, f]) does not work; you should rather use Utilities.vectorize([1 * x, f]) instead to only have ScalarAffineFunction objects.

Canonicalizing functions

In more advanced use cases, you might need to ensure that a function is "canonical." Functions are stored as an array of terms, but there is no check that these terms are redundant: a ScalarAffineFunction object might have two terms with the same variable, like x + x + 1. These terms could be merged without changing the semantics of the function: 2x + 1.

Working with these objects might be cumbersome. Canonicalization helps maintain redundancy to zero.

Utilities.is_canonical checks whether a function is already in its canonical form:

julia> MOI.Utilities.is_canonical(f + f) # (x + 2) + (x + 2) is stored as x + x + 4
+false

Utilities.canonical returns the equivalent canonical version of the function:

julia> MOI.Utilities.canonical(f + f) # Returns 2x + 4
+(4) + (2) MOI.VariableIndex(1)

Exploring functions

At some point, you might need to dig into a function, for instance to map it into solver constructs.

Vector functions

Utilities.scalarize returns a vector of scalar functions from a vector function:

julia> MOI.Utilities.scalarize(g) # Returns a vector [f, 2 * f].
+2-element Vector{MathOptInterface.ScalarAffineFunction{Int64}}:
+ (2) + (1) MOI.VariableIndex(1)
+ (4) + (2) MOI.VariableIndex(1)
Note

Utilities.eachscalar returns an iterator on the dimensions, which serves the same purpose as Utilities.scalarize.

output_dimension returns the number of dimensions of the output of a function:

julia> MOI.output_dimension(g)
+2
diff --git a/previews/PR2274/tutorials/mathprogbase/index.html b/previews/PR2274/tutorials/mathprogbase/index.html new file mode 100644 index 0000000000..84500bad2c --- /dev/null +++ b/previews/PR2274/tutorials/mathprogbase/index.html @@ -0,0 +1,54 @@ + +Transitioning from MathProgBase · MathOptInterface

Transitioning from MathProgBase

MathOptInterface is a replacement for MathProgBase.jl. However, it is not a direct replacement.

Transitioning a solver interface

MathOptInterface is more extensive than MathProgBase which may make its implementation seem daunting at first. There are however numerous utilities in MathOptInterface that the simplify implementation process.

For more information, read Implementing a solver interface.

Transitioning the high-level functions

MathOptInterface doesn't provide replacements for the high-level interfaces in MathProgBase. We recommend you use JuMP as a modeling interface instead.

Tip

If you haven't used JuMP before, start with the tutorial Getting started with JuMP

linprog

Here is one way of transitioning from linprog:

using JuMP
+
+function linprog(c, A, sense, b, l, u, solver)
+    N = length(c)
+    model = Model(solver)
+    @variable(model, l[i] <= x[i=1:N] <= u[i])
+    @objective(model, Min, c' * x)
+    eq_rows, ge_rows, le_rows = sense .== '=', sense .== '>', sense .== '<'
+    @constraint(model, A[eq_rows, :] * x .== b[eq_rows])
+    @constraint(model, A[ge_rows, :] * x .>= b[ge_rows])
+    @constraint(model, A[le_rows, :] * x .<= b[le_rows])
+    optimize!(model)
+    return (
+        status = termination_status(model),
+        objval = objective_value(model),
+        sol = value.(x)
+    )
+end

mixintprog

Here is one way of transitioning from mixintprog:

using JuMP
+
+function mixintprog(c, A, rowlb, rowub, vartypes, lb, ub, solver)
+    N = length(c)
+    model = Model(solver)
+    @variable(model, lb[i] <= x[i=1:N] <= ub[i])
+    for i in 1:N
+        if vartypes[i] == :Bin
+            set_binary(x[i])
+        elseif vartypes[i] == :Int
+            set_integer(x[i])
+        end
+    end
+    @objective(model, Min, c' * x)
+    @constraint(model, rowlb .<= A * x .<= rowub)
+    optimize!(model)
+    return (
+        status = termination_status(model),
+        objval = objective_value(model),
+        sol = value.(x)
+    )
+end

quadprog

Here is one way of transitioning from quadprog:

using JuMP
+
+function quadprog(c, Q, A, rowlb, rowub, lb, ub, solver)
+    N = length(c)
+    model = Model(solver)
+    @variable(model, lb[i] <= x[i=1:N] <= ub[i])
+    @objective(model, Min, c' * x + 0.5 * x' * Q * x)
+    @constraint(model, rowlb .<= A * x .<= rowub)
+    optimize!(model)
+    return (
+        status = termination_status(model),
+        objval = objective_value(model),
+        sol = value.(x)
+    )
+end