From 401ffc8904a57b5af0f0efc4651c5caa26a98402 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Wed, 7 Feb 2024 03:32:24 +0000 Subject: [PATCH] build based on ff2f3cd --- previews/PR2422/.documenter-siteinfo.json | 1 + previews/PR2422/MathOptInterface.pdf | Bin 0 -> 1282600 bytes previews/PR2422/assets/documenter.js | 898 ++++++++++++++++ previews/PR2422/assets/latency.png | Bin 0 -> 25175 bytes .../PR2422/assets/themes/documenter-dark.css | 7 + .../PR2422/assets/themes/documenter-light.css | 9 + previews/PR2422/assets/themeswap.js | 84 ++ previews/PR2422/assets/warner.js | 52 + previews/PR2422/background/duality/index.html | 80 ++ .../infeasibility_certificates/index.html | 28 + .../PR2422/background/motivation/index.html | 2 + .../background/naming_conventions/index.html | 2 + previews/PR2422/changelog/index.html | 30 + .../PR2422/developer/checklists/index.html | 112 ++ previews/PR2422/index.html | 9 + previews/PR2422/manual/constraints/index.html | 22 + previews/PR2422/manual/models/index.html | 2 + .../PR2422/manual/modification/index.html | 151 +++ previews/PR2422/manual/solutions/index.html | 35 + .../PR2422/manual/standard_form/index.html | 6 + previews/PR2422/manual/variables/index.html | 13 + .../PR2422/reference/callbacks/index.html | 32 + .../PR2422/reference/constraints/index.html | 12 + previews/PR2422/reference/errors/index.html | 48 + previews/PR2422/reference/models/index.html | 132 +++ .../PR2422/reference/modification/index.html | 31 + .../PR2422/reference/nonlinear/index.html | 78 ++ .../PR2422/reference/standard_form/index.html | 992 ++++++++++++++++++ .../PR2422/reference/variables/index.html | 24 + previews/PR2422/release_notes/index.html | 30 + previews/PR2422/search_index.js | 3 + previews/PR2422/siteinfo.js | 1 + .../submodules/Benchmarks/overview/index.html | 20 + .../Benchmarks/reference/index.html | 17 + .../Bridges/implementation/index.html | 32 + .../Bridges/list_of_bridges/index.html | 114 ++ .../submodules/Bridges/overview/index.html | 53 + .../submodules/Bridges/reference/index.html | 226 ++++ .../FileFormats/overview/index.html | 147 +++ .../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 | 52 + .../submodules/Utilities/overview/index.html | 250 +++++ .../submodules/Utilities/reference/index.html | 296 ++++++ .../tutorials/bridging_constraint/index.html | 102 ++ previews/PR2422/tutorials/example/index.html | 45 + .../PR2422/tutorials/implementing/index.html | 114 ++ previews/PR2422/tutorials/latency/index.html | 129 +++ .../manipulating_expressions/index.html | 22 + .../PR2422/tutorials/mathprogbase/index.html | 54 + 52 files changed, 5113 insertions(+) create mode 100644 previews/PR2422/.documenter-siteinfo.json create mode 100644 previews/PR2422/MathOptInterface.pdf create mode 100644 previews/PR2422/assets/documenter.js create mode 100644 previews/PR2422/assets/latency.png create mode 100644 previews/PR2422/assets/themes/documenter-dark.css create mode 100644 previews/PR2422/assets/themes/documenter-light.css create mode 100644 previews/PR2422/assets/themeswap.js create mode 100644 previews/PR2422/assets/warner.js create mode 100644 previews/PR2422/background/duality/index.html create mode 100644 previews/PR2422/background/infeasibility_certificates/index.html create mode 100644 previews/PR2422/background/motivation/index.html create mode 100644 previews/PR2422/background/naming_conventions/index.html create mode 100644 previews/PR2422/changelog/index.html create mode 100644 previews/PR2422/developer/checklists/index.html create mode 100644 previews/PR2422/index.html create mode 100644 previews/PR2422/manual/constraints/index.html create mode 100644 previews/PR2422/manual/models/index.html create mode 100644 previews/PR2422/manual/modification/index.html create mode 100644 previews/PR2422/manual/solutions/index.html create mode 100644 previews/PR2422/manual/standard_form/index.html create mode 100644 previews/PR2422/manual/variables/index.html create mode 100644 previews/PR2422/reference/callbacks/index.html create mode 100644 previews/PR2422/reference/constraints/index.html create mode 100644 previews/PR2422/reference/errors/index.html create mode 100644 previews/PR2422/reference/models/index.html create mode 100644 previews/PR2422/reference/modification/index.html create mode 100644 previews/PR2422/reference/nonlinear/index.html create mode 100644 previews/PR2422/reference/standard_form/index.html create mode 100644 previews/PR2422/reference/variables/index.html create mode 100644 previews/PR2422/release_notes/index.html create mode 100644 previews/PR2422/search_index.js create mode 100644 previews/PR2422/siteinfo.js create mode 100644 previews/PR2422/submodules/Benchmarks/overview/index.html create mode 100644 previews/PR2422/submodules/Benchmarks/reference/index.html create mode 100644 previews/PR2422/submodules/Bridges/implementation/index.html create mode 100644 previews/PR2422/submodules/Bridges/list_of_bridges/index.html create mode 100644 previews/PR2422/submodules/Bridges/overview/index.html create mode 100644 previews/PR2422/submodules/Bridges/reference/index.html create mode 100644 previews/PR2422/submodules/FileFormats/overview/index.html create mode 100644 previews/PR2422/submodules/FileFormats/reference/index.html create mode 100644 previews/PR2422/submodules/Nonlinear/overview/index.html create mode 100644 previews/PR2422/submodules/Nonlinear/reference/index.html create mode 100644 previews/PR2422/submodules/Test/overview/index.html create mode 100644 previews/PR2422/submodules/Test/reference/index.html create mode 100644 previews/PR2422/submodules/Utilities/overview/index.html create mode 100644 previews/PR2422/submodules/Utilities/reference/index.html create mode 100644 previews/PR2422/tutorials/bridging_constraint/index.html create mode 100644 previews/PR2422/tutorials/example/index.html create mode 100644 previews/PR2422/tutorials/implementing/index.html create mode 100644 previews/PR2422/tutorials/latency/index.html create mode 100644 previews/PR2422/tutorials/manipulating_expressions/index.html create mode 100644 previews/PR2422/tutorials/mathprogbase/index.html diff --git a/previews/PR2422/.documenter-siteinfo.json b/previews/PR2422/.documenter-siteinfo.json new file mode 100644 index 0000000000..80d96eb426 --- /dev/null +++ b/previews/PR2422/.documenter-siteinfo.json @@ -0,0 +1 @@ +{"documenter":{"julia_version":"1.9.4","generation_timestamp":"2024-02-07T03:26:04","documenter_version":"1.2.1"}} \ No newline at end of file diff --git a/previews/PR2422/MathOptInterface.pdf b/previews/PR2422/MathOptInterface.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e68ae32143fc28e8d89f09cf98aee9c3aeff9470 GIT binary patch literal 1282600 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�ZNDVVR2b% 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¥afViDJ4Tn7qOWL7Gtl&342cWDqETu;j4%lCm1F_ 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 z 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

}OKN_nL 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

`?>iO~BXp1rRO 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�XrdE!W5_k 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

{U7uYh{{s*^QA7(krbDCzS;Wz%yw+ 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

N<-qRXEYimiqbYdM^Y9iDS9@k~1 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

  • bDYNvag79c+7m1|a9phN=gmhG4jw=g( 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

    A|*&@f(4I%uJi5`(ubQ!krAwh2s|>gLSKqv9{J$ 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

    dlN* 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�|one#@-g?uYJsd3Xni`k8g$oC6CG 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

    $qS|m9|2bO+~xRpT*L@itaNU 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

    TM$-#CV1-Dz(+d@ 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 { + 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"; + + debounce(() => { + 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); + }); +}); + +function debounce(callback, timeout = 300) { + if (Date.now() - timer > timeout) { + callback(); + } + + clearTimeout(timer); + + timer = Date.now(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +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/PR2422/assets/latency.png b/previews/PR2422/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;overflow:auto}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;overflow-x:hidden}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}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 .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 !important;background-color:#f1f5f9 !important}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:whitesmoke;background-color:#33415580;border-radius:0.6rem}html.theme--documenter-dark .search-result-title{color:whitesmoke}html.theme--documenter-dark .search-result-highlight{background-color:greenyellow;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f50}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} diff --git a/previews/PR2422/assets/themes/documenter-light.css b/previews/PR2422/assets/themes/documenter-light.css new file mode 100644 index 0000000000..2f168c77b4 --- /dev/null +++ b/previews/PR2422/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;overflow:auto}.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;overflow-x:hidden}#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}.gap-4{gap:1rem} diff --git a/previews/PR2422/assets/themeswap.js b/previews/PR2422/assets/themeswap.js new file mode 100644 index 0000000000..9f5eebe6aa --- /dev/null +++ b/previews/PR2422/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/PR2422/assets/warner.js b/previews/PR2422/assets/warner.js new file mode 100644 index 0000000000..3f6f5d0083 --- /dev/null +++ b/previews/PR2422/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/PR2422/background/duality/index.html b/previews/PR2422/background/duality/index.html new file mode 100644 index 0000000000..cbc3e3a1ef --- /dev/null +++ b/previews/PR2422/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/PR2422/background/infeasibility_certificates/index.html b/previews/PR2422/background/infeasibility_certificates/index.html new file mode 100644 index 0000000000..3134642f6a --- /dev/null +++ b/previews/PR2422/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/PR2422/background/motivation/index.html b/previews/PR2422/background/motivation/index.html new file mode 100644 index 0000000000..ffca0a3eb1 --- /dev/null +++ b/previews/PR2422/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/PR2422/background/naming_conventions/index.html b/previews/PR2422/background/naming_conventions/index.html new file mode 100644 index 0000000000..934a4bb3cb --- /dev/null +++ b/previews/PR2422/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/PR2422/changelog/index.html b/previews/PR2422/changelog/index.html new file mode 100644 index 0000000000..9088be9679 --- /dev/null +++ b/previews/PR2422/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.25.2 (January 29, 2024)

    Fixed

    Other

    • Clarified ordering of nonlinear tape in documentation (#2401)
    • Updated vale.sh (#2403) (#2404)
    • Tidied `src/Utilities/results.jl (#2411)

    v1.25.1 (January 11, 2024)

    Fixed

    Other

    • Removed a duplicated test (#2395)

    v1.25.0 (January 5, 2024)

    Added

    • Added the AutomaticDifferentiationBackend attribute (#2386)

    Fixed

    v1.24.0 (January 2, 2024)

    Added

    • Added get_fallback for ConstraintDual of variable bounds (#2373)

    Fixed

    • Fixed RSOCtoPSDBridge for dimension 2 (#2359)
    • Fixed getting ConstraintFunction in conversion bridge (#2360)
    • Fixed map_indices (#2367)
    • Fixed SlackBridgePrimalDualStart for non-slack bridges (#2365)
    • Fixed test_attribute_TimeLimitSec (#2370)
    • Fixed order of model attributes during copy_to (#2372)
    • Fixed ConstraintIndex conflicts between variable and constraint bridges (#2362)
    • Fixed corner-case deletion in bridges (#2377)
    • Fixed ListOfVariablesWithAttributeSet for variable bridges (#2380)
    • Fixed SlackBridge if scalar constant is not zero (#2382)
    • Fixed setting multiple bounds on a bridged variable (#2383)

    Other

    • Minor documentation improvements (#2355), (#2374)
    • Improved side_dimension_for_vectorized_dimension (#2356)
    • Added DiffOpt and ParametricOptInterface to solver-tests.yml (#2368)
    • Refactored SDPAModel into a separate test file and test more widely (#2364), (#2357)

    v1.23.0 (November 29, 2023)

    Added

    Fixed

    • Fixed Test.test_model_Name_VariableName_ConstraintName (#2349)
    • Fixed errors thrown when querying an attribute is not supported, like when Utilities.CachingOptimizer is not attached to an optimizer (#2350)

    v1.22.0 (November 6, 2023)

    Added

    Fixed

    Other

    • Fixed typo in docstring of ScalarAffineFunction (#2326)
    • Added Gurobi to solver-tests.yml (#2332)
    • Improved the error message when a bridge does not support an attribute (#2329)
    • Improved documentation for implementing a bridge (#2334)
    • Updated [compat] bounds in Project.toml (#2344)

    v1.21.0 (October 25, 2023)

    Added

    Fixed

    • Fixed test_attribute_TimeLimitSec (#2256)
    • Fixed conversion cost in objective bridges (#2309)

    Other

    • Fixed flakey link checking in documentation (#2297)
    • Minor documentation fixes (#2304) (#2313)
    • Fixed [compat] section of Project.toml (#2310)
    • Added MultiObjectiveAlgorithms to solver-tests.yml (#2312)

    v1.20.1 (September 24, 2023)

    Fixed

    Other

    • Added MathOptSetDistances to solver-tests.yml (#2265)
    • Updated Documenter (#2266)
    • Fixed various JET errors (#2267) (#2269) (#2270) (#2271) (#2276) (#2277) (#2289)
    • Various style improvements
      • Replaced using Package with import Package where possible (#2274)
      • Removed Utilities.EMPTYSTRING (#2283)
      • Removed unnecessary const acronyms in Utilities (#2280) (#2281)
      • Removed invalid and unused method (#2286)
    • Refactored src/Utilities/model.jl (#2287)

    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_constraint_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/PR2422/developer/checklists/index.html b/previews/PR2422/developer/checklists/index.html new file mode 100644 index 0000000000..cde5120f2f --- /dev/null +++ b/previews/PR2422/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.schema.json` is updated
    + - [ ] The constant `_SUPPORTED_VERSIONS` is 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/PR2422/index.html b/previews/PR2422/index.html new file mode 100644 index 0000000000..5037958120 --- /dev/null +++ b/previews/PR2422/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

    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}
    +}

    A preprint of this paper is freely available.

    diff --git a/previews/PR2422/manual/constraints/index.html b/previews/PR2422/manual/constraints/index.html new file mode 100644 index 0000000000..672a4ea16d --- /dev/null +++ b/previews/PR2422/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/PR2422/manual/models/index.html b/previews/PR2422/manual/models/index.html new file mode 100644 index 0000000000..82e20ffd54 --- /dev/null +++ b/previews/PR2422/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/PR2422/manual/modification/index.html b/previews/PR2422/manual/modification/index.html new file mode 100644 index 0000000000..5b79649dff --- /dev/null +++ b/previews/PR2422/manual/modification/index.html @@ -0,0 +1,151 @@ + +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 quadratic coefficients in a scalar function

    Use modify and ScalarQuadraticCoefficientChange to modify the quadratic coefficient of a ScalarQuadraticFunction.

    julia> model = MOI.Utilities.Model{Float64}();
    +
    +julia> x = MOI.add_variables(model, 2);
    +
    +julia> c = MOI.add_constraint(
    +           model,
    +           1.0 * x[1] * x[1] + 2.0 * x[1] * x[2],
    +           MOI.EqualTo(1.0),
    +       )
    +MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadraticFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
    +
    +julia> MOI.modify(
    +           model,
    +           c,
    +           MOI.ScalarQuadraticCoefficientChange(x[1], x[1], 3.0),
    +       );
    +
    +julia> MOI.modify(
    +           model,
    +           c,
    +           MOI.ScalarQuadraticCoefficientChange(x[1], x[2], 4.0),
    +       );
    +
    +julia> new_f = 1.5 * x[1] * x[1] + 4.0 * x[1] * x[2];
    +
    +julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
    +true

    ScalarQuadraticCoefficientChange 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/PR2422/manual/solutions/index.html b/previews/PR2422/manual/solutions/index.html new file mode 100644 index 0000000000..bc63eb462a --- /dev/null +++ b/previews/PR2422/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/PR2422/manual/standard_form/index.html b/previews/PR2422/manual/standard_form/index.html new file mode 100644 index 0000000000..aa41ae2fcc --- /dev/null +++ b/previews/PR2422/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 \lvert x_i \rvert^p\right)^{\frac{1}{p}} \}$

    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/PR2422/manual/variables/index.html b/previews/PR2422/manual/variables/index.html new file mode 100644 index 0000000000..faa76e32ac --- /dev/null +++ b/previews/PR2422/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/PR2422/reference/callbacks/index.html b/previews/PR2422/reference/callbacks/index.html new file mode 100644 index 0000000000..228b0d30fc --- /dev/null +++ b/previews/PR2422/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 (that is, 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 (that is, 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, for example, 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 (that is, 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/PR2422/reference/constraints/index.html b/previews/PR2422/reference/constraints/index.html new file mode 100644 index 0000000000..1d16b6cb05 --- /dev/null +++ b/previews/PR2422/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 (that is, 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
    MOI.add_constraint(map::Map, vi::MOI.VariableIndex, set::MOI.AbstractScalarSet)

    Record that a constraint vi-in-set is added and throws if a lower or upper bound is set by this constraint and such bound has already been set for vi.

    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, for example, 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 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 corresponding 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 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 (for example, 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/PR2422/reference/errors/index.html b/previews/PR2422/reference/errors/index.html new file mode 100644 index 0000000000..b2ff0df2fe --- /dev/null +++ b/previews/PR2422/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, that is, 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, that is, 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, that is, 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/PR2422/reference/models/index.html b/previews/PR2422/reference/models/index.html new file mode 100644 index 0000000000..4c96259b4d --- /dev/null +++ b/previews/PR2422/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 set during an optimize! call, that is, the attribute is used to query the result of the optimization.

    If an attribute can be set by the user, define is_copyable instead.

    An attribute cannot be both is_copyable and is_set_by_optimize.

    Default fallback

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

    Undefined behavior

    Querying the value of the attribute that is_set_by_optimize before a call to optimize! is undefined and depends on solver-specific behavior.

    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.

    If an attribute is_copyable, then it cannot be modified by the optimizer, and get must always return the value that was set by the user.

    If an attribute is the result of an optimization, define is_set_by_optimize instead.

    An attribute cannot be both is_set_by_optimize and is_copyable.

    Default fallback

    By default is_copyable(attr) returns !is_set_by_optimize(attr), which is most probably true.

    If an attribute should not be copied, define is_copyable(::MyAttribute) = false.

    source
    MathOptInterface.getFunction
    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
    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
    MathOptInterface.get!Function
    get!(output, model::ModelLike, args...)

    An in-place version of get.

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

    source
    MathOptInterface.setFunction
    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
    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
    MathOptInterface.supportsFunction
    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 ListOfXXXAttributesSet.

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

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

    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, for example, 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.ListOfVariablesWithAttributeSetType
    ListOfVariablesWithAttributeSet(attr::AbstractVariableAttribute)

    A model attribute for the Vector{VariableIndex} of all variables with the attribute attr set.

    The returned list may not be minimal, so some elements may have their default value set.

    Note

    This is an optional attribute to implement. The default fallback is to get ListOfVariableIndices.

    source
    MathOptInterface.ListOfConstraintsWithAttributeSetType
    ListOfConstraintsWithAttributeSet{F,S}(attr:AbstractConstraintAttribute)

    A model attribute for the Vector{ConstraintIndex{F,S}} of all constraints with the attribute attr set.

    The returned list may not be minimal, so some elements may have their default value set.

    Note

    This is an optional attribute to implement. The default fallback is to get ListOfConstraintIndices.

    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 (for example, `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 seconds) 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.SolutionLimitType
    SolutionLimit()

    An optimizer attribute for setting a limit on the number of available feasible solutions.

    Default values

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

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

    The default value is nothing.

    Termination criteria

    The solver may stop when the ResultCount is larger than or equal to the SolutionLimit. If stopped because of this attribute, the TerminationStatus must be SOLUTION_LIMIT.

    Solution quality

    The quality of the available solutions is solver-dependent. The set of resulting solutions is not guaranteed to contain an optimal solution.

    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 (for example, 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, that is, 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 distinguish between them.

    If a primal or dual infeasibility certificate is available, that is, 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/PR2422/reference/modification/index.html b/previews/PR2422/reference/modification/index.html new file mode 100644 index 0000000000..e5cac32fa0 --- /dev/null +++ b/previews/PR2422/reference/modification/index.html @@ -0,0 +1,31 @@ + +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
    MathOptInterface.ScalarQuadraticCoefficientChangeType
    ScalarQuadraticCoefficientChange{T}(
    +    variable_1::VariableIndex,
    +    variable_2::VariableIndex,
    +    new_coefficient::T,
    +)

    A struct used to request a change in the quadratic coefficient of a ScalarQuadraticFunction.

    Scaling factors

    A ScalarQuadraticFunction has an implicit 0.5 scaling factor in front of the Q matrix. This modification applies to terms in the Q matrix.

    If variable_1 == variable_2, this modification sets the corresponding diagonal element of the Q matrix to new_coefficient.

    If variable_1 != variable_2, this modification is equivalent to setting both the corresponding upper- and lower-triangular elements of the Q matrix to new_coefficient.

    As a consequence:

    • to modify the term x^2 to become 2x^2, new_coefficient must be 4
    • to modify the term xy to become 2xy, new_coefficient must be 2
    source
    diff --git a/previews/PR2422/reference/nonlinear/index.html b/previews/PR2422/reference/nonlinear/index.html new file mode 100644 index 0000000000..d1b1f9bbea --- /dev/null +++ b/previews/PR2422/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/PR2422/reference/standard_form/index.html b/previews/PR2422/reference/standard_form/index.html new file mode 100644 index 0000000000..77c862a970 --- /dev/null +++ b/previews/PR2422/reference/standard_form/index.html @@ -0,0 +1,992 @@ + +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::Vector{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 (for example, 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 (for example, 1.0 * x + 0.0), and dimension must be even.

    The mixed complementarity problem consists of finding x_i in the interval [lb, ub] (that is, 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 occurences 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, that is, 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, that is, 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, that is, 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, that is, 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/PR2422/reference/variables/index.html b/previews/PR2422/reference/variables/index.html new file mode 100644 index 0000000000..95512f9ff1 --- /dev/null +++ b/previews/PR2422/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 (that is, 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, that is, 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, that is, 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/PR2422/release_notes/index.html b/previews/PR2422/release_notes/index.html new file mode 100644 index 0000000000..6fd2710fdf --- /dev/null +++ b/previews/PR2422/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.25.2 (January 29, 2024)

    Fixed

    Other

    • Clarified ordering of nonlinear tape in documentation (#2401)
    • Updated vale.sh (#2403) (#2404)
    • Tidied `src/Utilities/results.jl (#2411)

    v1.25.1 (January 11, 2024)

    Fixed

    Other

    • Removed a duplicated test (#2395)

    v1.25.0 (January 5, 2024)

    Added

    • Added the AutomaticDifferentiationBackend attribute (#2386)

    Fixed

    v1.24.0 (January 2, 2024)

    Added

    • Added get_fallback for ConstraintDual of variable bounds (#2373)

    Fixed

    • Fixed RSOCtoPSDBridge for dimension 2 (#2359)
    • Fixed getting ConstraintFunction in conversion bridge (#2360)
    • Fixed map_indices (#2367)
    • Fixed SlackBridgePrimalDualStart for non-slack bridges (#2365)
    • Fixed test_attribute_TimeLimitSec (#2370)
    • Fixed order of model attributes during copy_to (#2372)
    • Fixed ConstraintIndex conflicts between variable and constraint bridges (#2362)
    • Fixed corner-case deletion in bridges (#2377)
    • Fixed ListOfVariablesWithAttributeSet for variable bridges (#2380)
    • Fixed SlackBridge if scalar constant is not zero (#2382)
    • Fixed setting multiple bounds on a bridged variable (#2383)

    Other

    • Minor documentation improvements (#2355), (#2374)
    • Improved side_dimension_for_vectorized_dimension (#2356)
    • Added DiffOpt and ParametricOptInterface to solver-tests.yml (#2368)
    • Refactored SDPAModel into a separate test file and test more widely (#2364), (#2357)

    v1.23.0 (November 29, 2023)

    Added

    Fixed

    • Fixed Test.test_model_Name_VariableName_ConstraintName (#2349)
    • Fixed errors thrown when querying an attribute is not supported, like when Utilities.CachingOptimizer is not attached to an optimizer (#2350)

    v1.22.0 (November 6, 2023)

    Added

    Fixed

    Other

    • Fixed typo in docstring of ScalarAffineFunction (#2326)
    • Added Gurobi to solver-tests.yml (#2332)
    • Improved the error message when a bridge does not support an attribute (#2329)
    • Improved documentation for implementing a bridge (#2334)
    • Updated [compat] bounds in Project.toml (#2344)

    v1.21.0 (October 25, 2023)

    Added

    Fixed

    • Fixed test_attribute_TimeLimitSec (#2256)
    • Fixed conversion cost in objective bridges (#2309)

    Other

    • Fixed flakey link checking in documentation (#2297)
    • Minor documentation fixes (#2304) (#2313)
    • Fixed [compat] section of Project.toml (#2310)
    • Added MultiObjectiveAlgorithms to solver-tests.yml (#2312)

    v1.20.1 (September 24, 2023)

    Fixed

    Other

    • Added MathOptSetDistances to solver-tests.yml (#2265)
    • Updated Documenter (#2266)
    • Fixed various JET errors (#2267) (#2269) (#2270) (#2271) (#2276) (#2277) (#2289)
    • Various style improvements
      • Replaced using Package with import Package where possible (#2274)
      • Removed Utilities.EMPTYSTRING (#2283)
      • Removed unnecessary const acronyms in Utilities (#2280) (#2281)
      • Removed invalid and unused method (#2286)
    • Refactored src/Utilities/model.jl (#2287)

    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_constraint_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/PR2422/search_index.js b/previews/PR2422/search_index.js new file mode 100644 index 0000000000..4796344acf --- /dev/null +++ b/previews/PR2422/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 (that is, 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 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\nMOI.add_constraint(map::Map, vi::MOI.VariableIndex, set::MOI.AbstractScalarSet)\n\nRecord that a constraint vi-in-set is added and throws if a lower or upper bound is set by this constraint and such bound has already been set for vi.\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, for example, 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 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 corresponding 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 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 (for example, 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\nSolutionLimit 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\nListOfVariablesWithAttributeSet 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\nListOfConstraintsWithAttributeSet 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\nScalarQuadraticCoefficientChange\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 (that is, 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 represented 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 represented 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\nListOfConstraintsWithAttributeSet\nListOfModelAttributesSet\nListOfVariableAttributesSet\nListOfVariableIndices\nListOfVariablesWithAttributeSet\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\nSolutionLimit\nAutomaticDifferentiationBackend","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 verbose::Bool = false,\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.\nverbose is a Bool that controls whether the name of the test is printed before executing it. This can be helpful when debugging.\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 verbose = 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 (for example, 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\": 7\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/#ScalarNonlinearFunction","page":"Overview","title":"ScalarNonlinearFunction","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"By default, reading a .nl or .mof.json that contains nonlinear expressions will create an NLPBlock.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"To instead read nonlinear expressions as ScalarNonlinearFunction, pass the use_nlp_block = false keyword argument to the Model constructor:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(;\n format = MOI.FileFormats.FORMAT_MOF,\n use_nlp_block = false,\n )\nA MathOptFormat Model\n\njulia> model = MOI.FileFormats.Model(;\n format = MOI.FileFormats.FORMAT_NL,\n use_nlp_block = false,\n )\nAn AMPL (.nl) model","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":"MOI.Utilities.Model{T}() where {T}\n\nAn implementation of ModelLike that supports all functions and sets defined in MOI. It is parameterized by the coefficient type.\n\nExamples\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\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 supporting all combinations of the provided functions and sets.\n\nEach typed_ scalar/vector sets/functions argument is a tuple of types. A type is \"typed\" if it has a coefficient {T} as the first type parameter.\n\nTuple syntax\n\nTo give no set/function, write (). To give one set or function X, write (X,).\n\nis_optimizer\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\nVariableIndex\n\nThe function MOI.VariableIndex must not be given in scalar_functions.\nThe 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.\nThe sets supported with MOI.VariableIndex cannot be controlled from the macro; use UniversalFallback to support more sets.\n\nExamples\n\nThe model describing a linear program would be:\n\n@model(\n LPModel, # model_name\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, # is_optimizer\n)\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 take place via the MOI interface, so the types O, V, and C must 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 take place via the MOI interface, so the types O, V, and C must 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\nUtilities.loadfromstring!","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, that is, 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/#MathOptInterface.Utilities.loadfromstring!","page":"API Reference","title":"MathOptInterface.Utilities.loadfromstring!","text":"loadfromstring!(model, s)\n\nA utility function to aid writing tests.\n\nwarning: Warning\nThis function is not intended for widespread use. It is mainly used as a tool to simplify writing tests in MathOptInterface. Do not use it as an exchange format for storing or transmitting problem instances. Use the FileFormats submodule instead.\n\nExample\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> MOI.Utilities.loadfromstring!(model, \"\"\"\n variables: x, y, z\n constrainedvariable: [a, b, c] in Nonnegatives(3)\n minobjective::Float64: 2x + 3y\n con1: x + y <= 1.0\n con2: [x, y] in Nonnegatives(2)\n x >= 0.0\n \"\"\")\n\nNotes\n\nSpecial labels are:\n\nvariables\nminobjective\nmaxobjectives\n\nEverything else denotes a constraint with a name.\n\nAppend ::T to use an element type of T when parsing the function.\n\nDo not name VariableIndex constraints.\n\nExceptions\n\nx - y does NOT currently parse. Instead, write x + -1.0 * y.\nx^2 does NOT currently parse. Instead, write x * x.\n\n\n\n\n\n","category":"function"},{"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, for example, 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\nUtilities.modify_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/#MathOptInterface.Utilities.modify_constants","page":"API Reference","title":"MathOptInterface.Utilities.modify_constants","text":"modify_constants(constants, row::Integer, new_constant::T) where {T}\nmodify_constants(\n constants,\n rows::AbstractVector{<:Integer},\n new_constants::AbstractVector{T},\n) where {T}\n\nModify constants in-place to store new_constant in the row row, or rows rows.\n\nThis function must be implemented to enable MOI.ScalarConstantChange and MOI.VectorConstantChange 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(\n model::MOI.ModelLike,\n ::MOI.DualObjectiveValue,\n ::Type{T},\n)::T where {T}\n\nCompute the dual objective value of type T using the ConstraintDual results and the ConstraintFunction and ConstraintSet values.\n\nNote that the nonlinear part of the model is ignored.\n\n\n\n\n\nget_fallback(\n model::MOI.ModelLike,\n ::MOI.ConstraintPrimal,\n constraint_index::MOI.ConstraintIndex,\n)\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(\n model::MOI.ModelLike,\n attr::MOI.ConstraintDual,\n ci::MOI.ConstraintIndex{Union{MOI.VariableIndex,MOI.VectorOfVariables}},\n ::Type{T} = Float64,\n) where {T}\n\nCompute the dual of the constraint of index ci using the ConstraintDual of other constraints and the ConstraintFunction values.\n\nThrows 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(\n f::MOI.AbstractFunction,\n s::MOI.AbstractSet,\n vi::MOI.VariableIndex,\n)\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 (for example, 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, that is,\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\nget_bounds(\n model::MOI.ModelLike,\n bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},\n f::MOI.ScalarAffineFunction{T},\n) where {T} --> Union{Nothing,NTuple{2,T}}\n\nReturn the lower and upper bound of f as a tuple. If the domain is not bounded, return nothing.\n\n\n\n\n\nget_bounds(\n model::MOI.ModelLike,\n bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},\n x::MOI.VariableIndex,\n) where {T} --> Union{Nothing,NTuple{2,T}}\n\nReturn the lower and upper bound of x as a tuple. If the domain is not bounded, return nothing.\n\nSimilar to get_bounds(::MOI.ModelLike, ::Type{T}, ::MOI.VariableIndex), except that the second argument is a cache which maps variables to their bounds and avoids repeated lookups.\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 enable 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\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RotatedSecondOrderCone)\n\nLet (t, u, y...) = x. Return the 2-norm of the vector d such that in x + d, u is projected to 1 if u <= 0, and t is increased such that x + d belongs to the set.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.ExponentialCone)\n\nLet (u, v, w) = x. If v > 0, return the epigraph distance d such that (u, v, w + d) belongs to the set.\n\nIf v <= 0 return the 2-norm of the vector d such that x + d = (u, 1, z) where z satisfies the constraints.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualExponentialCone)\n\nLet (u, v, w) = x. If u < 0, return the epigraph distance d such that (u, v, w + d) belongs to the set.\n\nIf u >= 0 return the 2-norm of the vector d such that x + d = (u, -1, z) where z satisfies the constraints.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.GeometricMeanCone)\n\nLet (t, y...) = x. If all y are non-negative, return the epigraph distance d such that (t + d, y...) belongs to the set.\n\nIf any y are strictly negative, return the 2-norm of the vector d that projects negative y elements to 0 and t to ℝ₋.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.PowerCone)\n\nLet (a, b, c) = x. If a and b are non-negative, return the epigraph distance required to increase c such that the constraint is satisfied.\n\nIf a or b is strictly negative, return the 2-norm of the vector d such that in the vector x + d: c, and any negative a and b are projected to 0.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualPowerCone)\n\nLet (a, b, c) = x. If a and b are non-negative, return the epigraph distance required to increase c such that the constraint is satisfied.\n\nIf a or b is strictly negative, return the 2-norm of the vector d such that in the vector x + d: c, and any negative a and b are projected to 0.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormOneCone)\n\nLet (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormInfinityCone)\n\nLet (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RelativeEntropyCone)\n\nLet (u, v..., w...) = x. If v and w are strictly positive, return the epigraph distance required to increase u such that the constraint is satisfied.\n\nIf any elements in v or w are non-positive, return the 2-norm of the vector d such that in the vector x + d: any non-positive elements in v and w are projected to 1, and u is projected such that the epigraph constraint holds.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, set::MOI.NormCone)\n\nLet (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.\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 guarantee 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 guarantee 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-quadratic-coefficients-in-a-scalar-function","page":"Problem modification","title":"Modify quadratic coefficients in a scalar function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and ScalarQuadraticCoefficientChange to modify the quadratic coefficient of a ScalarQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variables(model, 2);\n\njulia> c = MOI.add_constraint(\n model,\n 1.0 * x[1] * x[1] + 2.0 * x[1] * x[2],\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadraticFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> MOI.modify(\n model,\n c,\n MOI.ScalarQuadraticCoefficientChange(x[1], x[1], 3.0),\n );\n\njulia> MOI.modify(\n model,\n c,\n MOI.ScalarQuadraticCoefficientChange(x[1], x[2], 4.0),\n );\n\njulia> new_f = 1.5 * x[1] * x[1] + 4.0 * x[1] * x[2];\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"ScalarQuadraticCoefficientChange 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.\nuse_nlp_block::Bool=true: if true parse \"ScalarNonlinearFunction\" into an MOI.NLPBlock. If false, \"ScalarNonlinearFunction\" are parsed as MOI.ScalarNonlinearFunction functions.\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, that is, 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, that is, 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, that is, 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, that is, 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, that is, 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 (that is, 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, that is, 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, that is, 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\nBridges.Constraint.SOS1ToMILPBridge\nBridges.Constraint.SOS2ToMILPBridge\nBridges.Constraint.IndicatorToMILPBridge","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 not 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\nFormulation (special case)\n\nIn the special case that the constraint is [2, x, y] in CountDistinct(3), then the constraint is equivalent to [x, y] in AllDifferent(2), which is equivalent to x != y.\n\n(x - y = -1) vee (y - x = -1)\n\nwhich is equivalent to (for suitable M):\n\nbeginaligned\nz in 0 1 \nx - y - M * z = -1 \ny - x - M * (1 - z) = -1\nendaligned\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/#MathOptInterface.Bridges.Constraint.SOS1ToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOS1ToMILPBridge","text":"SOS1ToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nSOS1ToMILPBridge implements the following reformulation:\n\nx in textsfSOS1(d) into a mixed-integer linear program.\n\nSource node\n\nSOS1ToMILPBridge supports:\n\nF in MOI.SOS1\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nSOS1ToMILPBridge 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.SOS2ToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOS2ToMILPBridge","text":"SOS2ToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nSOS2ToMILPBridge implements the following reformulation:\n\nx in textsfSOS2(d) into a mixed-integer linear program.\n\nSource node\n\nSOS2ToMILPBridge supports:\n\nF in MOI.SOS2\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nSOS2ToMILPBridge 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.IndicatorToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorToMILPBridge","text":"IndicatorToMILPBridge{T,F,A,S} <: Bridges.Constraint.AbstractBridge\n\nIndicatorToMILPBridge implements the following reformulation:\n\nx in textsfIndicator(s) into a mixed-integer linear program.\n\nSource node\n\nIndicatorToMILPBridge supports:\n\nF in MOI.Indicator{A,S}\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nIndicatorToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in S\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.VectorFunctionizeBridge\nBridges.Objective.FunctionConversionBridge\nBridges.Objective.SlackBridge\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,G} <: FunctionConversionBridge{T,MOI.ScalarAffineFunction{T},G}\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{G}\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,G} <: FunctionConversionBridge{T,MOI.ScalarQuadraticFunction{T},G}\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{G}\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.VectorFunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.VectorFunctionizeBridge","text":"VectorFunctionizeBridge{T,G} <: FunctionConversionBridge{T,MOI.VectorAffineFunction{T},G}\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{G}\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.FunctionConversionBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.FunctionConversionBridge","text":"FunctionConversionBridge{T,F,G} <: AbstractBridge\n\nFunctionConversionBridge implements the following reformulations:\n\nmin g(x) into minf(x)\nmax g(x) into maxf(x)\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\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nFunctionConversionBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{F}\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.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\nBridges.Variable.ParameterToEqualToBridge","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 ensure 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 constant 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/list_of_bridges/#MathOptInterface.Bridges.Variable.ParameterToEqualToBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.ParameterToEqualToBridge","text":"ParameterToEqualToBridge{T} <: Bridges.Variable.AbstractBridge\n\nParameterToEqualToBridge implements the following reformulation:\n\nx in Parameter(v) into x == v\n\nSource node\n\nParameterToEqualToBridge supports:\n\nMOI.VariableIndex in MOI.Parameter\n\nTarget nodes\n\nParameterToEqualToBridge creates:\n\nOne variable node: MOI.VariableIndex in MOI.EqualTo{T}\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.schema.json` is updated\n - [ ] The constant `_SUPPORTED_VERSIONS` is updated in\n `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) (tx) in mathbbR^d t ge left(sumlimits_i lvert x_i rvert^pright)^frac1p ","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\nScalarQuadraticCoefficientChange\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.ScalarQuadraticCoefficientChange","page":"Modifications","title":"MathOptInterface.ScalarQuadraticCoefficientChange","text":"ScalarQuadraticCoefficientChange{T}(\n variable_1::VariableIndex,\n variable_2::VariableIndex,\n new_coefficient::T,\n)\n\nA struct used to request a change in the quadratic coefficient of a ScalarQuadraticFunction.\n\nScaling factors\n\nA ScalarQuadraticFunction has an implicit 0.5 scaling factor in front of the Q matrix. This modification applies to terms in the Q matrix.\n\nIf variable_1 == variable_2, this modification sets the corresponding diagonal element of the Q matrix to new_coefficient.\n\nIf variable_1 != variable_2, this modification is equivalent to setting both the corresponding upper- and lower-triangular elements of the Q matrix to new_coefficient.\n\nAs a consequence:\n\nto modify the term x^2 to become 2x^2, new_coefficient must be 4\nto modify the term xy to become 2xy, new_coefficient must be 2\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.25.2-(January-29,-2024)","page":"Release notes","title":"v1.25.2 (January 29, 2024)","text":"","category":"section"},{"location":"changelog/#Fixed","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed getting ConstraintPrimal if variable bridges are present (#2396)\nFixed modify_function! for ScalarQuadraticCoefficientChange (#2408)\nFixed writing FileFormats.MOF files if ScalarNonlinearFunction contains ScalarAffineFunction or ScalarQuadraticFunction (#2409)","category":"page"},{"location":"changelog/#Other","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Clarified ordering of nonlinear tape in documentation (#2401)\nUpdated vale.sh (#2403) (#2404)\nTidied `src/Utilities/results.jl (#2411)","category":"page"},{"location":"changelog/#v1.25.1-(January-11,-2024)","page":"Release notes","title":"v1.25.1 (January 11, 2024)","text":"","category":"section"},{"location":"changelog/#Fixed-2","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed map_indices for AbstractAutomaticDifferentiation (#2394)\nFixed deleting a variable in Bridges.Variable.VectorizeBridge (#2393)\nFixed super type of LowerBoundAlreadySet and UpperBoundAlreadySet (#2397)","category":"page"},{"location":"changelog/#Other-2","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Removed a duplicated test (#2395)","category":"page"},{"location":"changelog/#v1.25.0-(January-5,-2024)","page":"Release notes","title":"v1.25.0 (January 5, 2024)","text":"","category":"section"},{"location":"changelog/#Added","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added the AutomaticDifferentiationBackend attribute (#2386)","category":"page"},{"location":"changelog/#Fixed-3","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed initialize for Nonlinear.ExprGraphOnly (#2387)\nFixed converting 0-valued ScalarAffineFunction and ScalarQuadraticFunction to ScalarNonlinearFunction (#2388)\nFixed reading .nl files with non-empty variable and constraint names (#2390)\nFixed reading .nl files with no objective (#2391)\nFixed reading .nl files with free ranged constraints (#2392)","category":"page"},{"location":"changelog/#v1.24.0-(January-2,-2024)","page":"Release notes","title":"v1.24.0 (January 2, 2024)","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 get_fallback for ConstraintDual of variable bounds (#2373)","category":"page"},{"location":"changelog/#Fixed-4","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed RSOCtoPSDBridge for dimension 2 (#2359)\nFixed getting ConstraintFunction in conversion bridge (#2360)\nFixed map_indices (#2367)\nFixed SlackBridgePrimalDualStart for non-slack bridges (#2365)\nFixed test_attribute_TimeLimitSec (#2370)\nFixed order of model attributes during copy_to (#2372)\nFixed ConstraintIndex conflicts between variable and constraint bridges (#2362)\nFixed corner-case deletion in bridges (#2377)\nFixed ListOfVariablesWithAttributeSet for variable bridges (#2380)\nFixed SlackBridge if scalar constant is not zero (#2382)\nFixed setting multiple bounds on a bridged variable (#2383)","category":"page"},{"location":"changelog/#Other-3","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Minor documentation improvements (#2355), (#2374)\nImproved side_dimension_for_vectorized_dimension (#2356)\nAdded DiffOpt and ParametricOptInterface to solver-tests.yml (#2368)\nRefactored SDPAModel into a separate test file and test more widely (#2364), (#2357)","category":"page"},{"location":"changelog/#v1.23.0-(November-29,-2023)","page":"Release notes","title":"v1.23.0 (November 29, 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 ConstraintPrimalStart for Bridges.Constraint.GeoMeanBridge (#2348)\nAdded verbose keyword argument to Test.runtests (#2347)\nAdded Bridges.FirstBridge attribute (#2211)","category":"page"},{"location":"changelog/#Fixed-5","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed Test.test_model_Name_VariableName_ConstraintName (#2349)\nFixed errors thrown when querying an attribute is not supported, like when Utilities.CachingOptimizer is not attached to an optimizer (#2350)","category":"page"},{"location":"changelog/#v1.22.0-(November-6,-2023)","page":"Release notes","title":"v1.22.0 (November 6, 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 new bridges (#2318)\nBridges.Constraint.SOS1ToMILPBridge\nBridges.Constraint.SOS2ToMILPBridge\nBridges.Constraint.IndicatorToMILPBridge\nAdded starting values for bridges (#2330) (#2337) (#2338) (#2339)\nBridges.Constraint.NumberConversionBridge\nBridges.Constraint.SquareBridge\nBridges.Variable.HermitianToSymmetricPSDBridge\nBridges.Variable.ParameterToEqualToBridge\nBridges.Variable.RSOCtoPSDBridge\nAdded ListOfVariablesWithAttributeSet and ListOfConstraintsWithAttributeSet (#2331) (#2342)\nAdded support for printing ConstraintName when models are printed (#2336)","category":"page"},{"location":"changelog/#Fixed-6","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"ScalarFunctionConstantNotZero errors are now skipped in Test.runtests (#2325)\nFixed VectorNonlinearFunction support in Bridges.Constraint.NormOneBridge and Bridges.Constraint.NormInfinityBridge (#2324)\nFixed various get for ConstraintFunction to return a copy, and added tests (#2328)\nFixed supports of ConstraintPrimalStart and VariablePrimalStart for some bridges (#2340)","category":"page"},{"location":"changelog/#Other-4","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed typo in docstring of ScalarAffineFunction (#2326)\nAdded Gurobi to solver-tests.yml (#2332)\nImproved the error message when a bridge does not support an attribute (#2329)\nImproved documentation for implementing a bridge (#2334)\nUpdated [compat] bounds in Project.toml (#2344)","category":"page"},{"location":"changelog/#v1.21.0-(October-25,-2023)","page":"Release notes","title":"v1.21.0 (October 25, 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 SolutionLimit attribute (#2291)\nAdded support for MathOptFormat v1.6 and v1.7 (#2293) (#2298) (#2299) (#2321)\nAdded ScalarQuadraticCoefficientChange (#2296) (#2320) (#2322)\nAdded Utilities.modify_constants (#2300)\nAdded support for is_empty and empty! of Nonlinear.Model (#2305)\nAdded Bridges.Objective.FunctionConversionBridge (#2303)\nAdded Bridges.ModifyBridgeNotAllowed (#2307)\nAdded more sets for Utilities.distance_to_set (#2314)","category":"page"},{"location":"changelog/#Fixed-7","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed test_attribute_TimeLimitSec (#2256)\nFixed conversion cost in objective bridges (#2309)","category":"page"},{"location":"changelog/#Other-5","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed flakey link checking in documentation (#2297)\nMinor documentation fixes (#2304) (#2313)\nFixed [compat] section of Project.toml (#2310)\nAdded MultiObjectiveAlgorithms to solver-tests.yml (#2312)","category":"page"},{"location":"changelog/#v1.20.1-(September-24,-2023)","page":"Release notes","title":"v1.20.1 (September 24, 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":"Removed incorrect kwargs in some copy_to methods (#2272)\nFixed ConstraintDualStart for Bridges.Constraint.SplitIntervalBridge (#2275)\nFixed MethodError when trying to modify a variable objective (#2278)\nFixed stack-overflow in Utilities.operate(+,...) with many arguments (#2285) (#2290)","category":"page"},{"location":"changelog/#Other-6","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added MathOptSetDistances to solver-tests.yml (#2265)\nUpdated Documenter (#2266)\nFixed various JET errors (#2267) (#2269) (#2270) (#2271) (#2276) (#2277) (#2289)\nVarious style improvements\nReplaced using Package with import Package where possible (#2274)\nRemoved Utilities.EMPTYSTRING (#2283)\nRemoved unnecessary const acronyms in Utilities (#2280) (#2281)\nRemoved invalid and unused method (#2286)\nRefactored src/Utilities/model.jl (#2287)","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-6","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-7","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-7","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-9","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-8","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-8","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-10","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-9","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-11","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-10","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-9","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-12","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-10","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-13","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-11","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-14","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-11","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-15","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-12","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-16","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-13","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-12","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-17","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-18","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-14","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-15","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-13","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-19","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-16","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-14","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-20","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-17","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-21","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-18","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-22","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-23","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-19","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-24","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-25","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-15","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-20","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-16","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-26","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-21","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-17","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-27","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_constraint_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-28","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-18","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-29","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-19","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-30","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-22","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-31","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-20","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-32","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-21","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-33","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-23","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-22","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-34","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-24","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-23","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-35","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-25","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-24","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-36","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-37","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-38","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-25","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-39","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-40","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-26","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-41","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-26","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-27","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-42","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-28","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-43","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-27","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-29","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-44","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-45","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-28","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-30","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-29","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-46","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 (that is, 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 (that is, 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, for example, 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 (that is, 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 set during an optimize! call, that is, the attribute is used to query the result of the optimization.\n\nIf an attribute can be set by the user, define is_copyable instead.\n\nAn attribute cannot be both is_copyable and is_set_by_optimize.\n\nDefault fallback\n\nThis function returns false by default so it should be implemented for attributes that are set by optimize!.\n\nUndefined behavior\n\nQuerying the value of the attribute that is_set_by_optimize before a call to optimize! is undefined and depends on solver-specific behavior.\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\nIf an attribute is_copyable, then it cannot be modified by the optimizer, and get must always return the value that was set by the user.\n\nIf an attribute is the result of an optimization, define is_set_by_optimize instead.\n\nAn attribute cannot be both is_set_by_optimize and is_copyable.\n\nDefault fallback\n\nBy default is_copyable(attr) returns !is_set_by_optimize(attr), which is most probably true.\n\nIf an attribute should not be copied, define is_copyable(::MyAttribute) = false.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.get","page":"Models","title":"MathOptInterface.get","text":"get(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\nMOI.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\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 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":"set(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\nfunction 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\n","category":"function"},{"location":"reference/models/#MathOptInterface.supports","page":"Models","title":"MathOptInterface.supports","text":"supports(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 ListOfXXXAttributesSet.\n\n\n\n\n\nMOI.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\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\nListOfVariablesWithAttributeSet\nListOfConstraintAttributesSet\nListOfConstraintsWithAttributeSet\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, for example, 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 (that is, 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 (that is, 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.ListOfVariablesWithAttributeSet","page":"Models","title":"MathOptInterface.ListOfVariablesWithAttributeSet","text":"ListOfVariablesWithAttributeSet(attr::AbstractVariableAttribute)\n\nA model attribute for the Vector{VariableIndex} of all variables with the attribute attr set.\n\nThe returned list may not be minimal, so some elements may have their default value set.\n\nNote\n\nThis is an optional attribute to implement. The default fallback is to get ListOfVariableIndices.\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.ListOfConstraintsWithAttributeSet","page":"Models","title":"MathOptInterface.ListOfConstraintsWithAttributeSet","text":"ListOfConstraintsWithAttributeSet{F,S}(attr:AbstractConstraintAttribute)\n\nA model attribute for the Vector{ConstraintIndex{F,S}} of all constraints with the attribute attr set.\n\nThe returned list may not be minimal, so some elements may have their default value set.\n\nNote\n\nThis is an optional attribute to implement. The default fallback is to get ListOfConstraintIndices.\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\nSolutionLimit\nRawOptimizerAttribute\nNumberOfThreads\nRawSolver\nAbsoluteGapTolerance\nRelativeGapTolerance\nAutomaticDifferentiationBackend","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 (for example, `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 seconds) 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.SolutionLimit","page":"Models","title":"MathOptInterface.SolutionLimit","text":"SolutionLimit()\n\nAn optimizer attribute for setting a limit on the number of available feasible solutions.\n\nDefault values\n\nThe provided limit must be a Union{Nothing,Int}.\n\nWhen set to nothing, the limit reverts to the solver's default.\n\nThe default value is nothing.\n\nTermination criteria\n\nThe solver may stop when the ResultCount is larger than or equal to the SolutionLimit. If stopped because of this attribute, the TerminationStatus must be SOLUTION_LIMIT.\n\nSolution quality\n\nThe quality of the available solutions is solver-dependent. The set of resulting solutions is not guaranteed to contain an optimal solution.\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/#MathOptInterface.AutomaticDifferentiationBackend","page":"Models","title":"MathOptInterface.AutomaticDifferentiationBackend","text":"AutomaticDifferentiationBackend() <: AbstractOptimizerAttribute\n\nAn AbstractOptimizerAttribute for setting the automatic differentiation backend used by the solver.\n\nThe value must be a subtype of Nonlinear.AbstractAutomaticDifferentiation.\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 (for example, 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, that is, 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 distinguish between them.\n\nIf a primal or dual infeasibility certificate is available, that is, 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":"The ordering of the nodes in the tape must satisfy two rules:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The children of a node must appear after the parent. This means that the tape is ordered topologically, so that a reverse pass of the nodes evaluates all children nodes before their parent\nThe arguments for a CALL node are ordered in the tape based on the order in which they appear in the function call.","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":"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/#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-2","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":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Bridges/implementation/#Implementing-a-bridge","page":"Implementation","title":"Implementing a bridge","text":"","category":"section"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"The easiest way to implement a bridge is to follow an existing example. There are three locations of bridges in the source code:","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Constraint bridges are stored in src/Bridges/Constraint/bridges\nObjective bridges are stored in src/Bridges/Objective/bridges\nVariable bridges are stored in src/Bridges/Variable/bridges","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"The Implementing a constraint bridge tutorial has a more detailed guide on what is required to implement a bridge.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"When opening a pull request that adds a new bridge, use the checklist Adding a new bridge.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"If you need help or advice, please contact the Developer Chatroom.","category":"page"},{"location":"submodules/Bridges/implementation/#SetMap-bridges","page":"Implementation","title":"SetMap bridges","text":"","category":"section"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"For constraint and variable bridges, a common reformulation is that f(x) in F is reformulated to g(x) in G. In this case, no additional variables and constraints are added, and the bridge needs only a way to map between the functions f and g and the sets F and G.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"To implementation a bridge of this form, subtype the abstract type Bridges.Constraint.SetMapBridge or Bridges.Variable.SetMapBridge and implement the API described in the docstring of each type.","category":"page"},{"location":"submodules/Bridges/implementation/#final_touch","page":"Implementation","title":"final_touch","text":"","category":"section"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Some bridges require information from other parts of the model. One set of examples are the various combinatorial ToMILP bridges, such as Bridges.Constraint.SOS1ToMILPBridge, which require knowledge of the variable bounds.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Bridges requiring information from other parts of the model should implement Bridges.final_touch and Bridges.needs_final_touch.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"During the bridge's construction, store the function and set and make no changes to the underlying model. Then, in Bridges.final_touch, query the additional information and add the reformulated problem to the model.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"When implementing, you must consider that:","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Bridges.final_touch may be called multiple times, so that your reformulation should be applied only if necessary. Sometimes the additional data will be the same, and sometimes it may be different.\nWe do not currently support final_touch bridges that introduce constraints which also require a final_touch bridge. Therefore, you should implement final_touch only if necessary, and we recommend that you contact the Developer Chatroom for advice before doing so.","category":"page"},{"location":"submodules/Bridges/implementation/#Testing","page":"Implementation","title":"Testing","text":"","category":"section"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Use the Bridges.runtests function to test a bridge. It takes three arguments: the type of the bridge, the input model as a string, and the output model as a string.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Here is an example:","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"julia> MOI.Bridges.runtests(\n MOI.Bridges.Constraint.GreaterToLessBridge,\n \"\"\"\n variables: x\n x >= 1.0\n \"\"\",\n \"\"\"\n variables: x\n -1.0 * x <= -1.0\n \"\"\",\n )","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"There are a number of other useful keyword arguments.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"eltype can be used to specify the element type of the model (and bridge). It defaults to Float64.\nvariable_start and constraint_start are used as the values to set the VariablePrimalStart and ConstraintPrimalStart attributes to. They default to 1.2. If you use a different eltype, you must set appropriate starting values of the same type. The default 1.2 was chosen to minimize the risk that the starting point is undefined, which could happen for common situations like 0.0 and 1.0. The tests associated with the starting values do not necessarily check for correctness, only that they can be set and get to produce the same result.\nprint_inner_model can be used to print the reformulated output model from the bridge. This is especially helpful during debugging to see what the bridge is doing, and to spot mistakes. It defaults to false.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Here is an example:","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"julia> MOI.Bridges.runtests(\n MOI.Bridges.Constraint.GreaterToLessBridge,\n \"\"\"\n variables: x\n x >= 1\n \"\"\",\n \"\"\"\n variables: x\n ::Int: -1 * x <= -1\n \"\"\";\n eltype = Int,\n print_inner_model = true,\n variable_start = 2,\n constraint_start = 2,\n )\nFeasibility\n\nSubject to:\n\nScalarAffineFunction{Int64}-in-LessThan{Int64}\n (0) - (1) x <= (-1)","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.25.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.25.2)-(January-29,-2024)","page":"Release notes","title":"v1.25.2 (January 29, 2024)","text":"","category":"section"},{"location":"release_notes/#Fixed","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed getting ConstraintPrimal if variable bridges are present (#2396)\nFixed modify_function! for ScalarQuadraticCoefficientChange (#2408)\nFixed writing FileFormats.MOF files if ScalarNonlinearFunction contains ScalarAffineFunction or ScalarQuadraticFunction (#2409)","category":"page"},{"location":"release_notes/#Other","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Clarified ordering of nonlinear tape in documentation (#2401)\nUpdated vale.sh (#2403) (#2404)\nTidied `src/Utilities/results.jl (#2411)","category":"page"},{"location":"release_notes/#[v1.25.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.25.1)-(January-11,-2024)","page":"Release notes","title":"v1.25.1 (January 11, 2024)","text":"","category":"section"},{"location":"release_notes/#Fixed-2","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed map_indices for AbstractAutomaticDifferentiation (#2394)\nFixed deleting a variable in Bridges.Variable.VectorizeBridge (#2393)\nFixed super type of LowerBoundAlreadySet and UpperBoundAlreadySet (#2397)","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":"Removed a duplicated test (#2395)","category":"page"},{"location":"release_notes/#[v1.25.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.25.0)-(January-5,-2024)","page":"Release notes","title":"v1.25.0 (January 5, 2024)","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 the AutomaticDifferentiationBackend attribute (#2386)","category":"page"},{"location":"release_notes/#Fixed-3","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed initialize for Nonlinear.ExprGraphOnly (#2387)\nFixed converting 0-valued ScalarAffineFunction and ScalarQuadraticFunction to ScalarNonlinearFunction (#2388)\nFixed reading .nl files with non-empty variable and constraint names (#2390)\nFixed reading .nl files with no objective (#2391)\nFixed reading .nl files with free ranged constraints (#2392)","category":"page"},{"location":"release_notes/#[v1.24.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.24.0)-(January-2,-2024)","page":"Release notes","title":"v1.24.0 (January 2, 2024)","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 get_fallback for ConstraintDual of variable bounds (#2373)","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 RSOCtoPSDBridge for dimension 2 (#2359)\nFixed getting ConstraintFunction in conversion bridge (#2360)\nFixed map_indices (#2367)\nFixed SlackBridgePrimalDualStart for non-slack bridges (#2365)\nFixed test_attribute_TimeLimitSec (#2370)\nFixed order of model attributes during copy_to (#2372)\nFixed ConstraintIndex conflicts between variable and constraint bridges (#2362)\nFixed corner-case deletion in bridges (#2377)\nFixed ListOfVariablesWithAttributeSet for variable bridges (#2380)\nFixed SlackBridge if scalar constant is not zero (#2382)\nFixed setting multiple bounds on a bridged variable (#2383)","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":"Minor documentation improvements (#2355), (#2374)\nImproved side_dimension_for_vectorized_dimension (#2356)\nAdded DiffOpt and ParametricOptInterface to solver-tests.yml (#2368)\nRefactored SDPAModel into a separate test file and test more widely (#2364), (#2357)","category":"page"},{"location":"release_notes/#[v1.23.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.23.0)-(November-29,-2023)","page":"Release notes","title":"v1.23.0 (November 29, 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 ConstraintPrimalStart for Bridges.Constraint.GeoMeanBridge (#2348)\nAdded verbose keyword argument to Test.runtests (#2347)\nAdded Bridges.FirstBridge attribute (#2211)","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 Test.test_model_Name_VariableName_ConstraintName (#2349)\nFixed errors thrown when querying an attribute is not supported, like when Utilities.CachingOptimizer is not attached to an optimizer (#2350)","category":"page"},{"location":"release_notes/#[v1.22.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.22.0)-(November-6,-2023)","page":"Release notes","title":"v1.22.0 (November 6, 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 new bridges (#2318)\nBridges.Constraint.SOS1ToMILPBridge\nBridges.Constraint.SOS2ToMILPBridge\nBridges.Constraint.IndicatorToMILPBridge\nAdded starting values for bridges (#2330) (#2337) (#2338) (#2339)\nBridges.Constraint.NumberConversionBridge\nBridges.Constraint.SquareBridge\nBridges.Variable.HermitianToSymmetricPSDBridge\nBridges.Variable.ParameterToEqualToBridge\nBridges.Variable.RSOCtoPSDBridge\nAdded ListOfVariablesWithAttributeSet and ListOfConstraintsWithAttributeSet (#2331) (#2342)\nAdded support for printing ConstraintName when models are printed (#2336)","category":"page"},{"location":"release_notes/#Fixed-6","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"ScalarFunctionConstantNotZero errors are now skipped in Test.runtests (#2325)\nFixed VectorNonlinearFunction support in Bridges.Constraint.NormOneBridge and Bridges.Constraint.NormInfinityBridge (#2324)\nFixed various get for ConstraintFunction to return a copy, and added tests (#2328)\nFixed supports of ConstraintPrimalStart and VariablePrimalStart for some bridges (#2340)","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":"Fixed typo in docstring of ScalarAffineFunction (#2326)\nAdded Gurobi to solver-tests.yml (#2332)\nImproved the error message when a bridge does not support an attribute (#2329)\nImproved documentation for implementing a bridge (#2334)\nUpdated [compat] bounds in Project.toml (#2344)","category":"page"},{"location":"release_notes/#[v1.21.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.21.0)-(October-25,-2023)","page":"Release notes","title":"v1.21.0 (October 25, 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 SolutionLimit attribute (#2291)\nAdded support for MathOptFormat v1.6 and v1.7 (#2293) (#2298) (#2299) (#2321)\nAdded ScalarQuadraticCoefficientChange (#2296) (#2320) (#2322)\nAdded Utilities.modify_constants (#2300)\nAdded support for is_empty and empty! of Nonlinear.Model (#2305)\nAdded Bridges.Objective.FunctionConversionBridge (#2303)\nAdded Bridges.ModifyBridgeNotAllowed (#2307)\nAdded more sets for Utilities.distance_to_set (#2314)","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 test_attribute_TimeLimitSec (#2256)\nFixed conversion cost in objective bridges (#2309)","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 flakey link checking in documentation (#2297)\nMinor documentation fixes (#2304) (#2313)\nFixed [compat] section of Project.toml (#2310)\nAdded MultiObjectiveAlgorithms to solver-tests.yml (#2312)","category":"page"},{"location":"release_notes/#[v1.20.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.20.1)-(September-24,-2023)","page":"Release notes","title":"v1.20.1 (September 24, 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":"Removed incorrect kwargs in some copy_to methods (#2272)\nFixed ConstraintDualStart for Bridges.Constraint.SplitIntervalBridge (#2275)\nFixed MethodError when trying to modify a variable objective (#2278)\nFixed stack-overflow in Utilities.operate(+,...) with many arguments (#2285) (#2290)","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":"Added MathOptSetDistances to solver-tests.yml (#2265)\nUpdated Documenter (#2266)\nFixed various JET errors (#2267) (#2269) (#2270) (#2271) (#2276) (#2277) (#2289)\nVarious style improvements\nReplaced using Package with import Package where possible (#2274)\nRemoved Utilities.EMPTYSTRING (#2283)\nRemoved unnecessary const acronyms in Utilities (#2280) (#2281)\nRemoved invalid and unused method (#2286)\nRefactored src/Utilities/model.jl (#2287)","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-6","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-7","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-7","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-9","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-8","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-8","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-10","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-9","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-11","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-10","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-9","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-12","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-10","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-13","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-11","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-14","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-11","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-15","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-12","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-16","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-13","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-12","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-17","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-18","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-14","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-15","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-13","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-19","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-16","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-14","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-20","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-17","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-21","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-18","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-22","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-23","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-19","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-24","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-25","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-15","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-20","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-16","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-26","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-21","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-17","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-27","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_constraint_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-28","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-18","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-29","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-19","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-30","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-22","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-31","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-20","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-32","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-21","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-33","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-23","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-22","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-34","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-24","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-23","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-35","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-25","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-24","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-36","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-37","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-38","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-25","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-39","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-40","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-26","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-41","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-26","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-27","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-42","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-28","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-43","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-27","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-29","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-44","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-45","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-28","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-30","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-29","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-46","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}(\n terms::Vector{ScalarAffineTerm{T}},\n constant::T,\n) 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 (for example, 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 (for example, 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] (that is, 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 occurences 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, that is, 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, that is, 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, that is, 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, that is, 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/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/#1.-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/#2.-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/#3.-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/#4.-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":"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 SnoopCompile\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":"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":"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":"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\nBridges.runtests","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 respect 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/#MathOptInterface.Bridges.runtests","page":"API Reference","title":"MathOptInterface.Bridges.runtests","text":"runtests(\n Bridge::Type{<:AbstractBridge},\n input::String,\n output::String;\n variable_start = 1.2,\n constraint_start = 1.2,\n eltype = Float64,\n)\n\nRun a series of tests that check the correctness of Bridge.\n\ninput and output are models in the style of MOI.Utilities.loadfromstring!.\n\nExample\n\njulia> MOI.Bridges.runtests(\n MOI.Bridges.Constraint.ZeroOneBridge,\n \"\"\"\n variables: x\n x in ZeroOne()\n \"\"\",\n \"\"\"\n variables: x\n x in Integer()\n 1.0 * x in Interval(0.0, 1.0)\n \"\"\",\n )\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.MultiSetMapBridge\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 (for example, BigInt), or would not give infinite value (for example, 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.MultiSetMapBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.MultiSetMapBridge","text":"abstract type MultiSetMapBridge{T,S1,G} <: AbstractBridge end\n\nSame as SetMapBridge but the output constraint type does not only depend on the input constraint type.\n\nWhen subtyping MultiSetMapBridge, added_constraint_types and supports should additionally be implemented by the bridge.\n\nFor example, if a bridge BridgeType may create either a constraint of type F2-in-S2 or F3-in-S3, these methods should be implemented as follows:\n\nfunction MOI.Bridges.added_constraint_types(\n ::Type{<:BridgeType{T,F2,F3}},\n) where {T,F2,F3}\n return Tuple{Type,Type}[(F2, S2), (F3, S3)]\nend\n\nfunction MOI.supports(\n model::MOI.ModelLike,\n attr::Union{MOI.ConstraintPrimalStart,MOI.ConstraintDualStart},\n ::Type{<:BridgeType{T,F2,F3}},\n) where {T,F2,F3}\n return MOI.supports(model, attr, MOI.ConstraintIndex{F2,S2}) ||\n MOI.supports(model, attr, MOI.ConstraintIndex{F3,S3})\nend\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} <: MultiSetMapBridge{T,S1,G} 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\nBridges.FirstBridge","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/#MathOptInterface.Bridges.FirstBridge","page":"API Reference","title":"MathOptInterface.Bridges.FirstBridge","text":"struct FirstBridge <: MOI.AbstractConstraintAttribute end\n\nReturns the first bridge used to bridge the constraint.\n\nwarning: Warning\nThe indices of the bridge correspond to internal indices and may not correspond to indices of the model this attribute is got from.\n\n\n\n\n\n","category":"type"},{"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 (for example, within the solver package itself) or only apply in certain circumstances (for example, 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, for example, 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 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\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":"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":"","page":"Introduction","title":"Introduction","text":"A preprint of this paper is freely available.","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/PR2422/siteinfo.js b/previews/PR2422/siteinfo.js new file mode 100644 index 0000000000..2710ea918b --- /dev/null +++ b/previews/PR2422/siteinfo.js @@ -0,0 +1 @@ +var DOCUMENTER_CURRENT_VERSION = "previews/PR2422"; diff --git a/previews/PR2422/submodules/Benchmarks/overview/index.html b/previews/PR2422/submodules/Benchmarks/overview/index.html new file mode 100644 index 0000000000..7702bc2d42 --- /dev/null +++ b/previews/PR2422/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/PR2422/submodules/Benchmarks/reference/index.html b/previews/PR2422/submodules/Benchmarks/reference/index.html new file mode 100644 index 0000000000..4a28d1770e --- /dev/null +++ b/previews/PR2422/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/PR2422/submodules/Bridges/implementation/index.html b/previews/PR2422/submodules/Bridges/implementation/index.html new file mode 100644 index 0000000000..6a3828024b --- /dev/null +++ b/previews/PR2422/submodules/Bridges/implementation/index.html @@ -0,0 +1,32 @@ + +Implementation · MathOptInterface

    Implementing a bridge

    The easiest way to implement a bridge is to follow an existing example. There are three locations of bridges in the source code:

    • Constraint bridges are stored in src/Bridges/Constraint/bridges
    • Objective bridges are stored in src/Bridges/Objective/bridges
    • Variable bridges are stored in src/Bridges/Variable/bridges

    The Implementing a constraint bridge tutorial has a more detailed guide on what is required to implement a bridge.

    When opening a pull request that adds a new bridge, use the checklist Adding a new bridge.

    If you need help or advice, please contact the Developer Chatroom.

    SetMap bridges

    For constraint and variable bridges, a common reformulation is that $f(x) \in F$ is reformulated to $g(x) \in G$. In this case, no additional variables and constraints are added, and the bridge needs only a way to map between the functions f and g and the sets F and G.

    To implementation a bridge of this form, subtype the abstract type Bridges.Constraint.SetMapBridge or Bridges.Variable.SetMapBridge and implement the API described in the docstring of each type.

    final_touch

    Some bridges require information from other parts of the model. One set of examples are the various combinatorial ToMILP bridges, such as Bridges.Constraint.SOS1ToMILPBridge, which require knowledge of the variable bounds.

    Bridges requiring information from other parts of the model should implement Bridges.final_touch and Bridges.needs_final_touch.

    During the bridge's construction, store the function and set and make no changes to the underlying model. Then, in Bridges.final_touch, query the additional information and add the reformulated problem to the model.

    When implementing, you must consider that:

    • Bridges.final_touch may be called multiple times, so that your reformulation should be applied only if necessary. Sometimes the additional data will be the same, and sometimes it may be different.
    • We do not currently support final_touch bridges that introduce constraints which also require a final_touch bridge. Therefore, you should implement final_touch only if necessary, and we recommend that you contact the Developer Chatroom for advice before doing so.

    Testing

    Use the Bridges.runtests function to test a bridge. It takes three arguments: the type of the bridge, the input model as a string, and the output model as a string.

    Here is an example:

    julia> MOI.Bridges.runtests(
    +           MOI.Bridges.Constraint.GreaterToLessBridge,
    +           """
    +           variables: x
    +           x >= 1.0
    +           """,
    +           """
    +           variables: x
    +           -1.0 * x <= -1.0
    +           """,
    +       )

    There are a number of other useful keyword arguments.

    • eltype can be used to specify the element type of the model (and bridge). It defaults to Float64.
    • variable_start and constraint_start are used as the values to set the VariablePrimalStart and ConstraintPrimalStart attributes to. They default to 1.2. If you use a different eltype, you must set appropriate starting values of the same type. The default 1.2 was chosen to minimize the risk that the starting point is undefined, which could happen for common situations like 0.0 and 1.0. The tests associated with the starting values do not necessarily check for correctness, only that they can be set and get to produce the same result.
    • print_inner_model can be used to print the reformulated output model from the bridge. This is especially helpful during debugging to see what the bridge is doing, and to spot mistakes. It defaults to false.

    Here is an example:

    julia> MOI.Bridges.runtests(
    +           MOI.Bridges.Constraint.GreaterToLessBridge,
    +           """
    +           variables: x
    +           x >= 1
    +           """,
    +           """
    +           variables: x
    +           ::Int: -1 * x <= -1
    +           """;
    +           eltype = Int,
    +           print_inner_model = true,
    +           variable_start = 2,
    +           constraint_start = 2,
    +       )
    +Feasibility
    +
    +Subject to:
    +
    +ScalarAffineFunction{Int64}-in-LessThan{Int64}
    + (0) - (1) x <= (-1)
    diff --git a/previews/PR2422/submodules/Bridges/list_of_bridges/index.html b/previews/PR2422/submodules/Bridges/list_of_bridges/index.html new file mode 100644 index 0000000000..bcf932a5b0 --- /dev/null +++ b/previews/PR2422/submodules/Bridges/list_of_bridges/index.html @@ -0,0 +1,114 @@ + +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 not 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\]

    Formulation (special case)

    In the special case that the constraint is [2, x, y] in CountDistinct(3), then the constraint is equivalent to [x, y] in AllDifferent(2), which is equivalent to x != y.

    \[(x - y <= -1) \vee (y - x <= -1)\]

    which is equivalent to (for suitable M):

    \[\begin{aligned} +z \in \{0, 1\} \\ +x - y - M * z <= -1 \\ +y - x - M * (1 - z) <= -1 +\end{aligned}\]

    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
    MathOptInterface.Bridges.Constraint.SOS1ToMILPBridgeType
    SOS1ToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

    SOS1ToMILPBridge implements the following reformulation:

    • $x \in \textsf{SOS1}(d)$ into a mixed-integer linear program.

    Source node

    SOS1ToMILPBridge supports:

    where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

    Target nodes

    SOS1ToMILPBridge creates:

    source
    MathOptInterface.Bridges.Constraint.SOS2ToMILPBridgeType
    SOS2ToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

    SOS2ToMILPBridge implements the following reformulation:

    • $x \in \textsf{SOS2}(d)$ into a mixed-integer linear program.

    Source node

    SOS2ToMILPBridge supports:

    where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

    Target nodes

    SOS2ToMILPBridge creates:

    source
    MathOptInterface.Bridges.Constraint.IndicatorToMILPBridgeType
    IndicatorToMILPBridge{T,F,A,S} <: Bridges.Constraint.AbstractBridge

    IndicatorToMILPBridge implements the following reformulation:

    • $x \in \textsf{Indicator}(s)$ into a mixed-integer linear program.

    Source node

    IndicatorToMILPBridge supports:

    where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

    Target nodes

    IndicatorToMILPBridge creates:

    source

    Objective bridges

    These bridges are subtypes of Bridges.Objective.AbstractBridge.

    MathOptInterface.Bridges.Objective.QuadratizeBridgeType
    QuadratizeBridge{T,G} <: FunctionConversionBridge{T,MOI.ScalarQuadraticFunction{T},G}

    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.VectorFunctionizeBridgeType
    VectorFunctionizeBridge{T,G} <: FunctionConversionBridge{T,MOI.VectorAffineFunction{T},G}

    VectorFunctionizeBridge implements the following reformulations:

    • $\min \{x\}$ into $\min\{1x + 0\}$
    • $\max \{x\}$ into $\max\{1x + 0\}$

    where T is the coefficient type of 1 and 0.

    Source node

    VectorFunctionizeBridge supports:

    Target nodes

    VectorFunctionizeBridge creates:

    source
    MathOptInterface.Bridges.Objective.FunctionConversionBridgeType
    FunctionConversionBridge{T,F,G} <: AbstractBridge

    FunctionConversionBridge implements the following reformulations:

    • $\min \{g(x)\}$ into $\min\{f(x)\}$
    • $\max \{g(x)\}$ into $\max\{f(x)\}$

    for these pairs of functions:

    Source node

    FunctionConversionBridge supports:

    Target nodes

    FunctionConversionBridge 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 ensure 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/PR2422/submodules/Bridges/overview/index.html b/previews/PR2422/submodules/Bridges/overview/index.html new file mode 100644 index 0000000000..f3e7a94d88 --- /dev/null +++ b/previews/PR2422/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/PR2422/submodules/Bridges/reference/index.html b/previews/PR2422/submodules/Bridges/reference/index.html new file mode 100644 index 0000000000..c963c70109 --- /dev/null +++ b/previews/PR2422/submodules/Bridges/reference/index.html @@ -0,0 +1,226 @@ + +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 respect 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
    MathOptInterface.Bridges.runtestsFunction
    runtests(
    +    Bridge::Type{<:AbstractBridge},
    +    input::String,
    +    output::String;
    +    variable_start = 1.2,
    +    constraint_start = 1.2,
    +    eltype = Float64,
    +)

    Run a series of tests that check the correctness of Bridge.

    input and output are models in the style of MOI.Utilities.loadfromstring!.

    Example

    julia> MOI.Bridges.runtests(
    +           MOI.Bridges.Constraint.ZeroOneBridge,
    +           """
    +           variables: x
    +           x in ZeroOne()
    +           """,
    +           """
    +           variables: x
    +           x in Integer()
    +           1.0 * x in Interval(0.0, 1.0)
    +           """,
    +       )
    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.MultiSetMapBridgeType
    abstract type MultiSetMapBridge{T,S1,G} <: AbstractBridge end

    Same as SetMapBridge but the output constraint type does not only depend on the input constraint type.

    When subtyping MultiSetMapBridge, added_constraint_types and supports should additionally be implemented by the bridge.

    For example, if a bridge BridgeType may create either a constraint of type F2-in-S2 or F3-in-S3, these methods should be implemented as follows:

    function MOI.Bridges.added_constraint_types(
    +    ::Type{<:BridgeType{T,F2,F3}},
    +) where {T,F2,F3}
    +    return Tuple{Type,Type}[(F2, S2), (F3, S3)]
    +end
    +
    +function MOI.supports(
    +    model::MOI.ModelLike,
    +    attr::Union{MOI.ConstraintPrimalStart,MOI.ConstraintDualStart},
    +    ::Type{<:BridgeType{T,F2,F3}},
    +) where {T,F2,F3}
    +    return MOI.supports(model, attr, MOI.ConstraintIndex{F2,S2}) ||
    +           MOI.supports(model, attr, MOI.ConstraintIndex{F3,S3})
    +end
    source
    MathOptInterface.Bridges.Constraint.SetMapBridgeType
    abstract type SetMapBridge{T,S2,S1,F,G} <: MultiSetMapBridge{T,S1,G} 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
    MathOptInterface.Bridges.FirstBridgeType
    struct FirstBridge <: MOI.AbstractConstraintAttribute end

    Returns the first bridge used to bridge the constraint.

    Warning

    The indices of the bridge correspond to internal indices and may not correspond to indices of the model this attribute is got from.

    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 (for example, within the solver package itself) or only apply in certain circumstances (for example, 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, for example, 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 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

    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/PR2422/submodules/FileFormats/overview/index.html b/previews/PR2422/submodules/FileFormats/overview/index.html new file mode 100644 index 0000000000..a916d60fcc --- /dev/null +++ b/previews/PR2422/submodules/FileFormats/overview/index.html @@ -0,0 +1,147 @@ + +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": 7
    +  },
    +  "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);

    ScalarNonlinearFunction

    By default, reading a .nl or .mof.json that contains nonlinear expressions will create an NLPBlock.

    To instead read nonlinear expressions as ScalarNonlinearFunction, pass the use_nlp_block = false keyword argument to the Model constructor:

    julia> model = MOI.FileFormats.Model(;
    +           format = MOI.FileFormats.FORMAT_MOF,
    +           use_nlp_block = false,
    +       )
    +A MathOptFormat Model
    +
    +julia> model = MOI.FileFormats.Model(;
    +           format = MOI.FileFormats.FORMAT_NL,
    +           use_nlp_block = false,
    +       )
    +An AMPL (.nl) model

    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/PR2422/submodules/FileFormats/reference/index.html b/previews/PR2422/submodules/FileFormats/reference/index.html new file mode 100644 index 0000000000..b0d4923b38 --- /dev/null +++ b/previews/PR2422/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.
    • use_nlp_block::Bool=true: if true parse "ScalarNonlinearFunction" into an MOI.NLPBlock. If false, "ScalarNonlinearFunction" are parsed as MOI.ScalarNonlinearFunction functions.
    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/PR2422/submodules/Nonlinear/overview/index.html b/previews/PR2422/submodules/Nonlinear/overview/index.html new file mode 100644 index 0000000000..9e171db9f1 --- /dev/null +++ b/previews/PR2422/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],
    +       );

    The ordering of the nodes in the tape must satisfy two rules:

    • The children of a node must appear after the parent. This means that the tape is ordered topologically, so that a reverse pass of the nodes evaluates all children nodes before their parent
    • The arguments for a CALL node are ordered in the tape based on the order in which they appear in the function call.

    Design goals

    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 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/PR2422/submodules/Nonlinear/reference/index.html b/previews/PR2422/submodules/Nonlinear/reference/index.html new file mode 100644 index 0000000000..dcf26bf864 --- /dev/null +++ b/previews/PR2422/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 (that is, 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/PR2422/submodules/Test/overview/index.html b/previews/PR2422/submodules/Test/overview/index.html new file mode 100644 index 0000000000..21e8b64832 --- /dev/null +++ b/previews/PR2422/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/PR2422/submodules/Test/reference/index.html b/previews/PR2422/submodules/Test/reference/index.html new file mode 100644 index 0000000000..ab89a09e73 --- /dev/null +++ b/previews/PR2422/submodules/Test/reference/index.html @@ -0,0 +1,52 @@ + +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",
    +    verbose::Bool = false,
    +)

    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.
    • verbose is a Bool that controls whether the name of the test is printed before executing it. This can be helpful when debugging.

    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,
    +    verbose = 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 (for example, 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/PR2422/submodules/Utilities/overview/index.html b/previews/PR2422/submodules/Utilities/overview/index.html new file mode 100644 index 0000000000..07c2dab6eb --- /dev/null +++ b/previews/PR2422/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/PR2422/submodules/Utilities/reference/index.html b/previews/PR2422/submodules/Utilities/reference/index.html new file mode 100644 index 0000000000..c63e24c002 --- /dev/null +++ b/previews/PR2422/submodules/Utilities/reference/index.html @@ -0,0 +1,296 @@ + +API Reference · MathOptInterface

    Utilities.Model

    MathOptInterface.Utilities.ModelType
    MOI.Utilities.Model{T}() where {T}

    An implementation of ModelLike that supports all functions and sets defined in MOI. It is parameterized by the coefficient type.

    Examples

    julia> import MathOptInterface as MOI
    +
    +julia> model = MOI.Utilities.Model{Float64}()
    +MOIU.Model{Float64}
    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 supporting all combinations of the provided functions and sets.

    Each typed_ scalar/vector sets/functions argument is a tuple of types. A type is "typed" if it has a coefficient {T} as the first type parameter.

    Tuple syntax

    To give no set/function, write (). To give one set or function X, write (X,).

    is_optimizer

    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.

    VariableIndex

    Examples

    The model describing a linear program would be:

    @model(
    +    LPModel,                                          # model_name
    +    (),                                               # 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,                                            # is_optimizer
    +)
    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 take place via the MOI interface, so the types O, V, and C must 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 take place via the MOI interface, so the types O, V, and C must 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
    MathOptInterface.Utilities.loadfromstring!Function
    loadfromstring!(model, s)

    A utility function to aid writing tests.

    Warning

    This function is not intended for widespread use. It is mainly used as a tool to simplify writing tests in MathOptInterface. Do not use it as an exchange format for storing or transmitting problem instances. Use the FileFormats submodule instead.

    Example

    julia> model = MOI.Utilities.Model{Float64}();
    +
    +julia> MOI.Utilities.loadfromstring!(model, """
    +       variables: x, y, z
    +       constrainedvariable: [a, b, c] in Nonnegatives(3)
    +       minobjective::Float64: 2x + 3y
    +       con1: x + y <= 1.0
    +       con2: [x, y] in Nonnegatives(2)
    +       x >= 0.0
    +       """)

    Notes

    Special labels are:

    • variables
    • minobjective
    • maxobjectives

    Everything else denotes a constraint with a name.

    Append ::T to use an element type of T when parsing the function.

    Do not name VariableIndex constraints.

    Exceptions

    • x - y does NOT currently parse. Instead, write x + -1.0 * y.
    • x^2 does NOT currently parse. Instead, write x * x.
    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, for example, 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,
    +    ::Type{T},
    +)::T where {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}},
    +    ::Type{T} = Float64,
    +) where {T}

    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 (for example, 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, that is,

    • 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
    get_bounds(
    +    model::MOI.ModelLike,
    +    bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},
    +    f::MOI.ScalarAffineFunction{T},
    +) where {T} --> Union{Nothing,NTuple{2,T}}

    Return the lower and upper bound of f as a tuple. If the domain is not bounded, return nothing.

    source
    get_bounds(
    +    model::MOI.ModelLike,
    +    bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},
    +    x::MOI.VariableIndex,
    +) where {T} --> Union{Nothing,NTuple{2,T}}

    Return the lower and upper bound of x as a tuple. If the domain is not bounded, return nothing.

    Similar to get_bounds(::MOI.ModelLike, ::Type{T}, ::MOI.VariableIndex), except that the second argument is a cache which maps variables to their bounds and avoids repeated lookups.

    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
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RotatedSecondOrderCone)

    Let (t, u, y...) = x. Return the 2-norm of the vector d such that in x + d, u is projected to 1 if u <= 0, and t is increased such that x + d belongs to the set.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.ExponentialCone)

    Let (u, v, w) = x. If v > 0, return the epigraph distance d such that (u, v, w + d) belongs to the set.

    If v <= 0 return the 2-norm of the vector d such that x + d = (u, 1, z) where z satisfies the constraints.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualExponentialCone)

    Let (u, v, w) = x. If u < 0, return the epigraph distance d such that (u, v, w + d) belongs to the set.

    If u >= 0 return the 2-norm of the vector d such that x + d = (u, -1, z) where z satisfies the constraints.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.GeometricMeanCone)

    Let (t, y...) = x. If all y are non-negative, return the epigraph distance d such that (t + d, y...) belongs to the set.

    If any y are strictly negative, return the 2-norm of the vector d that projects negative y elements to 0 and t to ℝ₋.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.PowerCone)

    Let (a, b, c) = x. If a and b are non-negative, return the epigraph distance required to increase c such that the constraint is satisfied.

    If a or b is strictly negative, return the 2-norm of the vector d such that in the vector x + d: c, and any negative a and b are projected to 0.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualPowerCone)

    Let (a, b, c) = x. If a and b are non-negative, return the epigraph distance required to increase c such that the constraint is satisfied.

    If a or b is strictly negative, return the 2-norm of the vector d such that in the vector x + d: c, and any negative a and b are projected to 0.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormOneCone)

    Let (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormInfinityCone)

    Let (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RelativeEntropyCone)

    Let (u, v..., w...) = x. If v and w are strictly positive, return the epigraph distance required to increase u such that the constraint is satisfied.

    If any elements in v or w are non-positive, return the 2-norm of the vector d such that in the vector x + d: any non-positive elements in v and w are projected to 1, and u is projected such that the epigraph constraint holds.

    source
    distance_to_set(::ProjectionUpperBoundDistance, x, set::MOI.NormCone)

    Let (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.

    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 guarantee 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 guarantee type-stability.
    +
    +If you want an iterator of all current outer keys, use [`outer_keys`](@ref).
    source
    diff --git a/previews/PR2422/tutorials/bridging_constraint/index.html b/previews/PR2422/tutorials/bridging_constraint/index.html new file mode 100644 index 0000000000..c2bbce9059 --- /dev/null +++ b/previews/PR2422/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/PR2422/tutorials/example/index.html b/previews/PR2422/tutorials/example/index.html new file mode 100644 index 0000000000..7e62a60b20 --- /dev/null +++ b/previews/PR2422/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/PR2422/tutorials/implementing/index.html b/previews/PR2422/tutorials/implementing/index.html new file mode 100644 index 0000000000..ae3258550c --- /dev/null +++ b/previews/PR2422/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
    SolutionLimitYesYesYes
    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
    ListOfVariablesWithAttributeSetYesNoNo
    NumberOfVariablesYesNoNo
    ListOfVariableIndicesYesNoNo

    Constraint-related attributes:

    Attributegetsetsupports
    ListOfConstraintAttributesSetYesNoNo
    ListOfConstraintsWithAttributeSetYesNoNo
    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/PR2422/tutorials/latency/index.html b/previews/PR2422/tutorials/latency/index.html new file mode 100644 index 0000000000..bd791920d1 --- /dev/null +++ b/previews/PR2422/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 SnoopCompile
    +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/PR2422/tutorials/manipulating_expressions/index.html b/previews/PR2422/tutorials/manipulating_expressions/index.html new file mode 100644 index 0000000000..5428202bcf --- /dev/null +++ b/previews/PR2422/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/PR2422/tutorials/mathprogbase/index.html b/previews/PR2422/tutorials/mathprogbase/index.html new file mode 100644 index 0000000000..b832e9b6ce --- /dev/null +++ b/previews/PR2422/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

    JtQ16JcKgP_5yGAbQCIEzHMbrnyzEwzS=ASKWn`iU(zLBRDhX>#gjxg~qeDT4 zn)F^01!gO@F{;{Df3I<=`9jUUO~F0DxAl_ z$9$Kzo{SBbHkiQdz~{r8V!YZF#OoBD8f{JILy@l6$Th+D$O6w!maM0-AC}#E?kl^- z+CgHIQKjC)VX;<=8|Q3+&Nyas@|tR0T3*BGcI4F&GtyM_CEj}9D5v41$j!^v$At{< zXDblxL{XxcXPay&XQ}4%UAjz@r$S6G0(Gx_%T?g%3@lrke?ow%KtJ#;nhY%eK?`vH zPR9TLT7Zd({l5cVc4JM(ZnE9o)Xu@D?;E`W!4!7N;^wuYcu{*&1d{zB5lO;(|G-UT zCJ~X+tbM8XUqKosJpC#-dNN5|4BP%1yxCswI})jzxIEu~EV>IB`jI@yYfMs;2 zA36{*^2K;hBG>war3WYrdW0AZM0LCPF+dL(uJQG9ILQ+I`JUhK%j}tNL-cs&)nUF- zgTMyy$0baJGyW81I@74#vt_9#kNL|~&QU4cm52|1o|q+_oEQbK2~<<&IEMdjQCg=^}lL}OK= za-bmTz(3>wX}%-pMFsx$bVkfA+PD_Do{>IAXQFaUA3?(xH~h3o+4apLO8nN@!Fhem zd{QhL)+0`I54_-JCKgs=w2&2iLy0xx)JGzuqA3SMYCfr8Z3}x?F)D%k-L#&a`RSyu z%n*Sv9Wkl8FPzJ)0FQ8oieU#yxk{C2%u>IDpvHObgG|g!435TVdhvjtcdRZw&B})J1 z7hiCw+um9SwOFg}>2gE-N$Y#u)|vs;v>_a!oE}Hy!b*qvOuWf3*TYq%rcpWazU?jGW=IS2D5Wu+0MLirH zqPPcNy$^wr3Y!Fr3iG1UCaC@rv0$^Zr}Ucdj8dW{y~UfyrVsTuOxW+@xzl1TLvq_l z)oRbwhj@uMI}o+HQAj#SM+O)vbyPT@B1$c{@F!B8b0a%`n3fXFZ88cUmWT;gtc@EzCjTQPev@ zFRk{51J(=x>=0X8i^UHD~0p=k|fjRp9jx4my&$vAM8R{bjf$qFzhE zTQ$hhLtWev?^tN$hcvTLpX`Dvg)9(b!bX8xSAW&meNr(n_RMz zeT=O%`NTywST<$xT3%MYqEWgkiutyooT3N<*k7p8qE4`k?z=CVvDFz{TJ2?wf!5cR z$Q{j-9JYy#MbvUlOpQ9ShEZtGZXqvcA9`Oe_!C|U$%;v5%jL{K6uhP396Mtf-6(|T zHf}TAjEXfDF)^-*l1`1Z_TM1}Zs#ecj@&S=q4DBIMpBC^(I1e6CLX1wV)sV4uBuL@ z4k`7wl{^E=_MV`c$elSjXfEkBTlE?1U6E-Af4r_#ejj2pnbkbum5iEwSBQnw!eEh(9e9~3);@oL-x+hYkr=&}3EKsN z7xu5h=PY(WC$R^kIhD~7iNicgqHCTPt=*JIMg>9U|7M$}_<11uGp8G7ts?d-!g<@2 z{Ewjcuse>ZDX4z=VZ~JEIorR33Jj`sR2X%v07z4qN=}io&xt=wxnu|aH*s6kRcA01M&sD*Ac%$)bXVddiZP)EmSN?X+CK}ItqFbM=K-+%pT@{I znf~t}DHAKpf4NYhH5q%!hP3^nb_SkFs6oT)4-M?P>*{~yINwQ7*-uhQL-x}veotBP zRJWzd-6+4AT4s1(=dKRlg7d4~?;aFbja>Y+5P9CE$?}f zFg{)1V?!;o#GP?Jc{slx&N^;BD8n6O!(S9Pq+vb$Q&6)2zjrbs^KP*)R(1P=2n2?p zY~?tG1QDI2Ff{;Bnz+2g5=lfIi-cn;ne>x_XaS zhS~S6E?-2Z;(Pg%vj^TKv$rCCJj0}f^zZ`Gp~Owl++iT0EAUeQ0DKi1ux(%8I7EW}fbUj7Ct$-o z1@!6$*}Ijs^_beq^)Fj=7N!$k_dQ;rJ6NC4TA)%={;>Bg#Ez5D{dpm*_Ic<7B)oO3lthB0tZ8ixpmROaO%@)P#BM(a zF;|PFp2Ro?N>AZwy6mUoZ*BU-51O?1h`m(m`(ydL>_`{lAox898c>MAo6s}>P*60c zp)J!(Zk56#VpEN3rRLt2B}&>;68O2bDr0bW5=|(Q=cKTB4-$cQfNe`hNy?4f{=qmh zy}V2)hDdP)`Q<}eBrG;xs3c8NxuSwF`%?8_A3ywpouUikXOr>OBu#REB?YJEdcuSM zohwU(3p~-s&uIq{i?UE65HVwl+u=2Az**6>k1oUNRJjaz{OB zIiKdl*=F;WnvvP2r=ou=nDvM%&QO@Q-SOaxQPBkDyixDl&OYX3TJ80t*QM)sx0E2E z$^Ru9HMUGRCcSDJU0t%34wR|U0AB>RGc#yY3G=H`^gKNsmHO_c7De28!l$wa5tnL}L zB9%ZB2AJG+H`e<-)6+yjCRX42rQPCY;jh>^bOkkuhREplZWFvR*EX5eQx`#kb`a5vCJTbpCJc6wWgAE|acmYeAdE%^a+wfJqx80tLkqByOTvSq^PK9P zi&f4o$zRcP8I^Lg>4e_?{^zUMB6?JfucLTjUOBpSxx&P%5Cn5RB`p9cL-#UpCX=|s z@^}xI%mx|d)Ojdpfj%h3cGiI}7hNj#I4oiwS&we5P4BY=V2br*F&Jz+TuOE;HDT|a zmN1s70BFAd_cYvpvxUfhK=R0LIKB`&-{w7gRD*Gq?PSFi^!~XnzlCC@DN>!*X$_Lg zeZev)xndX%bNHW`500qXGMP$Vox7x(olzjif?^Yr{NvHRxtxyiA=U6-OG#&9eBmZ@hgz=^mT%k@dWj)GmB7GAfER5cg<)74W6_j3I1DC+nq_fG#7dTfSgb)sMSS>F-vD9g&!Ma}pW&v4onPv5^?-d?N4(40TmC(B?MjtlG#3^PsHEg0Z?-+h<2+gb^d(%N15)3FqjJ4 z(6aaiLLyIoU|EINcwSPaJa}rD*qsjZuG&y37$%zsPd&FCZ1nKY$9@luBtvG2Futlm zA-a&}P9Xh&%rd>^vrXR;(|j5(1`X|s`O1D_@z53Gt!Kt0jrdxMJCb(_ilos%MzeGR z5%Ftfrvzc_eC~4^yB*&I(iLfJr-HLfdp+Z7fRo$wq7|fpUYK=Sc^U1!<|@|^c*MyGg3+8{t0uq-zsvtVwJ(;LWg zG3Q3;nhUM)5VR(Yvhbfr(TW>oOqE7fw?f| zKcGu`P7*!Tp4uDRDT-1a8>q0UM_eablE_1y99n=#PfWopruvAX=4WV>q!gX_pB3eKjy)NJC=KgWZCy_UMmjI`S z(9W;+)0_`ZS*G7UFX47HMwu$_b5UD;endb11ok>iXv&8k5Ro+Fswz6?nJ!miZnEP< zWT!sY5RKK>%CyBB`kes|;P{ghbH*aehTt)?-0fL&c+UCvYN&`+xkr=05mk;rcYX;J?uQXnnV*~r^wisKAv1?S*XA>Q2LG2Qj^ zYLI0F3TY(S-1Ycl&IyJ^OH|QyxUU0Ciz1UbY0`JY6v^|#0rLj+IR~AOU6t1Y_zS$` zk2~9cGTNBg|F6-;{$J+$hkt>MB^}>1JbMipqR zrynq3vH333sopQ@dLW|jQ==>~2h&V;1Zc3CSq138^E&Gob`B;RcNd@tH0=n>!ymp& z`yH1LRF};MJnJpeu87t5&E8YOG|}rM7-MySv@J2hk1&y^NtRhq{WNCf+Cy(yIyJyG z+Dpke@5N-USK*gUjA;&(2(J5%<=$F*ZX2(hpqjTeXa1K|o#fb|2<9<`+hoO?oL7y+ zY(eDnQ`cg?#9rA$O&Z&eNs{qWyI#^y^}ShRxzEazZ)acl?|hirj8k98&RD~P3kv*} zdX~-L3F-m8(uz|=qPYz3SFEEr%Lap=2l5!vl{a~)al z^Ng!5UB=&zCRlH(2Uln$poy5AHC*ft&v}R)mRY^RIyv%b4c7xl|PsSnU}T_hCS_ z8!i)yrR1SU1l`~TWwCrHXbFcxTWvTP11Y7e!8dZD$sr}L960JjHPXW)X#}AzNLtV+ z8n7tMCs%1)JqY}eIIAk5NbONCkT7Zk$zR3={H9DRBOwCOriGoz+Gw;hz|ICf8m23Y zmyDwm&^b+xTB6&@fJ+%;wC4Vbx&+#l#}yed(=MaV?4q$`h{3vxd83e1ILkt$|J#@V zZ!Z^gtKB9uAet@-PAU59vbUjvR%T&l?W$J&*fiEv6h-wVGrF+FkiT7IBP*Y*CV(d` z%|WWyf_9wlzufIEF$HF0IyptiF>#q_i8l_PsMG^*OR(_drB1TLyuPSwKwsc&&}4wu zE5QWdyB!K1MkpMmz>-8EnHW)l+%V!#+Z-^Y?3nGLWRY=GN_pa2eKj^MK6*Fax24ID zWZtXWl;LQ+{l^X)2&a{BQP6GjULK1`h*N&eK_vm&=&U}9lo|=jZOm|7w@7QZw)zSb zaWp-#IG8km37bPznTnVhVwplt&QKM`7VwVU2~U02V?c=y6#@OY2!w&Z98P;jonM>Tj-S1>O^dr&&Qdb09<^h5XK~y4-(e9PK|^wA?-0WnJQ#*Yzhd4$%ru5URyz+qt?a;Z~Av`Xa^|qym?i*Rbd=V@7 z*ke;G_ah;_f9sC#lxO@nPs}y>LL-U3Pr9`)V4jh? z_yy!-7Yqu1RT2)|HdyxD_Q@>Q7@4m{727#u387;e))HS1acYE6_Ytq)e|T8{nzEWu z|9l&*&v5D|TIX1tenoq^?!%hX+I{p(4vjXQg}dZX*flCFSv;TP-AjUUO5ee6-!a z`O(H*h8pF1(z2-S`f%+KUM)GCa1oFg>p?n#X5ZRe3{1RG7TWW4331AVi^q7_xt##N zj6sOon~&PEf#3oH7-;*EV@u(gRdSJ09w<27@9Rg?sD%M1I&TdtMqP?_r}Mn=@EUKu z(K15Ypk6UdX^`GJ9Ap(XNB0j^>ZAPJ^m5Xal@kOzVBcO{VxXm%OW(ZsP|K&*x$u_K z^12hxAj+}h-?GEBT1TM`H!Rwwww5+{2Wc5-O}Xk!@2MRH-@7XHd0uPf4@L@2!8yZ+ zB&L=p3}D{IQ@7+a-8(aDyC{oPbL@!irmUmVmp%61^S}T0yO)t7K4>BWOv_UFIi|~7 zDoM+c3R(lBn?eO(nI_@Vu!$_^B@|!7L(F!u%eOAeddQ10eZ^{$7SaNI@9T9l>H;Nr z9X|POsTldasL8NYk?2m-lTC4G&yz1e7TTNY+&@i{uiLY?FDF%vT8Lsy^*{Yp*h!E4 zZ7WA2*d!?gu}hNicjdR=)ZV+Ho@I2J8vC8@PbS-Za;K~kK}#kzml{sD3(ih7;)jSe zY!h@_#~KuHsMY23>vHWMhDI0FFo(9rURs`9xTm8!>&VV)P(LaCUG3pE!ToQ5&+PrT z_j)d^0Jx5zS0?W~zUVzyHPWo2S?7aqQHU{rTfcySdb`Zl(_EiT*UPl@{q1zmw za`8BNC%4Gk&nL0G1Wv5fZvluOon@Y`s5zAa_XQW_iz8eA!JlX4+=P~?afX%s;pl=O zM#R@g*ZtSN{>&c}e*O%*wGC_mWH7k$*J_IFoI@EZY10d_PbZ||kfw5caN1qIV?OAz z7H@bCD})_UInHeZTUNwqYyh@@XiKTz_H@edtVmiCihPs5;)#z}l?^oZn=j>TmwtgP zXlC7_bHi{NT;X=>ckEU-k`adzef#+Ktj2R#US4lb`TNE=+-h*GDyq82fCPzg&dwAdE?LT5I{t_;(_nDI6b!(4D*<% zR6`S3PW( zVGrQu0opER@jH3?_M+j-1z8~5-rv-oeO|IwHc|sTS6#Hs);({v`6hQb(5d6BDO_B< zbnZwJ>^!PC#tIrfN^9D8((KSv5CiWy>%LU>rF=)MC_RD8K<|_#B|x?n(uUWkCXp(g zj3z&%bb#Bv8`A$=>vavg!iQ#k4TzJ4Sba`>$PL-71k}uLd@Ni|ailU!o4dz1Y-u{e zG~`+e$&%(;Gi8HiZhcJ0BF978#^ZCykR=zz&%+C*V4LVzn~*QBA3e@wPSn9@dEsnY z=)jO+xvksMksU&Cb8q14T3! zMOkySP|9G(+HBk(8)eO$ndM`OkWX{C&O3XZtS%@BZr=QZE#vR}$uPs_;fSbxEpcAu z)eopxv<43}mm!(MYHO09d;YCb6t@_K!MVfJM(YY%UeB5V&>}(y#)z5#T1150Jn}dE z+q%B|n1b$@Pl&=I+K8qdWFln~$Wy6p@Sl`$q|HrU0uIRVW+2=L(>tee2eO}1@6pkXvxj!-Pb5fj2h-Z37k1WW zKVsp1PILYXm>3io(7B2uAaaFDs!c8wSHlt0fIcdB$8LO*#1S~9B5 z$es&oHx-Bh=UiH=86_EQ0=M7|kh``FL=!ASPtOz*41TZ^R4ef1wWP;;=A z-H(69(0b#_$cGtU^F0FHJE^&xo*$|3(T8t5-!IM&#ix(hQUkPE@C3rHgYsq~@KV(PKn|cbxRL20R?H^_MyY883mI2h zDB1ndG-kQizuc^Mop0iL^bvX4@v&)tQqyqISt#zQwHS7hX#Ge&EiL|_za9!Lp#Kpl zl1Z;s zE;#gzhVraDeTGWOHc)A--}Q|`CJ{Sw_Lf3VH`YiXr7kPR8*6ZkGk}OI(l~%7v`R%S zB1X10)$o_)>hj{91kxWox*cms9s#eXX`TpDPt`TaF)3fCR!0*DKJl8PDL#YBDJHq$ zZ)$>ll$M(I1z7Hw$w{@c@X8TvNz9g=RcpR%SJj&hDpU1KfR(PSH3yzow55NbIqrAO zEQU!p)1X?JMb%Xr+6HFLcs7I$rpx!hib9vHb_|G85;2TNsqEGh&D7IaPaw7cPv^ z^zZY(9s+(^5wI1J6Dcj_bpHOyPtH-jpxsGq2}?7ZM3P8Ad5chd{p|(q`uK45@cD33 zcQ;N2)H%L<`;gy($NGVeiUM>0kF|5P<9FrjwXcok9s6oNlQJ-RU>0V##z(zh7Y5)B z_Zt4yxJ(osaL3&v_Zs{i#xio1+Z?ahRJis1@}igHj#MX3j0$|{Hewmd)5s!u9Wun_o_kGDrt-6_c*R`oVa-_vH;FE@`gTg zrl3DBs>oE9Aka-Zz_c!D^zuNyQD*hFQf1o|pqQhGQoB#sA?D*a0t^d@yj)|_(3Yi= zK0jq4)gD|{M6%yN`%$1#1;xu@zyIhkt!WyZ*X_guF+#Bup8JNm`P#+GAS+~l9}yUO zS)J#QK_O{A0ui+Sj(Fx@HkY?{DZ+qaW9?GbXK|Dma7WX?UinR_US5IMB2b+wD^`9w6uD>Q_Qta;MX zKIbWU=lV7DNJPTSNAJ}$SVR~mv9QRbySBnElKR zSc7vK1&O4P7eONc=!wz`w4uNYp1+7hrM0I3HL-&)8||fpB4$(jMxR>5VqYRMQ*)p-QnNr@^w{PB zgZ80}O-4Nt@8Lt<^D^0VW{v30lqnM6Uc;)bZD=lLE~1xqYvEg-ygANmOqK61n{<8x zYpIsc1sP%Ry2xl%uVBHp1moG{Jfl5PADMGd;l zjzx`LhmL~4(8XNn7~~PO0he>?WyN27BXLLjt-G0C>my`-Mx)i%wpq4?ONCpwqNIOt zyQcs$SZar^+E}oU;7h9yVjh@dJ(T{+b9WW{0=gdZFCd?3 zw+X*v`3?XfMYz=S%5yA+g%{{2xcBq{FJRe|{R~&oqi3|typn{zs+&k57VspE&OoI6 zfj+u`QYts>y-WBorw|%_aEzod-dBs-ouU;jtEnhe_X%hUodoN2=}GYZXPB}SFQFNY zDJ$x~%Vo+Wig*zPL$p-qY7Iuoox}+gyOd2O*N}=?b!MUXvxifjh9v4r?pPX$IhL8l z(8qy#@zm|9q^FHk23emuXz-E^5Qs83jejs*BbX7Wbu0p6?GV#LlX(t86NcN0_)#} zrmsCI+E+h|anUJ%^PB0Bky*O6ztlM7*bYd=tRshxdgo#!%OS#e*)Jg%#vK}k=V`fN zUMbb(JO?@Q@@@|6Xh&%-8L@4hX5VeTpo}NRTb2Cq;tStpwom8IZ>PXOFiP3wSHLe= zGeUmT{OvP0mu9z*=3=a!y?WXc%ODpugMCtsnq9pFX>19Xr1@u=Qrt;)lRib!iDGIw zGetb#PsS+aY)HBr4%37!W~*&-{6-Y<#6J%VB1as6Y3dbtP(vJOJOfu!WO}Nohlg2YuuD=&-(rrWKNyGlo!sJ18caFED!Sbbk=DiHb5 zH5KuQxlXLa3~np&m2Rz5t>jMvYRnL6+%={Ml5X15dCa?AnF8bvKg%#w1MkZ)mX9%& zm<&P=>NW>_=4xeJkSwe;BGG{w-0rUPd0Z%$nF7diHNM-)pkERqWHwW zY<7~8P4S@M+TNH-jd2VZ^8ejUW{0PD6=?IGF_9lP*k>$8gqND%YKxi2uhHTOKDF-? z`rIB{0XDAo0g2!5@Eu{LUozc%B7RJ@FI-6A-Zb?A6K=m=7D%IYi^2m-HM0)qJ2k#! z)2>usC5d z>4z-p-`{=D0=5bLQXaR=pZfoY@_6_CbvGK7Z2szT7*?bli9h+n{k=SD1{y2oe{!0F z&%vt|$RHNx`~Bx0d8GG*^W;_9AL3Bs`}Oq0PL7HB_5A7y%WWi49}miHDxTy-`jKi# zo9gIC#S^~LYRspr;{0;QBBg%2|YCzdT8PC4VoZjo(MwgF=-}`O3 zC1T3l2!4~AAeP(f<%iN4!Q6oQ$uLAEJl{9(=i`%?6w9sL2R1B~Z3c_z<#=j7qGo3h zA!%O&sk|_Xk(OP-mg0;2kFq@?sTo z6QbmsD_Bk=<%6`3<+Np8d40r4ck<1LHa)+*`8>rl%X}R%|={?8t6PeQa;Pah%muiF8bjH(I zATL_l4p67blfj2zo>r-zP8esP2Lu zcGnoty5U!aKn0sFElfOPR1KSwXWuq?idBWoJZS#_R)zHI`2J(WsP?VYh&z^rwmx=8 z=nx!Ui8v8BgF^j@<<-+J8oWeM`R!v@d0!qf&AQr^>l|YV53}J~W~(Yig;y-E3n`%9 zM$P&64rOQzPAb!5t3w5|&MCfPq<0MGYlIJLhp>6un<&-F*vBhl@ z&3s`{y9_Y~SUKC*bh@TT!nIn$zdJ8kXOeYUvYWvTEK?2?`d2-a>v?HUD3oE;j70T9 z@DEgpgf4C>l!~j8jRYox@iT@uw>r{?4|gw@E%td7^wM!$L2~K5J9;yvoFtyq&iLXc z%b5x6&Gj4uvjaKk!ZgH+8du)ByMkK`jF<;qr!r+Gb^;6nwC_3Omyp&`07xhFa~gOL z{3h6t+<74k(|53M}r=yhzl53PRx(BlJj$SUo~#R6I0`Gu4!W3CWR-$dEPH= zuICKqIM8s(;y7o~eG`tK#(h2sTA^U0{8FQ>VilX=Wh*s#b)#F7AlYnLqApS$K2x09 zmz^nw6CFD_>Sdv4dWoPjIQahKVA7Br~O%oLv8nF>TN{^HG9F-U}g?2`_!VJjp7)SP->0JAP`c_&kZ-!<~I<6 zjibvka|dkP5@&hMqlvTeHLzObB!`jAZfaeh>Ki}&!m|M=0N~U?l0P?rk_dXQ)3)$@ zEP!G$Phe3>Z2}%sz-AeR8eL0Ur(QSfo>KtbE7a^a)9DAksMnR(e@JXN*qQ#f^ymMb zHpR&Jf77NoSlRwtSHB; zYxkG(L|h*n9%j@yB(8&n+`K^iA|-a1qdN!{d{WYv2Ig49kEUB56`vQPe3}gGUq_M? zYA7n!9*~L*B{l}y?Xf(EL_}MLQE^S;qU0b~OOV`>eXpLR!^n!)B?d%_fr=&t9*9w~ zaf0=tS}qByZ<{}Xhb=5JbflEafYuT^pAq~+bEbnymkFx)5tfMndZO#hFjO@V_KZpE zod{j!^$l%&K#fvBy*QZFpyEQlx%~|s+6#ll{1lm z2{({sJnB)yJ=Ib_@(_!YyeCL8icvgu!}+_cvWJ#YF1+k z+Ef_gWahnS@~j4MBg}WkD&fMa51c{zB+cFZ!qbs@#$(2J)Z5jOdJFOeuQ=*dNqaK{ z(gqKld815#TQrEoS9VcD5^Q?)Jg787YR35%>s(6R;t5VfH!!iHSAo zAPx+s(y{4-$al=EhjD2l5*fG+qmH}M0)jUnrt`*8 zjn=XmJJ?`|?c(20A7(~Vdwa8E^s=)59S^=9U4FWGd{YrY4F%reAG98*y#l$zjog%q zKd24iAQ_F}K!k{g3vb*YRo(U%-VJvSw!^<%9$xw$pr;1n|C2K@J&3&1+wr~l@qJ$K z`hMQGJ$OAf`d;W9v}5@&{(Re_x5dYo^TqAWobr7?*?4O;eK>o&7@uSL^y0$HnT8u( zseNn4!Nni+ic!iL!7+ewno0y2O)DB)30+um$a3rA;K%Ca;pg;W?#B4x<>XJt$&no$ zdoI>L1NdBq%kT_Kml+vAsbd!iO;ixTza|Gv%rdH)8Db-VsBy^)oJx7nS@Z-S5@ z9FS1U8hl;4baMILryar{(!&@zN#sOxV!PeH*zwKueK6!pm&@OL-aWgtis8%|Xo$vM zctx?F(Xkaw?T^NOOe8;ecvzc@Jo{XF{k$kWm^`z6C=U9wF+*-!f&lQ&ovG&rV#Tcg zLuYa`9b1AP8Fv=jlZlrr)06eJ{Jb$JUgPEWGIK}PR`jQpAv#iY$aaC>V=15~ax36F zK_a_O_E5G79li#8gH>zI%Dw5;;op72VxOHI6&le1CXl{g5%>W*aELFX53?sHb}t?u z@t-hp&I%})>_T%Qt5;Ost+_*FzDm=U;(z2df{j;&bM#hUqiY*)TfXpb4x))Hd{_Ax*hHy$YZ*CbwP_TIYc790Xmu=lV^o=scH*N( zQiLsD2|#u+2g7+``VzH-$E>{~>f!Ob(P+$vVa+Mkn@Ej<0h84NXmIJ5fayjm?BklX zriDoK4=}fbAtFw}`Q$`-jk~*NXj$p{buQ4dRpds?T6RE`#0Wb9@!>+Wts3&f9y0tw zhM;~-liV^5F(Es04NrWM%haipBwFW8{>!V7=OC^HOn> z3DP7fn&$n9prCkha3KtH7HRt-Fe759^@BiJ$MFK=hbJ&OWJs=vehIB&C`Uy(_jNwd zQ2=6+LQLDcVIcgXTQwCW8S#Y+VB%ec2o{@C#l;BYEczL8G$5G$BwYh3@(2g%yLkI? zBARAydQf)(yh;%nB-jBO4OhW-^6DhDL1O}B+bbP{5I6qj5&P+}gz!u1E(D+ioSu5t zl)-sYlG{CPf)N3K7;H7_<)u>2;fxTT%$nwd3PhwSIBge)axp>k{9m5R75paNMkTOg$8^KI0zpeE_Vgfe^|9@TPWPiX{5CQbsBJ{o z1hsL+v+p|*=Xkf7$eU}OH<0F4<#MzJC$grUEjTlb%f`Yh`lqRONo zs9`!&P5~7P5kM%iCE;=^9ftLe*(j5kTe?_XVfCd!u&(Z;sDL6=g*AgA*jfl_5(Ohr zc&G!g$TJ^pNeV6rJtEVr3OmN9#a%7y2*<@iBj&3Xsk0D`+o<>>0tx9lYwJVdydb&K z^P@+nJicnILtcuxiJ&Fr0nNgyypC%kj(X%$ut@D8-~!Vc2_V4@uutCF6R^ANP$8hn z$nnCJg%%JZ8`X85_0J(s=C*d$FjZ+P0T`y(_De$M)i1~T57p$=R+e3UOUT?~AtgHD zlaM(F548c4U-wCJ*(Jb@7YR2E3uxsm=e-L0g979Lzxj8R_|*Z{*CQ+POHSP9Wqq>X z5SekGzz@$%N1DQYDf_Y;3EX1yx1tZ-HeFXslt{{lX`t0r?nJHnBS@fJ zIbj0;E$LdKk|c>j0T4P1-$(66yi!w`5egb^i@s0m!lg)4qWCYy@z^E}$R`?}h;U*K z@-4tc4ZvGA)+q0x7J%1f2Kmu0Ta9f9cu64@-Z%G=KKsu<{$2E1Szmdv(XiBrWU+V& zX9-u07xTa@5d=( zcl)e^Qngo+D53S-Q{5eJIS)47W%kr>?o5JELD^~`wb@2mQIY2Hl;+`OP+43ai=&M_ z?G}hui#hd|p}anV9KUoTInGy2racKQfo@f@f>wSAU zQSm>H7T@rZc{i9oyh>8H?JoyonS4Xb+D{X+*1HK%iL~V8PyRUcT2Pr@*{=V?J6M{t zrxXf&mQd>Ith7z{Ms5w8H+dN=rEIxo%M2dl^*LoUxtbypc%E$1EY|nItLM&G)pbsX z#ZY!U?peP^kMU+~4Tp!_W=3J$T?afBmE<2Mk5KTey#JvC^7ywpMN@v#Li?4gAGTd% zpSK3*&$KVc8|&2cPE_JxWc=Sl1ku)R>^|+T9vx#o|F#bsJWS5qec5%#I-uU7EBxV` zb7BHh?23@C{I1F3f}YCV$IPwaS{++gPEhrx8k<5+l)ZM2rPi|7SLfsFV*N&MWmA0G`*2>I?td-?+-)>1k0VC)I>abX)Bx>E zwL<1!E))R(k@!l7QB5Nh*Dak*)mTHSsX>ZDTUK2s`f0oI;gfI$`6nZXKLer^X)l`z zL6@S9igB=}?Zd!?6{a0Am$EqeHpq|G45fkzN^pt4 zYJB@&W7(F=v7Bka>J|~yN?lqn(g^q+a6Yf?>}?nPX(+Hk8Ytq>R@=Zl?5uAnS#(x7 zF^H06jBOtn-z(14j2L9xzIH_?jQ5>+On7=Jbu7ZT7-HQ0TSI|Y)7hQU2Ws5ksy1&S zJUu}X%9GOQ;Et{DrJLgI;MzXvRTH2Xm(i63AzTsWJdJ=RmE=$5>&8qB(N^JFya@>U zXkg4rP}q8iCkx(GKQ;L1V_1wZL8L<=g$z-jT>6syU286wwHKHZ0%p^#;inyH2xGjiw`U0M&@B8NG`(w+8s~SLwq(Y}4^}i^_L4JOh zZ!id>^)^ANV-OhrUbr0>-xkHhn{`KsmR;Ez*8QPuMP?ChGXf>V25w*26Re;xPMzb@ zAmG`lqnVi-VaKD%6QE#{Or6S%*V9p4c6l8K zH~W88&cnJq0GA6)xLc6h}>UjBI!czR4HL@W_f zF+f(ZiFWP!8u$UcdHJ_c&I!q?CKmQkq~R%0c%($Qs`(M)i#lHoT>=0q6dRN^+F(RW zuK4t6eNs<)XN=#r+?|1#6(eO9&FA=}r|YQx71<))g*7ESM*IwNcs~PwW}Au?TAnrNi$X* zWZq&!r?~{@XK5Afm=aDmSU#+AoU;vzUyX#n0#rxTT8=>Fr^d1fq7X+c#>J=!rWuM- z0eHN)=JA<&STl8=M?(5dGLml$V?=mP@#tI?Pyao~6T)oE3TD1&K0GUCuLir9o_#+3KXelq*0s-H6Bwsw z%ZaZkj5b5R`|K-l9TTU2lX;d!*IbUvC{xp{>OA3`)Ya*B_mWc@nB#t2$H^a}7wOJU z4=VhdqgDNkrB0Qf%bQrVzi zpvWx?M`SL4nzbWU2kv7OjaD3&!`6m4y28HNij#7rsl~+6naI#N-a#^rA)#@8we+KN zg7QY4a9h+kxM8vDn7K4|k65i&6hUCeMc0Opz8lF@lEhzpJHnD&jH0ww+zT!wU)y}c zYJWi+RHhQ0AiOoj=W%yhd$|(uMi)tVb=yVeaeWaaSCpme8gJ7{vKi0@ny`{A5NUfG z4iXT$>JAdbWCB~Eoe9$&*+SXig>LHUZl5P&+PY*AKhij%{vLI(BbJkbK zbiX32KuM8HR9en?Q2qq&J?Z47k8|A0qModl?! zw+y3hubh45SL#d?#V7b~iVN_63brh)|GWMrV{BvUWJbWq!uj8XCj6>^H-A;YGr!P; z5R-TnZ9hTaE#_r__TeOnY zYd0Z~Jw1@mGM)*av82_pkn|3^soa4KrdS+6dy=uWc(_Jq)22bfvSEj=-Z%53^( zGGYP6>gLIw*yf7y2{4}s)GLuJDOIOx_p(RAXTGJKRYKT z!smAKa^YT~Y(0lonQO7rSh>G9hcAflV-^MgJ13FWNuRcFK*?v07jHl_wVH>}i`_?4 z=#lG4kOw7+{rD_L>~RC;yJ)PAHA9l+OdQ8h!!PYsWh%MLsXj;X9rNhZW6u#+_Q!LF zWdu(o>oYo)U-s3ZO&%@14T{g|3|xBQn7le!r-`5{G;Pexx9Mvmk0Q0BeCKtx6@~}i z;@<``FK{QCcS86P;)e}PU za|293Ref{kcL+9}wt-D7`5f!8ax+=G#Ans4m=B8kyL!X0pEm7Vp+X04FQhqoj31^n z6mL?F1!0T-H6A~v7LO`LF!4DVc%NOnuA3+zxGWhU`pdVylw@AcIKE%H&+ta?rZGrB z%aF!Y4x%m|5%h2U!;3gSAq-fuTBke0d|F@cAX=z z48nF=1`i`Q;}##rFD76cWwm1Et67YBsMb#;p& zKr>xM*R=#(bXC}s%WWJI$ipq*BL+3b+afC`Edn)N75b+Rp9BJEZ_^ncb{RRdB@kRK zJE-mz;$&=3f^@_zE>oAHI6U^W66LO}cRvhN!z^qs!NrwCI<* zmS{IWjCjF4d7z+qrOsBDu_JUJo_)yI-V;0)MewP0vqHuEdxL>C^|=J>({Zry zrLmrL^QG%Nz8OK#?_o3B-9*WN`*DWD)9awNSgLAPrg#l(e*Z&*tBGl~~Drz;g8<1lBL9+?MtA{q&h#6R0kb)>{buyto+M>mAgm z%WI%xlMNKQ%JB8Un};{5a^Pdzrmp?_aItgzu?J7tyh6(NTN5SDYjRvh+x1gg4jJK8 zKK%lK;}*Rns3#uUd9u8is*6|^v&A+QjEDT9GF+j>e^jj@JDt`@oO$5fkX(#VKfIl( z#gFEAIB8X|Bsn6Gs6LkF0$GL0Q{@^5*pQ^1u2U8x(G~(>p$gQs@VDxH3NGQ)_8&wo zhWYZr6lIFo1RyewW0Joj2R8frvH`&0?6=?vwpa~@;%2H3V$iqk<|2VY#bC0d4U`mn zn5zS3g#@At(WKWnOAU~JhVsdH%MQHvnGz-0(noW=YaI$6AsVv#$5*L$T zS<}3onnOXPm+vsihh`4ZGUv9(;sJhD@PGZXVavd*dX}AMQ#Lkl9psEB3)sIg4#G#g6o`e3OmBTc4$00(RG0@n^k;cieR~y~%JePW z8bEQ}6;DNm7%UEj8mM=cpqz#x#s&qQ%raN3}QqHR_`TaiwHdJQBgvy4$QKi!Gdx+akeOacZJ#YbmtL zwD{X-3lZ65fX;E0ZKugJX_Y`04aPa{us za;k_@aNL)}Ubt^Qo+Xg9{3)e3Cbj{N%XE~S)gnLk3+?-puAzH2^|n>aIZEET3X@5d z?>))QA+z7$U`04-oZTE=KYS%5V?Zf@cM?23GXH7d77{r8%A%zmal7TD#${5AEn_0|QP~)W zTD4h&(3~04Ln|5s>(Jcz4+x@SKU4C{g)NFQo~v9jqY{$Mz(KO)sIcF_V4e({Z9=yK)an>LjWs`NJPim+@o8N!~MU zDT~NE3ph7%LAc8nEkscnNmHxfKC$f%^K+rWg-;HO*>Y^@^{if2qqo1qXYUv5`K-)c zm=4&5_cFQCz$R=9G=Gff!z7(35B-&K+ztTWxyv}*Dpxn`%h9&R49M&=Dp|vW!ggZ}KHpY6%!x7DoZjZY{ z(=`WJI?X!QfJ7_Cc~GY5VAvj@59ndPvZWX$UA5&GGuRiS5pIRlQ`kCjzgI~}T`IkV z-J^&Tl2=3OP!M!go1)ndQjgr0NZx*@h3wj-oXfaV?{&J?VdB>GiTCF4X%sXbZ^eSt ziBuAg_I=Lqp4AD$xk*&5wx<}$ZMcBRY=I~*+2`$I%_b7 zc*wfZbi!S#@DpuA9}3bc{nQb_+9aTqDR^!2G+4EY6<7o^t|JZxAt|W^o}Db_*(2cs z%M?Hm(Ec4jsdYQL45;KaaT*`5A%~>~0jhP)>-&%UvIPcx>YXy*Zv8rwbC+}CMktybmKi2op%Rmsw;v=hH^W$$4El{h zhUors-}VO&3==(VrVy0;PKCymZj66CiCsxv(H^8Z=GofzM`#vD!N*%1->yldcH5F$ zGKPqN#mAP5w7rHTs#X{S^n?ftjxX}v8#ZiLE3~$<$za-p`QGWJU7s<6S4bHBw zy{CFm-m{+H#RzKOPn$na;$KHf9BeWhG5Z@9Pstum(G=j{F}X-A2ySZ0AS*oW13eM3$WSs{dd$r7ZT4 zJYoNIZ$=Q_wsX+^<;cj)Zi1NuXL<)b4qo#+ASE>g96YbefA8~mKwrhO$pQC}s5&}+ za@>~Q6;BVw4HJ-NMVAgk4@WR-@UC++)?xVWgK0E|9wbcOG+dkE!1g59wFAJ)Y?h+M zpe`nVl0pgi8hJyIOQ*emTrax&H}gmqQc1&j>)WiFXx9hT8>whp<*NY4b*}AON<9Ws zdVWmJv#GvkYFq8fJo7oE``*YyTS0c7M^nH}Ff?-=bH;L=G#97BH$%=%21intAI1JoX<`{_CgmD~5YrEnZkBnLD$` zx%!K|P^#}56L3R~{Ekujal> zgIL2%{eAvg0C`W@X10fmO?}V{TdJ_Uh?mMmd64rTh%P284@jhsdz$CU`evqJ3BX{k z$xG%BWO#}*2bw4{{w>^xR(W?V>)e|#_IP#}GgP4sf3m0=u~f^h8Ouz=ax~}i;p77l z%b2bw>eMgMNL)=<;HA}UHFMA8)9VM~18x@fr}=J;=l#-`{cJT11((p(B!rm!W^3Hb zTJ0No_ODtF-|wlmwrVeSOJRX3U>myo6`}O6){#jlbOmsJV<*5s$*C&L+F($Dto z3Fh^+HS(Vlq{M)S6DLUZVs6!t?7&gNs)3r6=vW#TOs$DjQi{XDL?4OO)58o71=^Bn zMyW$KbWm*Tl-t`KrMc6cy=YN}brXfyK0o!5_$2Mr7Xt){)7bV`_=7K7^xcd5Vc$6w z^M}^fv=5sbs`Vf$WU5$ND(`8C!}Xz+sFA89(#`zgiH+<#bW?)XC=yTe`Tn(cnnze8 z78zFj!074@LG@U=YRnhH6vc*-8rOhHik@KO7F#fmrFcxtSq1%f2324R6foFzBVz;$ z&Po1R#nan|X?rW`B;e>rXf~Zz=W9Z)hYUSd`7iY%X+RhA!k zgNZ~%uNW=6-uU=`&5DA_m*3iQmT$6o#v*b59X$^IhMtfDXo2f9$&-|z4XB5br>;G z7K`YY9ROF|H42oU>?s5yzn}1USVMiS=YVcyz3W)kK+<^W*;!;|prCg?ef%mC$|e~@ zGSn-R-b3}v(Je#fAe1lM`LN<;b!zbZ^EES}j`HWgW46@+5OhtaCHJl#Q(Cq|Hmn)9 zc+P==WMSqt%41uK$6(d(NoS2p3=a;P-foSy{Np_+%9w|ue741e2BtXGlX@N)ygb2* z-V^jg#YxxDc~^IU<^q?zyQ2m_hEV21+Gnn_bBnzNDo^h{-q(?X+}y%IGlxu3kK&AK zbzO``j`~m8Wa?tnLI+EGM8k`wjr%9C^$-zy<-s7awMg^=n_+)Oyc+L%tueNJbvHUY zNN3%Zo>C)H@mHatmwE9-;*Z8%zG&ElQQuN zsli>xXLDaux%8{Qs0)Ds70n6PUn(!xa3MCtRE9Ry6~9{+q$hiAz18Aai} z;|@D$QBng~$$Wv|Di+jm#tgU`WwJL88O1+sU=A(g9sLBHiZV-p!R5{OZqmhpo{&ZP ztp|eUSqjuD|IyVV%Lu|h7Oj9a<*#1qW#)GpyUnzTGX+4DonT`58oh%oeZn8LlueqS zn3P?}u_<1NZRA#$y{5rq-U2QwGv4&_ehE+i^i9l`wWT>&;%mVXuVd5f5Wxs1yc0Rw zSFLNS#bXVdW#}?)AnAmfob(>*Nk5Q||61DDzZ&6rv_UzqdczPc8eFR~#tv`R63K^2 zUw0y)TW-C*U!0x%xJ7d>`%@yxaJ=@NjR)NkEJ1KVg|?~N1CakTRL z1oE#mw|N^}^34tptZGfIau%@c+Z)BeUYC{+r=04ath1Ha(v$ORcID;@occ9jy75H4Pi z=4^NEu{$_igbt)8aAJDPA!)$VlVbjKe|ExfJGJ#MXi9JDq*oO!jpuGEH> zrX9k28oS1#Y;3<>_1su^Pb$O-2D6~ejGN5uS`J{T*l6}H7evDfLfH=gBy1XfaG(1% zA;xQmK!vT8*|n)q$y=06jqRJ{SRo=@?Mc-Yr6E=&aHu+4->#+PQa!)gj4c(A&+dh7 z-f9?c;KuKU(`4QbX%i8%6T=TjT*7~dDQ_tol6hkB(_q0SJDJ5%8xB@}LgC_#Ber|6 zAfVY^D#Q^3`v9yCSvf5rs4L5(C~T}Ms;mV;6^qdyD3fqmBv#B3f~olX+h7$C8Ue;u z0Z6M`P%O9jm--7R*E*m}84ZQ!%T_54VBvuRW5)Yp?TT%QsK$-?X_S@E89))M5Q-`Y zMoT@Fh(joW>H{ND(NOI85yGnpS%gD|wJ4zYk+B|1ild^0+e*veVbXA___4$%T!3jC z8kNrz-9i*fU@^#8$4lBU0{0n;AyNAU|B|Jiypa7Bh#D?~p@>+K?w_bo;~GI^uRo{k=0d_R%%u+1_D#z*1t;cRdL zAh0Sq4Odvjj0uxw8>S@&3PH$U?kR+M7_PVezOKwi^k4{Tj z?pyghTC}X@>hgHsy ze&2S!m0rhzC8%QI?|w6Hp20L!wm)t?kb+-L-dwt(ook(vJPOqjCJ`D;{58R1UPwzHnOZdEb5qX;FesA{OKCc>nB55*3w;8Ckj(+% zilXr^3RSkwUxBp~Lb!n7dQ+awrv#AhUKCOi8m6dhz9oZBqh%g|k)7A1%Jfsf>Hf>m zG)A#1JFR9}uUgSlNh@DI{N@u3ySPD%s`>V^Z199^kcP&q8iJHJm2Fg|xX;+PS!{^~ z7^)pE220`9JT6JEGXpT(JY^VHyAvg=Xpz9DT|vc+2ndy6F}XJZQ*bQ#T8RJz?R zoQA<~?J=KK@FFelp(s6fSw5fW>d}Shl^@jLUTR#7^rt$(0`P+(UGYx?WK5~emq)qC zG*TqHr$rK;Ql$@aYulH=ypwCK6$zGKVJ1L#;7~n#A>cX| z1{q%DrcfCkDaLL{%+(Nfw22Q2LO)p^@~cWpDHIq-ma9T2n%$#%Jf5og9mSl0YJux| zLaVLj+$|)%>l)_Fl~9fRk-5Dq;hG{%Xc~ zOa4^nVN=WFO@Me5}V$?S8RT}IMS59rDRFm_Xu z+DbNqB+VGCmFhS$h_cELCUFY!K1jIT;=-`X|KvO%V*_o;43qGM^xyoM0?DYX!4my) zxoA&yZu%thrM|^Lk=#A8P`kQer@$k?oX(vw7uT}dm4iLcd6V0K#pQXte7}tCK;lqn zov{t(HW~*PTql3U*`1z?on+kDc7Q^Z&&2)PTz=Hbix7a?|Bg&-gcwyTDD4$3C6deM z0x#*uAig;-={5gSbsRmrKG@E`OE}aCbvE&RJl&s;nAS_=A{yPOr8i%(@hx2Aoxoz{ z3V{1p(MQXbfe+*DJoTTwYjF&|laMx8w_ixFZzWoeYJY7t?ru_Zttl8k#b#$&ko=*>Q z6;Z&faQ%8-!i9ifn=XZ3W$|o{Eq%mMwAN3w*k&`eOnc!*VpK20cClGFVL4ir3H@#x zaG+s2>sz-xqK2`d_lWFhoGaQDl zg#gOd{cRseBD&zG4ng(S`KJ{xRihK2*NQtC!7h9euf_fj8K`}|jh$(}LuB4o zQSAdLxAH+pG-#$&ZnR;lD@88rGb&xnM)s`X7`mgYon| zXb7009!bAzk9eIqmAQ>2oyYH=g27S}sg_d_d$b1Jc$^&fY)q;6!QMa|U3ezn+-kXHP_eZ=uxDb2koyeJU=gis$iUp^^FF)6M)QALZx$$Q(;o%dJ2L${E5 zuk0A#?ysC+Y`~bY8pxG(sD|Hf0nO$3f)oUIaZC->n)#tY87T9regMb|`#LQBi> zT9Rqd8j4As_LF*%agYRX;M~Ljl~6UPW^VvPwTp){tC;~$b7ktf6~`G68+ou=O)}p~ zlf|0=l_t#JCV#4BYIP}+45mac&DymYBZsP-2Pzel3MOPllu~ZvPy$9XVPosKCuP?> zuTfPexp64_Yr{WrW4C{Y`rEHr=TaMbh+E41(SRyMw&XsCHtjz8k%Huab)37wILC4#Lu#-O)J#MNGUec zHB(8)*_11+14B-zKpSgJ1cg360%%GBS7YA|J--=)mGw+gVeD1QaPF%kDQDdP-HQJ){B@6HV{jIU&7)+uU-B@xbhlEW zYbIM;*apcAu3b5L>OkSSR`Q}&xZ6I`i!1p zmj)m4`x0)jHX(ZNH9(bV470|(n^Cp7k-U5O--n|YGM!cN;`_HQQ5PK){KmP&rO%x2?9QU`fvC&=V zM~kBKq7|CIyvz4yVIyLZJO#C_7#AQNDsq0(wC>Kud3GoSy4UQrCezWuK(8Ez9Ok_> z@_wuX8jXMR%}B1*DX_+|gA3BTg@4~{P$JN-PS7Lxyo%+kR!`u93uZ!#xHZjpKtzA?jvTFJj=NUtS-9LKdD`E$F$f8T88d;_219(RIk z=YQt;Uh;nE@KxV;{)HxgcUmc*{n+qTJ?@0o&i)|nkiOTpe5`T`x=#;}YsG5<)ht{V zf9vtu@JV>-X~>8C>e9U2n`wd^f{$gD;S(gIdg9JeHT}15B%Y#&aLaq*y9A&9UE-GY z#J34P(XP*wzVmqnpQ~Luf>+!;805eIZnCUrMlAUJ=44RlDf^Xasdl$h>M3nI%`51< zAELmzgq)pS(nBgqFREKPW%RC^I9bi`sM;^9*JS)7?XzJ-=KDkl&7DvmTa^EyJU$hO z>}1xMGn_o{B{|_AyGaNo2Kb{;G`-L{zssx)#7fQ&V2mS#?0-7VIsa2Po1NvqRUY}L zIa#yuzfN;bl2G_QhTRKo@Y9<9EmR%UKdKrmKfR|g_z4n{EndYJP6m@Dr+c?k7cj-v!ga=g+qWnq9DuNvJNNFweVHG-mNvKBESE1Gzm#Xz?VIJTzGi?-I>o~uEecy&G zBv%KVs>L5;hI~}rh(qiq!+GUC2uNcvEQ)6k`l$1f@-*nuD$iw-k_VXDQ`!gzqtKnI z%89+e=pxXdwk|714YLu)wjhv%QZ+0}MmxO?XDcEhZqmB=o8hhf?_E8+U-6lV2aIxI zJOKCH#x1f#h4}9eeLGP1Y*NsKMVHn@iE70s?Yj5_7th3-!bsHQLxZ@^#Ak6AL$2h< zX5hD~N}W|}o`-{DbEind5pwb(RFkLek80xiLv+T_(-TxKwp+a2QJfS972`Rb)3ZpON~+t>CP+* z5BO_*?L$(HQJgLa&1_~jZ6@}|19loX<1PYp&a5aL8jH58@$ZGqReb%_JcpBmVf$#B zyhi>wcnT)6>+&Yxg_2(uLX$oIbXM6m$WO#Azp-QTkGIHu<%4Q6c^gN_8g*?IooT z79SzJW;he>t;L&tD5P2(UZjflDnb}SY0!+Ubm_-v<}un;YD>E#ES|S0wr?Ca)D`n6 zD!5pLG?5J6N#60uw>}SLupXWGRBb~mOTi3G*8R<6Luv(qLK=tYNp3@-;H=ufO^>oC z6U30}<-VNV6*yhJ7j{@X1YHNzImsg6>cbUP-s35T^cj!E6q~Y^6K4f5a9BykNcOpNXIq?N)vu0C_OTc19fqsZM{glzyU*Eu{Azs2;G=&s zV7PGqFy+Y0Y$GSPCb?EPw+Mfc(rF~lL|i@_4^Sw!pHR>?-d%Jed3>RAOW@krRb^F5 zovXLu#DRMPbgW9?o#7pBJk_YkESW}~(goeJZRV_$je+ilj-AOYtkezRt8yI?&&wwf z`jZN^h^i$1&S;c}<2-gcP^kZjj|_LzB=312t+@-=uMXXX9Qky3)-Ht`^SQBP<)hN;L0e5)jr$Gnqt5H1U09TM2Sa#gM{ zx0J~!b5$tyEg;#(gFX7f1lv4hZx7K-%MEC_1XYA(sFymfb^myDZ0Q z)5FoDQ}7KQvC!Ao)*jKCa;#08(jeP|X7v|@wb?@qJm8Nv)x4#g!NmA{Hh6gm;N+YS zXPiv?%}EZ&eLIVE+!@LuLH~KnP8vSA;E$o|GHyZ!<6K387q|fY_qbK-GUE=as%C=| zsv8xsf`X;6BkTak^jwM$J^B(GTUqL8CLh9O&eJrvjAdozH*;+s0RImY|E!D*|F!+i z#P}?O=#e0?i@dJp+8`}?0!UJ5Ay&4n8uMT2x zBX(~FoHDt11-ZK^DeTeVvA4AM*e-V090bE-4#ID+djWwT`P8{+#S#y@R$+K%R$8no zun`^;ns(3aW-837Efzx`{`bevg*Y>uXveGQBA7G5yoz*E;W`@A^~0YgXJ+N_xV| z2_^xh7Ce$-?4cs&$x&Bb^O})b2=D>k77ekP#FmX&Bvl1PMU?8F#k|7Edy0tdb=)a& z1t?t`0$l4laG}P9Xp~2T|Ys=Qd%sP!MN^RrhpDo(+ zQ^PkDi+uU3B)NR_^-j_+5%-Gff~@;;kvo~`Nn;oa?OAT?Fh$6u)wvLfJCW-SC2r>)-IyAbdCko(l&mw`GeFqGn=*+d8^`8 zA)I`f{`?ari|vF%W`@kfKaQtqd+LK4^$~o2eGY?7zsY#DhUm=ej2yPjt{p$w*HT=p zLarHE1!9JDeztQ6xt&Euj4s81)m7k)9CUsAlb-VR;_#!0e)~@JVO0J6o~`hyhO+Ba zZt&jqnwn*LiBl^}YhToc7nSUO{#gIx>%P$cW{SY9H!{vpJ zlxQih{qqcA9q7ZD6DmC?sS}Zrb2bF3UKQ|XLUdW5M*0-%8!RPxR` zi0lw-)*H^L<~m5TJMSPvAxWeD`aDo|)~@$w`=0E>?h&hOInj9|#$|PRlFG+oBU4#s zgB7^`850&3ey|!FW{3=W(}ov!n56S3aKHw?EOhf|kMLJ@Aun91!ic8wt+=s!wc-42NadEZb zG2KO8dGFk%YvIanjg#$nZ(oGw<{`2*UrwKCfAXwW$x`GGrNn8@f*wqci$?i(hvH1% z#FCGv)8v)rglSdO#*1r=`s0OhmA$P~EXZK^@og0;EL@rFjoN9*e>k;Uj0bHjUHE zhvv>gj!I5c0nH0&1vfq7Ej>!|>=m_Ueqo2li-$kKyx(*tQA>qFRGLy|kV$E!+sEsM zj%W$ud*OBC)FUNxnP(bG4E8%sS)M-IXk}1Lvk8)hp;)7W!L5A6_ee?~de)-&BbpYQ z4~P3@(QQ+8qe{PPU)!4X`7_|iCU{(6tx~FiptK)lO3UV&#Kzr*=3AT!>*qd!Vhwp62hI$V= z(I@Pp%Z9rDTNHWuBpc*-7W7O%J@`?MxM^q)*wYS9Q-X=~cs~FhfaHHW8vV4O6&1ZHrzz8)cx(dqT{6=XY=fk zklaIKzCQd#YYNIjUoeh5ls!q%sSmPo^OsXk4M*A4f7EO z+u$TAG&{(EJhrbowy2H9cKoyzgZD=#_bo4(5`Sk9IMW@9cI|FkLS!CnYXU>i`g?&G z0$p2O)OXVXW8x{GoNS^^9XFC^eaB1BB&Wwf8iFihB!4Rmh8x8gK{X zoI@*ORalXV@bGIe(1gCZ;@{K$kQkm7uF2IG%ctm$P1^13&5qYhj(HfDf_6Vh*yD|Z z(W7Fqixb|-l__5+Cf;S|krJgMx)0SD1m`yz^!hECALdaqp7l#D+>R+(pO3?3)2^iL z%p9S}4Ck~xq-x?O412WM7Vq7SmmbO3hF{F>a9iE;0zLa}#6hHG z=kgID(#}X258R*dB-^;;h~!>{p{0#exlT-nKLx%TgyQP9xr;H(lphU3#toP7(^A$^+r=oH~39nX8#oUBLO zLc%7v`XJWms?M4Zr)=Nueu(sgEc!A`7pM_ww#ON&dl!SiJI~R&C936O89Gn++N2IL zIc&uX?{)*p&Q`kqxs&k0HxwF_k-ex4m7y_d1ea7};$N5Vt*rjK%s_-it(gS3lbBU! zz!@I9bG3gQy%<5Ecic~$OZ#2C2<-J&G?}I7>w@6n-^@>W<(kBX;6{(Df`}0$(7DZR z(v%lX=nmTuO`odw;f{qJp!Y6O|B}Zr&ZwDB#1esK4I}UegT8q=;U4c7I zNQ+j4thJo}Yug6gFD`JNV9D1MRG5R_! zHs5csYMdT`)6DP5+I>F)lj39#{?~lTqM^a_f&9^w3_&3hs_}fG+f_?p$x`s5vPxls z-x~0Wc!53mkZ-vs`%4)c-)g&X#ot12A!BuqVxTDAMs6WfL~4LvO7_+O$lFTu6NI@_ z$DNzGPB4d$FIfCAoB3Wx%{%7VaKxBk4LuTU_Xu4%y*9}h5mzA#U~Ci-!sfiHR%QnY zg?y*k--&7rCLuh|0OHTwbb;$XB#eA(E0RUlDqZ7g3C5ys5KLd@hvXujT{mN`)c^A} z@&|#3%8nTTV8k@}huRKRAAhuQ4m`*fxsUuc1hduS<>qGR`~JzLPj}77mfUbpH}B8p z`OM=|uU#b`gO2yC3#*TRU>C?=O*PJsR4CQ->Aw@bD@W1+ra}G(CDGr#bG?l#cbn4@ z2G=*X`rEl^=g4uz{-E9hq>acu{qLQSJ^KsZGYWc3JSiPE6I&+x z<#qEzz}-lFq7N`UQB8y5+_?oV0WY8srt`uf_pSGBzdkNx)L*caz0A20GCdxN z(K}zbE@6CJ1CjpnVoZUhXPcO~D4S=~m54*rUNJV*0)ktJ19B_!VF5rv7aL-6#8aF4F^0uy04l79<;2s7v$C%Aza6O`k@? z65m@taD z(R=s$TJKErp`q^?qZoz7`+$gET)db5uHlX z+W9QX;P0HroCI(1LGl&7B~~=wlD*Q{Z3f!*;>9gA75?0tmFj4~$&gTeoF@6MBf%3D zz5Q`~x#b}IR=9kcV=+c(5qaI7l}=e6Ir*64EygZJmHf6Ho2idsx608UAM#$L&PUj{ zwMw(JsBH$RDaFKghCeOOm2J`}8Mriw#-jgxuX-ojBcP9%_tmOFP||Q3zwT!rjHH#7 zt;lX)MrHnUVXE*)-?1s5%H1C6i#NH527czdO1z~pxPtm((cZ!_?ReVL&Od{xBq(_% z%!Hk5ep1$i=-nkF5+D_g+Qhx`nTpo~q^w1Itl)Je`}&l^s@SW*sI_ciZ9OoAQmHv8 z@c9_97#RWkdYvvA6>kv-7v{Yq48^t87QBK_qHTLfTzt&d)c13pIv+f?vaK$RG$^_$ zVT&0*iE!U1*nZvmuw~Qy(W6QjiBhuqdQU*XE^k0KTp%c1GXWcSd%m-f`~kqOqF5NI zR_~dr2;f95mLj}a9MII6y7HN)$1M#baO5_Ao|fb(lE!APQ_?C~&XDDqnyU~s)&5yF zX7cT@Ltk`Wp7G@x!T{KQUfO; zdmp|Z(kc59v5+RWXymovmfH`pN7@}S2FXsg1<|zGo?&bKTurE3PTD;Jhap}~<${pi zWkX58Yh2kQTCiHqveH6Ddx=$xXE}58wzw=lf1op_sC0vw2{n5!uNpe>cmv>KeCRA2 zVP6+4hopTPdmqB;1#my9`9pNBiF%^FqIOHoE$P`$u6?$tRwGM6N<$htMc^M3M*cUG zo!h^Rain;s!^C3a*r3T0P>`h%aFX&QsMU8i277Eg?ezPB2_;De{E-q8(V0GJ;!LtG?ET70gs3}t8*CB+&9svvPI7|} zu}m=|7`l@AySLR=AFYW#tR)f&y6trKg(etS4X`k4rBs!jNmN{$;bC^{!-2~T{{zGu zXjqn-_Tq>-f@T{u?2^zIRBw5S_vn;BbL-^UW~&Nx2(3?4tKBUA0}lVew5b-jjp3TMa)bt9M@ctc?t3qUoi$~N_2Fi>OB!TYP7brxL*sH% z8@BL=?TbGYb@EZ00u`cHR^|nV{Uq}bcdLI@F=JRlW04cfmyNJ$nbb3Z+moz! z=q)+T%*0BFcMJPcma*ea0{!kCX_89l)u^94i7O7oD!_&}4~K+do@K536d5|!Bb@xy zu0;m(Bjo+AyAP{1^k-~Cj9UJZ_f0$?tvw|}DshBPwx(3Ru%IIq6$ssX7ABVuIJDi> zpD0HrPS%_OkBV(_v)?>^zkfcd<2iaFl}o{9Y~Zdt5od|ugsErSa5Y_1>|EoqI7OD= z2wyoH)Sc<-b3<_Wp!GjFA*(arIKDo%o(_kYt6_POzP%vos_o_%GHOU))(MpKe>Wa?wml zUi;aErG{I49cpZ|?gy_LSC5cI-{^c(eO{vi@k~5kQf&k8y6gHDrjwxKQ_TFGeEb0r+RYTX6JSR z6B}qdy|BJrXV+P~vtRkEs*WZeymo!qw=}>xfkJ7r0d3n~!0Ul)Gwyb35?e0Qe3FtaJmiQBhJB!}iAqRqw)Fdd5@TCh|3apz*;F6}ijAE!7NM9HGM zewy3q%r!(MHmi2k8Ekelelf`d&4- z>1-J(G#$b6MSZZ?6oh035Il^~!0(~QAVG2I7>Sz7Nu-Uog}xXVM*3K)N1Dt{QDzh8 z$6iuD5h4E|B$`8I6iI(b@t&jVC!t7ogl-HJ>8y;5V`AJb!1G-ZR;_*Pc7VX(9ki-e z0%=`Vl8myhBzJQOaCGt7ntI&c*reg^oT~GXMPzB(7x7e57ovIHq)GXo%=uq!J&{g|=muPAcbkG0)Yd}Ioy%NXMcKCdx+C=5aw%_NLtH&HE}O1ZzL4gI zoT}0fcKG3xMjwBgX;O&&ni&!#BrnTYfKBWu@mR_Z=M#qT&*-9rp{=&NS4gJ&Bq_6} z-Q5yC;yXTTH(w_2Bw;$#P}u1lj-f*8YduM=U?wo+IAF;B?+jBZF0)|M6+}fvlY+6o z#KBlb{!n7P=JAYP_ym9sqYP2@N{g9sogh2l?3k8_vQb51nQ_pG@rp3j*;teekrlC5 zG9`aZ8W1N6Oiz6x?;-1eki0(3^7PTLP-|2lxlIl4hDW?cjygN>$^N;s zzrZKA=*?TM{{{H79B+)7k&Y*6b4QmmAJ~}f$PzV{P&?rdQfYI!owQejHw1Zl5T(l5 zGi0CV#L9=Qb(5ag8Tt3K!1pc69Uc5rqDgZu_Xaz>#j1 z9Q&>`8`a4_=&!#RKdtk9_i&&WFXJOlsZq7H4g-2C_arob5YcsKN{w7~H$o7gRsE*!i2$0O z1pucx00@*Rj>G$YX;mev7jfqx$EngQ1Nli#q2?W}Z zz-}{ORRFyjuPN9GL}sHOXg~4q^K_(Vw$muKmkpbP7)3!i$ej|R8@pK6D{V;z44~A? zcTyc?ictsj9(tqu%S_RW)L6-{TsxUwa0SUrvdS0sxWj41^FHH0{Gc%Fz_15AsaN_< z;grVVU6yN96XGlPC$5z!9liVnD+NLdjC{r?{{7QdEh3kS5-YRPF6~NTBppg6j~dPb zUJkBw_eoL)4wD;Xpk~VR9C@`^k{Qs3J?EU>DXjU?hN5FiQ9QI8&xkB~Qq>&I?Ce$b z+bK0R{GGvHvmLY-!%NjNtN=6Uwc|48S#ZA&?d$=R!}T?Z*)KQpSh1+2lRM6WXZcsM=S(Vn| zRVXcarH}Kc^oR&ZbPm8i3J;*IXCrz)`b-T&kM=^tUPpgzunzqwySjsDeWD)Qv|4$5 zbPONp>j92U5BF$gE8=!w%%0Wf^ZoPf%YZAC04YEUPY+k%g}R?CG|FK{cJhr6l@7Ky zM$mEffnU(_vwTZ162K zHGC-|^D*SSD8XcYORRe_^`yztafSAhfe0Rp?XV3CkId#&?Y38q(GJC=LCK+Qr z%-pS1Xy}WA&T#73uU$&Jo}EzF>#R{N|BVdY+>3LJM1QL1muh5J2BxM!(n~&51AjRj zL1GkE-BL=<6cqmhxl>@JHJ=i*8!%x^>g1iM9ltR=(-;ovM%o654WAZ@ajWIc$}V#o zwEL*nzzd(RAV&v1j;iVA<(hn-zE6$A#uZmvEuY*W|3@F!~qjPh2QWs)g*6Ps%m8aTbF|AV=6Li;pE9a~&TYeD()t+z6#VH8zsY;Fcx9cTeWn zOD0uqxf@%QzAVUFoAB+EVr8==R#byChI@Id&V9@iiMY3Tho;xOPFdTRV}P;%u`E>K zcpY{IyfsW1z+T>r+=Yc@nwiJ>VzpK`S;L-AynRq9*j~G&sRnPL>b#Rm*UFi@96gjw zSS2y&@iSQFhrd(s^b{5FODm1r6bi9Js>zG}#wQCT8+CwD!)D)6yrss)Ra1+o~8PE=k7BZ2Ka6lH}-Q97ap3`aey{h*lgD zb-+vZydqzhMm5|7E>`q|WzT*?-c~xK78VbAmK`3(S8ad<92^eAcV<@2`BPF)8QbXvH2E)*io}gJx#>x>R$;Hy zVGWypdzKj#NC)?y@o3G=0lk>*83T4epzBhkFV)j}+{T-&??B=XDb$?-QG#9gT2QL) zyMhKCedT2Zv+$EOTce2L74w8)*0=6Nz_Ue*oNO;Muz!3n#oQOK)e+=4`$+wGSr8K= zmg+8Pnj#5+>t-evOD)O zkA->BHhw-M(8J+^=-p*N%=eJvuv~ zbp7;@KIKxbMV~AYQq2Z2pv4H?*}002+rK)*4y@MEETLHZD&FjQE zF6{3D1TN8bdgFL+Nt97)%{ZcwH5E_H{bY07dCu>iLGZSpLipZ|p@mxf(GqE&ep`Fh zs%QV!5Q*%%4?qTg!LvEk|PfF)e!yy)? zl3-XK)@^J~*ObKLOxv{`sRyiaRMgMPlOq_F&w=QfJ4qF1eX`S1o+;=Nf||1ym=KIw zcI}27gE;Q1N5OK{cC`AWv&yY0wcvD|W2VGTxMpH@Wzrgs9m#>iX1vI1!U7~0zhOA4 zP18(WXKly(=qc0adpY?EX zMIh_6s<(#?;m(ahK*Qqq3+(ui5(c;ZyhdhQyX@*H2NCQ(Dnl%54MricIV?o@bS3!I z@Zt`jba4$2>x*HKB}8!4sW}ll1?XggMidQFspDX9{^@8AtQyey&IGw(*zCq0_0>ew zeZnV$F*OY~B`d#xt+s_Ze_GJsot~S07*JVN6wo3;0EW+3gV*K{H)i4M*4NM}3qve|#bLLWDa1 zAdgoVph(B^v2ryjm&^e(U#A{yS=(ryM9$k1622Cr0V~@+J33J_scBs07k4_izzBVv zj~Ny5N%I+4EgfEOdP_Y5)4ZjZk}X70I%qQv*ermd?^~u)AaY1n990f5w()o>ti1|W zBUqd->y&865;=SH=DXCm{KbyIR9FciK8gv7vzsT7np#Jkf(I)vQ!n($+X9132sp-q za%n%w{}7~%m}RHRtYM4Tbje}+!C&<~5H@2Kvol! z&i^^bwPE=|;nBQS9^%eylu2v)^TD+Nd=E#tx!ppB6u5M*v)n=!7Ny*hT;}~GUPk(b zj-UZys4=@Dp?0-lU1iK@B}+by)KQ#Xm6_Oc_%PsT4}o#AKhm5nrF3W2P{RslX<_UU zJo=!~vW$}G*c|XerhQt@?SPDtl&i{P zlK$&7<!($oH<8`4Te+;su zZ~yW60r(Sa?6>Dm5tc#bMFm;dXgRx)k4y<3L*z;B;rL!G`R%z?e2+s^05Y+u z_5o3Y+&|afYnhiNCfx%igkV%zCLeT>{k3OUL*M(DADku=Gqa^ z(es)zBIWqiGy;)R7bj`y0tWx!A_qd@yR&hjqpcR8XxkmjAXgYShxJ$_s3H$$toV3; z8KG}`e%T!_qXDw!gOSRR3_u=c*-A&r-lxyij2SMNhqul_3RE|tSIMBNIi*dJM(Q#> zllAz$N35LUGA1pbS=3Rt2Rrexx`B!Jj3sXMmy=rRc<1q`P1f=~B3j)RI%4C%&{ho{K@PMQ&G=|Pl)&)yrk58 z+gWW?6x6_IHj-1Ec@nX>b#A#T(G`z;cnPqTW|<3>y%50u5G=-zTKZyU^;(tC{O6cT zf*+XK2$hcBB_{BkY$Mp3vR@e^&m8PTJAF?6-klu@9*v0kPuw#dFUU6|-?krNyq07(5U8`d@IV6JD4Z5kZ;^)Ib!BW-owb^0Gs zGef&pk(oY9<&Ba$7?zd@6ZQ&f{n$80Bzb%15)fvRb4q{WE-V{7GGcM2H~O>)Y#cim z{@y}lP}~ECt2#kTbr8_NsH=!cQb!WiL?>AX*3N%bghS%hc%*i*(!&- zt_mHJ@t8&YgC8I)yEW?=J_O~!iHRd(|MJ_DZ34oRda-qeDX=(V+*QmoigGH3!rvrOD4jv zw_hvR)L#~w+2sQBb<2w>>1z!-?;~^R?y`o?e?uvJ2>{t(W)aM^@cCjhy zs;McI%fss)aAr7?-()2GNOfM2d6IHCXv>aAs}Wy)3$!<%V2TyQ?nyq^|7bo)kuBAM zSXiZ^qK3uQv};5zJD7lU-}k5{=vKRWlg+{1aEZ!_S;XCrrUrCir_o1Y`r?(Batw(jFn$O&r ziQ+k2g7wQw(>6Y+s>+Yn0-iS-y%3|dXdGb2p`L{rlIpq}jy&3gp|4?}gAvfP;f5Mo zq@jj_x3hR`+Li$mFcb-fcaK#aIZSv_f+rS8d6t%p6t$dU^odY)rJpCOdRbT8P>+v) zzG*h(G$*BKKv}teVr>=HTgq*F_DYdwS>D4qC*WzWVVazAyPUC|)^j~WdC|CxX+Y}V zeQ{sQ(@EFd{GJFmclhb++O zAd(wY*(2_Nknvn}m654|=sfR_EK&%?aTZBz6VjKawZeJwCE5gR9>V1CSJ`Tm#u=h> zM%uypyd21VQo)SwfLMAxRH@mCELGAnmt@8d=HFAEfL(JW z-S0o=_AK6F^v|SHE!;Laiy;IqYtuncW>rb#$Ak@!A$S9H-<{eMY${%*b`UOER{{kY#%gyxguMbo z?^r=^crvMrz)C?o^V##+NFi9%1wd`vhg$8xFzOS*)#}vG>#E2#nxm)Fkw#IZ93>0yG0t2Yc$^rBJz?{qs@fhO<&G7h-J;kGLCclwQwxHbntfcb>rr|^ zjsJ(B_X+l?bepPkOj~et!U?3+#NmPg8;3Z(I3t`v$BwAzv$E*LI2XJoL)k-ynf6-*B1897Lsn0?da8Wzfq-)O#jct%FL`oLVCqHvCEt0 zm^a-+sE~gKTPKDdB1l&fZ5&4q1XTW_7Q~L`B=bmwN zu^bH8i(BZ$U!?nHZ1R5(d0n7$h`CGawRU?ai_zl?_p=#}&;lrlI3eOw)fl_2vKaUAB)deyOsL;O8Q6Msd@-9AVs)TKc?jXql8-Eo%Umv}Nx7 zaiGlxof)>XC*^Ik{%%EsYWev9ga}%cb~_fV=^9ey(%Cp<8W5uBaJTtx1>x9l?`UhX z|8X$o!fxr(TzRgKXjZXyr_s2$Y?f3y8p_!>eApyAZYtH zeWF5|2@xz23xMOot~6yTqhcg-lHRM-jL_j({g?Un>!)|OVa?LHqKSZQ*7O|^9^md3 zK>q$VCxG+w{_*?n@hJaJH;AD2{Pu1G@YV0I2luTwF8~Bqcwp~fW6wr}ENO3s!$(%U z>doNIXJp6GeQEdgAMW=p20)2Q1gt5i&-7Y4N7hR$~I{LLvXr?wKr0M7 zN1*DHl^M3<`Q}9sPs(_@-Y4hGL-1b;diYy@-}lq7u{IYbO&)fj7DE`m`Ctzh>)kJ! z-UIJdIkZw6HY-sv-&mP3J)wB@yx z#$t`T9SJJ@1RIDr+Uf!B?c1{+%=oKkQ@6|)!e_&$)A!RfY}sOTFxR` znW&%b;f>u`E8gJFwx9#&%>V_)$OGBSM<@2`fD@wNC-)F7Ay>7e)%l~$Wso94>y96m zMJXlUmcddxvPNWoB)IBFjox(pIx^k=twB1H(p3_6ije$DDYNtk} zSy1+ofpSW#z#~^f#x$BbhrLK0*T>fP_}5N7(VnXV8cC3lvkbYhPOOIvg5aHv6Dm^>c-LUs1q9=$vjZLo6MRBqUBUtk_1FSs zl0iie>CPh2lVJcM14iX>OOh-b*=)m!+@dA1;ruvLPPSmrS#ZN3NAM{bC|TTK33f{u zk74B}aH+lIqEimtY3eI>Ae3cEyTndW&@pa99auI1-wJ_kyWf1`;E@qm2$<7YkcEN* zoijtgxgNP;cD@Rn`wsRzulFbM9==$T^9(DLJE{R^Zp6Jp_KNo@LHGb8<+4gFVDTQd z`drkxKJ75Y+t4a(dd4ZX%ckyK9U`o0uQ|jetI|z7?ywv{t?Py;zSZ5u1&XrZCePH0 zW{RPKer@}o`xt>jShN(Qher1WyT+vaj&6ioWaMmVRSK?91Y_}})X3PuF|x%YbOcs) zRXjiY0&~Ula!Dlgd#H{jW`)vng|Li^Kp-TDt>U?%>ft5Q4QUjc(^52f|C;}bgKVQD zCleV6fRNcJh|0$-fj@0%*Jj=IGqXjmvEQ=3qQatVbg7^RJK&VM%$gCEhA4@y`K->v zu_oOLYl_2W(KAlz6^P|AvGUpnzOwkDmgBgKO{g>#$^}D;vnL-Mty9=h8HWB2E98$Z#tjfb9vwM z8t{1V0ubYjCb+&dd-Qe5o7$TP)$)|VnhO}clrX88N1n1cW}`IeqE}c!(Ku0ba(iIL zy#9ki3Og5-k#zC6^t!AznFIY+?&R13jrttf^llj?n zE=eOuE~vSaW=;9>d{!Nn$7mV0f%=XHD-m>Z1C+Qg{SS6(&i18vA}9US@tWwyTa@<@ z!bm`4mdTXahq86U3`~`utSQ%ne|qECW_lySkn%k70W~~_nKAq$B zW<&=>h_a;WfIf;N3RgNKg7T(WakcFw{EudiqEDDRN z5NDQZRoeF0IWS4n8B0@(mmewTeH$Oko(k{M+bt1fNny<-xxNyAkjcU;i4UYyTW+5u zT%I0A7JN|TBpZ&{nmc{GJRo6cG3n~Qa}#fULwLTuUa!tpycaD|zg#$XQC4Kp1s)cx z!!0nG38J(Cq%>MokXYxn&u{nbuk=#~I<1Mo^Ef4a@-HT@YbP3|NT9-V7$9^8Opf6f zhK*zwR4a?abeiFS)EOYeXzU)QHra=t#y9(^R`ipts!yEzB)GU4wO=fXnn0JsYX&Y5 z_U*=r+eFnB*EZ;SN%gdN7;8F9# zA|pd_?b;^TtNSWulw>eNez^ja7AmTlmwAn(5sKK>bAgq4>Ek%?ikMAj=+=l;IWK!X zAn$dPV?@UGWu0Jh*0#$A14nfBw6>zv1mp1K24dIH7uw~v+?_*vmeXdz|1ffAk$@U* zQ`H23@-3)Eth@f(Q*@%5jYpoG>V?gO=&?Q}-slaAj0lvgE?MQR6WB|PdgOgHt_8+1NuYk*cN6Nf?$-OjAjZ?_%Jn;{+J69as6{sMz*hfpnFNV?ig)adhOY3KDPnQhk-#hF0ZShgvvFLEk`lfq6w`@>8A_|_C6lLXTaC{(x2Y* zdjQ$ibg1{59-MbylKBLH6F9)k>>$?fx%q^cgGKeX!|n=Uv-cV_dX4uO<#Cb?TObwN zWyjfqkssQ5?{}^Y^`c#f>6V`Y^E5zgTDoY&Fjw(rNr8^Itm4jSG4YsrX3gUG%hQ$W z_$CVr6Al-)(vtgnoe}r(1CW%P6!jmZJnb)S>;H={XJcjhKlE}I`u`5LxTJ1ngV6@} zef>Z5@@kNNB9mZ&dREj?39qgI2fBSkQw-oBokK#E4M@W_u^+FTJZGb}cmoaPKRCH5 zYg>41hn-vlMv!Tmwq&Mu{I4{9LzKdVB174Shpfm1i(=uzhAH89hx_)E!;;m6v=OcH zj&5?g*?wX5G$H` z^-HI?Ksl#~9iUv*t)A%+NAjK`{c4q&)eT2br%3^mB4JV_{}*HL6l7bpZQG`8+xAM^ zwr$(CSK797rES}`ZQGeQ_ltMqy@<0vPQ-}$G3LkoY<2cldnrv%YPb!-w41;obM~>b zL=xQ)H+Oi6trGK;?G|fufKPVK`ahfcUDoSj>BM zjtT1tXbYA$RO7NqG60NJ8wjn!QrLpCTh{IJm5ato4atS0tRQrAgV*^B(#;rwxf#)N z1q%o=BDH^DtEw3Okx@j68f7Aw$;;S4%9W+jU}ZU?MiHJXuQNiwI-1)=E|kl3pVwiW8}rqfn;3@ zBZN*55exa%8G^E^4^IBBclgWhNYxxIALLs_oBq^FvoOEyVzM+Z`7bT6c{|ywjGBT> zsVZSoFw!%2!}$IFur(a&`u#rmGOje(E5)SN{&FmzEB$tV6?Nx_%gcY5(Ju}3abn6o zffZSLIXT@M+hC;^Ik9phiC=QyV#FiMy)Ith3uoqz*XFKosq_oE&!ylC@sSPKTn7)7 z!>a+16f7mS;7Dld;)Q?AmU4zWBN}~MS~|MMUd{cOeKxMTR?oJhx~0t+o$bCqEP@qw zVhJYSoPYl&FeF+Ry3~lFA54tRof@L?UM^3}-Him99njkW)1mr;qjm{>Kx+1LUsV2b zCm-%A3z@NfFKnRASwqlfJ&E9j|LkvR=PY+`^l)dbFI|s3_;p;bxjS-aG&&4)T-R*P zY(2C%xZZg>Gy71Ny&_F6jFLyn3*!NTUdZCbd{ld#&wly7EWA#&dhPl0Z&pyf5{fwU zLo9ucTwR5TXox`!Qc`sE-vr5-qHw$skSX5^nn;9AhWQfqK3LJARVCxmfe=-oyR)f1 z0TJ*1<0W2%2o~bkLh9dyB5WkGRc%dze6S}Zu~Hf!5T=rc{=6U~jAKJtV*njQ3vMh5 zKM_n5ORn8jXdVqCKfNB$OldRqHS0TcrE9G<3$EMXDE3DdIEKqo?&`&0J-Ca^@kxBC zxw%VD;qDG~;qIn$_onRfOKtD(QQJVc4T%h5OTW~Uczx8wTZWaj(p$k_XJ4nKOP{oroy2-DPIcC|uo%h=h` z)jpFVDDt=g%eH3Uw#gGcG?Lv#Bq>W=csp#6GWVCa_RCAd@ zX`s@Hsj5BTasUcBq#5y+5`&+T7Z6ASQSVTfu%)bQn{<7tooJm@FZEy*O4hwNwl^nJ z?ZXnL-W=#f#Y?-N80=_8-fI!G>E(2wJSt~4AdPPwgaPqBP6!Y(qVE&QM}%LQAE;`= z1A)J%eA%BrfIVJ8st9%$$s`vrC!}6%E#RD*jR{qhG4k%ipBPD)fA?7cA_gMF|A`Iq zPNp~B{4oLwXehp=9@u|izyo(YHAOk)5s*QeA{b(g`%k_r6t+5KRk!+>%q5^gTQ5pw zgeh2~`miXLV_a0=qOV4s?@Dbv>YQHmdnAk=JW2(-2qCWbyQ?gU81HyX3`J%yS9}Um zIO?mFFv`A%a5z)lHLMf6Dheb;MgF&N?-gb;%(5QD49(M zCPg+is#r=!J@4o}Of|2De+8cqd?GRiXjBasH!i*_Ik|Jc*vLqj)d*!Q!U2>8cS%q% z=N$oV4o-~hE4zZ*AC7ZZ-kccIuouI4Q8T|)nZ2>)4wZV8x54Av$XJCrl%c$<()+60aGt;-1ueEDT*q#iXd!IOrqnjNpJ`}K5rTLTjSzeH834AfP+XRB`>LIe;ofm}pVWAOEMG@;k zgzc!tQFr0^Sadd~#l4|j_4LyYE-P6ducETXHar3{IUM!~lZhj`Roj5gDgkcpaU*xb zK6s9|Eoyp<-S!^Vk3uJr0<3gq8UP{vmmUuY9{KzV$(t z(U4^}sS;K~M~WWi4X1zwfghCTJNlN{SAJ1u_8IMyAcpiBA`h!~{ zE;#ynqyOin$!Xi*UpoYQ1wCK{ADOAJViY^%C4krpYSu(1$p#qw2^<@Gjv`p=14-K3 zNN#kZz9)H=Es8-lNY97$lG>IA(%|~)RYb&AqRqpP%HS^Z79vlC{%sp{t}v${1U+c) ziwa=sxtNkiK@z%N&^J*+ij@RN{1}`#0fV8;i9kv*_%vLD(lNNzB>j)g39@)l2_S|# zB+Y+@d#v%`Yb{D#y1PWr%OYBg<9G|&tPqElgNSdCl674!l`CLL@siZ7isHJLaVXVR zTqB@*dyOO_RiI=6q^Qw@n8&IW(34czw{S=EMMCzjqLAhXCd} z^HX`g=0xl)TKZKA8d~T(1wpv_(bda|rkS8vT1Uv_C2s8*|C&5S2 zHkcqImiHqZ3o;0*)CSeFK>%9Oq*S(wH>=Ir&;7M|sL11PUxyHe^v|1$Z8h%1$enf- zP+)XSTigEu7}2iq`!9+34+q=-mx%vg!V4qguXpu-1Eg!h`X#)yJ#FhLh+WL$@Fv7c zgtr?w^N;w1nc!K_0*mukeSV=s2^Hx5pf{(1X$qpTigEyA`Lw*VR407%XygGe6EwOt)*+pyr2P%6t7hz~ z`66;!5+_Ng!oH(4q^!M*-^HZj9j@>@t^#?Qv3Oy<;#KhhlleKd#ci99;1s~H$MQ_R zPjDq_)u*W-W@o$|wxl=LQSSG&5_cGf7RxCsm8^oApw8~?6mG=;roZ#)?#}m5uhbx2 zqmR$Z*{#eg;+KUKsnBS+db#id{1D`y`PE~rCF(&0xvpa`3a%aQW;u^OAZB6hms_7~ z;i$obN59|*k(RJGI~FmTOk4XzO~oNW=a$3_(VTaWzn@t?0YH#&=`O=NH5H)W3MMeB z)30YOMUoZGKJH7>Jtuh~)=cm>F3igoamP5YoGY199E`7*jilSFhZefnBYyum@te-E zNTr#PKMx#h1%UHfMAUq-GpgqKgKDe+W{FxjrPlviJM~Kz+wJZ}DPtcIJ2Ngad-93z z*vMw!gY_Lkd5-{>&MhNy!rZ~DNMX23<8d+_FuXGqDnUOo^Ua`z>xCf!gz!=H1&fgT z?*5Z9TADnFK&(1+`8M@h1l?%#=OR;=rF1<EW*faMWBMgO3WUkRYWsvsD6@mgA5=BQTKZO~WWsACyfqF}$IW2k3>+yq z{a0Z61Y9}3X>tGnT>dO7ru#V8LZ(u`A41h zuThD~W6?8S6n1d4m?s)JGwFwR2hBU)UX^gvs|8N7cm-D3@D!is(FE>_#iFcm@Ncls zaH49B#-$qB7f`Ka&%^vz+&RrBut-70m+ADLlUH?TSQc2@XYnW*C9f!!npL#f^s;3- zQm}TPmQ25VS# zJEH`~=2dfRh6-N!>9A5}j%z0gGrc27*8a#-CaQCzs~(LJI2tUJLYyCdTGi z)HEu_GF`m@SHa=4%MdqCyMC`bI)HT*1d9W+pX`DEfcEWi2O*(u5D%G@@;Nj?;5{Lf zi<83ClbS#h2z^Z@*mBLL z#0~n*3(JpS1(`1aiyJuzTe()e37^tc|F$s=Dl_B#Sz=z44hA9-AS%W`-C(7tQ%U^x zcw&2n*Snc+$CHT|H&0-O*yjrRj1*Y@H6z2GffMm5UUlVplV>pk&u(~3%R@@J7$-Nt zIuW*=Mb${j8XTlgkFJ2`=BdxR3V=;tOrEvAu_k-a%C7;Q@|~z02gy@eV>l&;!Ew6e z@WekzlGPL&vj~2^+16xz0GLT&j`OKTOTI2_;Z;ttjmX`sh^!zGNAC8E*gHJQGdobK zr!O2o3CxH+Zz}H3R%gr$wb^E=H-D0r`~-Fv$(6-XT>xJ~j|$6=0& zD3NqKW14yM0Q(n`zuDn=$$4&JLC^R6DB~nm)mE3v>(*XWgg8yl@zK0ctghFoso!<( zUY0Gj&ZtK9$m`n?zN6nMnr${dWSK#}QoKk)y1qkbQjOYvz_MYG2HVn@hYKYn#Z+#h z7^e(C9O&+q!^6{c>8nFRcs|a;B3^UT(VD~Oq=370*ktg2ReEOgViA+nGY^&CO*F_y z(eNIcJaYtH9g9d*HI#2ffEs6S3S>Fw{9%q@R&Uv+2)*cjzfMu47tK)PZJWsA(xKe! zAYh_^Xx1)=rgtwbgCU>!XTY^sFHubd>`iXpOa1J%L{@Fk&X-A2(l!fU-VO$uvheRv zXGu)Uf?O`(7tX;YOy|?F=q$fWhc3i{(%w})lg=Z_d98CVHn+vX^d$?i=w{d|_M;|` z`CzAkntkXnNZQRe@h7Zu)HP;4ty4qC)T-t`a<)h#I}Kr9m=K;wamn zjscu!<}4qr1X7rZ#McyltAw_Y4Q{@m#iWc2NGkK==lcL9YUv$*K8lQ=~d~+-Z&_+9I7xBf1 z*sve)sCIYS|B{gy|NQ@?hyOPtF)^_HuQE~>_QbEV_L5gG9$#Ih=pQ-*1jCr@|FzKn zM_K#xBR}pb6?0%bkH;Nj6Kge(AenDie?>`mVy@L6zb^~CD+ zw=lQ`pdNdHmxu6=?C|;e#)qp@%5(h%rwpSnZRGqM&^vDF@inT>+TI^mN0RnBrjjp7 z7o2i4ggVReWpWu@JmXi`6&!XjUTBdL+f&itL@?hBbLle-+_ZKtpb@~WWpK73cAXEW zQWH&kWtl}4oxj)a4)rJ%Zp%If;eA33dIW~21%;d`o`mdthqNs|DA~Lpy&pn{LdyzR z5jVqX;J=`#kM88cW2sh3*@Mf_yo|15G`}p3bj^Ggkfopz%?(JaYz$D>47*)Y?_be% ziOeHDxB1H?303%{yJ@`0yJ=ypD5dD<9$6D4@b5Khh<_e8Auo{#sZ&4j1E4Sy4xSMk5+BoYKMG$klF90UG&FU1=g@X-cqe z*U17fQqP*0aNKSswV$~~xDKwJQVtZ#SEhkp!*#<|n8e@yuq1VLN$F~fHa$0B12}j;s$NYR2Qp^{m-%-m>6ai?TLUTj?T*G$DNk%z}qGOqCPGk zy7+K^@J~L@fvu*Ht3M$eY~wst)xRtPvynN*iLfE{9~$=#wyLQ5FMG5INj|OxLnA8X zErVOODxG#ZU*5iT@URC@x0WYNVt=6t0FT=5k4p{>bND~tRbx5Xx9kqj{x*S1K$W?- z^9Nb>oy?W{@y#zTR;dY9n=yqG3N{sg1ajOv%4-=o2&AuY&1An;O+ zgRuf)o?N~#oqTwFqgwgwZS<_^Uq7!y;$iJadhBPk!x;%iS%#Y$pVP~&^T%XKhKT9f zTHdU@v{~ew8sOp6vrt)vE9*$U71z7>X^JjhGv%OLdwSnz1a{tkEb=7mu4`@~Rb6o*JfUHgNpV^|tijTc_kswTmRMN5uk` z8P$S2nCtt}b?{dQFP9p5W}3MYy&{=E zKAKqgK{a|Q+6vC{rdBg)sT~#~W2hZJL!(oN$W3gYogOqR*&iIEk4|`lW*9H6VMVt) zzSZK(+6sS`MjNadT&(!G!P-`vE|@BDLUL!RmGXkYSjO#dz)V~6Ls{T2Iy%JMv(-12 zG=&BarNj)Ko5SHJ;-o<-*_8JAE`c&o0z1=qPOjnuHEcvU>|+4>h@&M23Z=f(x! zQnxcy6_>h;4*01FJ6)s zTkRCLQ*h&6op0bqnXT3U!(Z)t%S!LI@G`JeJ>x1qIK_3%r@4MDx(zKTPh{quSs^Yo zBbO6(s$T&oFLhv4Z{r)5V3KTH0Qya{AjGC!zW>hJQ{Ah-ryxvLQ*UCZ6z+G$kO2us zsDm((0VhPucKswkoGzYOl55N6&6Wqk*;sxWKY|iQ-epm*K4k$L!ipI50DU9Dqsx}x06+Fps1O= z@QR|4@hxjWJ54XhqC`*JXYNLVw8%A+uFT%ohO`Y?ZaXvomN4g$J}pIQw$S%zWtu=D z2)Zv5L`nS9Aq!WhX31CnHYYmml44m^>UQ)#Nw=cln@5eRx8MhUd#<7u>qzvl=^8Dy zZCRgKg#53(l3)SxHNo?cXDG>#A`?J*P< zyJ>Hss>^Pd`j1Yo?i*h&>Mf055{T=K9@j4Te@Gw_LfOAnN`aT}u8#*1NoMXC?#3j^ zyISv?SINI!KqJ)t?pf}=26imBQ9yWU)$Yd*P%nRd+|jn98~Z=D1F)3x2J~)vZj8}X zq3rr?S{Hk^x7~iOE$3kK0WQD4yP+TcL;v79{F~E`|KqIZ=C>&9rJA7kOaE}?>vmb1 zOtt1ZS#_PqCI>3)6L5uDtm06 z6{x-^kKjr-Z~&Lo^|v(^;)pNQlTpP`d^+EiFpNclSs(ODZ6s>fp_A*s2u1F#)SlGx zZ;1{`Z)x@bc~g!j*E30ox9$!NH_Cv2Kjp@EPB_VQ;Xe_%aDB$Dh#y#=EH5lV6prS+ zPZH6Ghw&?bNKF3~o1exbM;NuUOPd0NfW}&IfgJ?zq-C?QMm(>jkxhZVftTX9+S@huGA6kVuRi#^~1-e0(0?v`jo5n#eo zWZYU?j1*zlMBW-F-yuj}RU3ZhvDfMm&0q$eI%m;dfnyO&k`8?958qMmAW|Ax^sB3@ z=xer<5%OaKh=VOn`d1dE(ekm);qZ!llg(IG&6}sBtK<{6mK)`&gwRymRQXC!t`I_H zSy}L|9OJyzy?R2Vqh-X|nbJ1IFY-_jWn2*!kp^NS?!=5A#8J}RhBX)hbqHFvwX`Ho zB!3G*{k@hA$!-j(ibfhR!b)zSnG)_Q+9$G+g#SGT210N}%|N9n8cDw1C8^)IyENveU@+loa_YnXry6Oew=7DC-Nxo@k#Yzg%I64^)``4pSn|Omd9$gr zd=zR{D6+OYi_XM)$ixbSA&D~GjZBI@mp>^v^8Sf>>mL%CbEk?|2vo?Sje=Dx5_>%6 z572*u!4NJF zB&-%ubHskA4;v>f^P67Ljp&5Uiu6i{b}0U_H3OayPvL|ePI8s~#Y@8H6=t*CeO#wws4yZFL{@r|;#pM*uWCz4nYhvT#>GFgQoTruL zLkg71z**>emwP0pW5J``pcY^>#U^9CDheNhok|wkt!mS|(5-5nPbapvqN(YvD(%u! zt+j%1KMra#EHo_!f{^Ss5jPnK8%+a04*5XY(NE{3p!q5{@0C0D>>ct`k|8t<{MdOZ zs+Rtxjem}|HSG;BS1>hfE(&?>L^WO~1rm+Eh-5cir!iFYUR%mH_&L07;eQ(rOzi)2IIuJRZ->KJ%mzC`*MFp^ zQ*ll9fLLJd+1G%_tO7e=PFN%yM+|R211M~?Mb;CxZc#XgA_eNu6}n4>MZbm|yzf<> zo-5uiB3M}uR=Cg>yP$YzP2T8~#1wF|sCx5X2kO91tY%R1fdmI54kPnY+@H(+!s zV(1b3sKGOQOjMQtG5DdKd-4H--wpnLle=98^)`NI-y4kU&&)wF{p06){29sXILnr!) zg;hHGG?ON`WPyM@2EED2oLQ9y44DH^cmPRgkOl@N)BSl=kqKsN_Mi5op(g7RjRm`0 zGqdRi>Il!3SmWvas5B-?M_tfUlJw%71M}GN*4Y@-Oc#Af_`phHhiCrzsT3=Powykb zNNUW4k#-ie=4FEV4U}siu-6p^+mFYIuM&EAjYBtH`qRg?XiKoiLQ}4g26R`iZ zPxobdm?0Z|L>Keq4@9NpwT3o57)1EBRXVAV5J_V1QbhAr!h9M*mW_ zR~n9%sy&y+smQCO*YYoCjBC#aag;j9TsYGe?sIH5gQ122x%@69Ueu8$L@H%}{uQv= zBZ?&28=cQ{NQB`Ye=257d0K0)oCf2Y2BtVhwR?zIhQY&*6c695%_W&&dAM>Mo+426EQ^OB^pCTU~4bM#*q|rqLcqc zMFoK9O7L#)+a;@@>j zDx+>F!^l%Q-!UY01vy6Db-1#mi$4o1n{rlc`B^mrPFkw%)i3B)VIjwHX?9bp1c z2{;v~UuR|#!NdcU>}GTlLIAKGdwIuI6dSvGLIa_&e|O_QkOeE{xKDFYKLD-@?}~Wm zr0jSi)@(W3@#*R!({$@5S8v|>hZIN^rgtjKl$Tr0wwruYoS?deD+m@~<;!-8E=ZOM zN5lI{wm;sWJ^ht&M%uuEffV{U>HoJ&7sxS9$WW(~1Lsf+BJ{9ph{=uivsc z9enjD#h4RlyHKT*@q(cxy4Kr`QD*#W;6u-!jYD{YOpL&Ot%RwgV79}I)2_kPHwXpmPosNx^y=_Q$=2(wQPWBe>r(PqZ_G6u{D;n1`vTqJ^Gc@lPoAf3qaL02 zOO!-2e2BJK9|90g2+zOEDO2#l%QoBncfBLsfLdcKj!&FOc*dSd1z*&ew0P0lP3vdveZ2}}|h$)7K&oN>ebT7DBM>eKE6hTt%QJNO5amAr78+C8uU~1Vj9bEC8^)U6Vj8 z%k=l8g7cDZYm#kiIrGh_bkfr3Z2fS9T<}D{UDIGmc)dj4x^O0B=SSxc=L~W%)11 z+swZ&|2GwYEv+%zM^>cn56VZNEgkO{Tn#GrzZ`lztq9Q7ohYGKFyN5xRkenkB~R+UBNpwGkY4ZwneDj zH`#GUP|xqVv3|UFlQd@A!FmJWUl&&gXMS=?F2o$ba9e&q-cayKDAJs#NoK8bFDrIi zH*!A(${$_qzNBBXogWvmF`I8J)H58)cx<8bi*>yzKbH&ZGy&5Wz1$L z$+c0!#&jqOh7ti5?;;6463Iey9q4tY4~L_I;;{0RdPPwvb*M}AU8&Z(2$Yuu<48yK z;sS!toNmEpxC7>O`>4$Gfva9*$h2g8jeGI>lyXTMxGe(=YH>nmk9~9&gp-5?%PZzE z5Wj1|X{>1$&-~61ezU5J4ReHvxeB=V`4fEEIVVT~0(l9RV4d7Vi#3s2nX6p}VMiR5 z95sc;7vvc{KNIwnEYlf$FH>xQL{p8TM7UaEg$H`2lCI<4#C4KdJvi!-3)xCugJgT_ ziFwxZ^@heAQhu<-zYPo3MiWtHxK<-Aqqso3W}l7d=pvO#exuvA&uH0evZQy#YMMD$ zl44qh{Cs#2-o+Vz3*+jlJ-bl>g(bb*?8PE4!Kk1zw|3T?c}4fx+==DFdt8BQp6pVr z!KTtci?j5jZaD%@_KPP>D-$SLN8}ri~ z!}7)W)V>!aw>u8iO}u6qqP~2h*jMerkS{7V{Jh1g!GwePd}M=m2Qa?qkpCJZN{nE`dBx^mDYc@ zBVYPP;aYpTqNXL*m>5l|m)#}MCR%C5#D=XIr3|rjQl28os|DB4;JZ_iwKzRs)g7iI zned5c#@s}6klQA{qh5gl#A2&mf*Yc-f$=HB{ zZ}W#?MT<~_^%ufc`5ExltOC8U5FzOq@Y(BME3084N+yG{9vK>%)gft^`o>(v^S#-B z*#!8$_h8ZW2_8PC@`w?+t9gW6Rm|q2=XM);`HHk`=Kquri;x74zk`sEL}+odM)wyB zDFqZqDCbjZLRv1O)$BeA+uq&?7=T2`$lr zJIdV2dq~+J2|6@)TO21_tL~^tPCT1JHH`+iA-5srlrqJ|P?}*!EJRbthkER|_i5w- z$UR~0O8aPV+o*RG)DVJ0hmuy@g#qUUdYSe%*QwVZaMt?w5ZA_GgcmMsL25+He+ugh zxM~8T89%jvqA8b~=nE7V^!DQbp(Uk?=nJ6L06}}6Ahzajk!%9!!?~qs?xH`ouCdz| zsf^h0u)F(>s$JLHI@_dRn}ODfPsNGOM0Qg(Z5mR+0xhwjH{Z+Y+KZHv!G%29G;Bs7 z3o%i*h^S_0cr0l%K{pC9huQ|GCX$}9y7_&XG)Geo{ENDc-d0@@voz*GoBkt=K3Ms% z*%*-gNP!_Q`toemO9cY84;@g25&5PTsMXQy zYlw||S8N{$H6oKAQxWUmrTj!$IN#EwtD#eK*3``{`tR?k9-FIWF;OUcU}kEgj}dxEl$by zdcLw$I1~oDq9dZFOUQ17xk)ClSdJD@qe^br)0u*xbW|4H+S$vmZqh29(`yQ1kVsg= zr-feq-}{jLT{gV0v^gg4E!Y`9*l_8D`ZptaqoG|A_2szxF^>Eoo?(E8*6ln<*)I|N zuvzKchE*tl727B3=kNmCF+-M7FbQ|Sm2y{T8~^F0ad z`{!|4icc}QYr9L+v#{4#=Gt@}=Zu@&#n>wJzcOay6_PfO$P7;hs?IWYwUt<0vcnCY zo8y&~-U)+}3MUPMl3bY)-AeK^xTa4=GqL6)L$Q}FrE!_|Sq%aOP)qjYViGgXVG4cn z7Asn0&wgJ)4QNuG!;_TY@DhL z`?sg+n$5~_!+qhaP^tR=w}{8~KY5$KCC~qz$L~n1Erys4Vd~`fOhu|;bRQG~NHilE z(2SLg2?tYG4DRv=Uc0l#wygL}102qi#3ivZ$fc9&`F0=|-1qhF==1x2KxMy=p`tfz z;G+e27FgCVU_qt|4$R*I^6yIzTn`=xdPX&q&S+bbGv>SPnNoJQcr7y!iVk}F?&A=_ zEH0#T_$y_#v(D$s0{YM746N1L+jO9{T5ajhwx8!-_!@ro`1Zasw(+3caZ=iWI5qV? z!c06c>4Du$K;UB(ySy->4o>X)4s_DZ?@huf|B7sigil@K@6>xHk9O;<@Kk1`OqIr5 z(wJmZ9ddbOi))r?_#GQfq2xBkXl09RsT>Vah#8wbgb_21afZawncscBt;i_zk_5l5 z4k=xia%U9dx5ZmB^T7zE+S96e->`zn^2%qCIqJMy0q*riM3zDcOH{-F_D#fGipzqCJ&hl64>mqUMaugN-QGbn@O_k9lTIxrvj z8PZXT@7g6~DRG_HExZX!u1HH46SCHLsZV4-A|)9Y6E|xMY0Yx?Qy?RM;QlJ$tmJeD=>FWKj1DArhRO zQj@Kq9SxmSUyG|M{4IV=Qm)hCBkeM_AWhY#Qlvt&i(s}9{2Nk~eIxB)&$2;jWZ~yr z*Hf=LgXmnS%hpP5h+=+5|N#9`?7;lG9El^1rd?WtC zhsXrNghl-tm2#k7=Bf!Ygk7+FILfhqgQy#n5R<}9ejcfNs_kR)BdRs>yO;ol0!%XY z=+-Ip>G7kf@1AkxqE!30@7ew+xG8m`fyz%Q8g`Q(5i{@VUS2UkoeZ34*GIwy<*HJi zecu{+yb;$y7SM`?Njn+?)Sa5m>x<*-eshBzFq=jUl3KM#aV!onCqb#E`1 z4{k@-7f+4W@`Rc6TYci{^5# zlSmPlcBye+^q+(!&mx~d*0rn>WDscwvuzQ{YrPPcent{Q)V4eu-*_s5@^xA`QZJES z@L*b;VZwfO_o(H}g#2Ks+|-^^QKIs#7L?LPQQ|4at;yLnSQV?Gh{aoR;STgs z>*kZ^gm(W%$`;lsJ!rWXtrK!j`Qut=l||%AY>GDfEL4ymJSes}1kFDmpk~^x~*w zXi%k1>J1#6-Uw8gWoVQg_q$w8GL^JCGw8&)0AKH~xh8(oENnAA1aviG{3BeP6`h!;rr&EbxD|XSV6x_gZH|%# z4>gXJUQpLv0pOYu~-hS<4!0uL4DCUwIt7tm)6Y z$R4u9&>5mNv(r^0+jVUyj5T(br`5@cGtk65Fh;Hoa$<;7Ns(KsFcyoMd!}yMC|!>T zNo&S^5mx26lcTBSjfj~_1RWn`VcoTe~fOhR$=LN6kaV`9qj{7#Mh5#lym+g?f@)Tg3 zv{LNdUdkqI$tVdRlxw6m&K0LJwdQM+@lezYJ>>R<1jj2Iy=d_gbR#N3a69*STVS=C zNDP4vA$fcpIp^WKw=PGb(5YZWDGyCR{tFN;baD-@rMKjguNy#WOLjFHClUG&U;>QJS+gpKG4<+aIeUviL)bM@Tc9yq=vnCdl_Z?X0unu zLr7`mJP&}iHK_)N6^bzpZj=KcLmXMEzV)f}=4JV@awbqp>)xrN-G?b0wyxHPvDCi0 z#D00srSW`G--Dvx{AaSneo2N(#62%4CTV0S0xnoi>g#yaRo_GDs!V2EWjg1Q7d@HUWN?P;>UFV)=x@s;Qe;B1t^RG_WgXS31)L~ zCz72)Fw1?yQc#SITLmlrGUFEz`{U?r6*Bb&!q1UpBEcHJexERPYptn2Y|%-3)RCI^ z%Fs_AQn{TCJvX(xN>OyByw&I=XYo{d%~}2P;VWg6j7%&iheZpg_fgR?9N2hPltGqG z_AH9~dQpG?{)YjWk2oZMN`|!qJm_C=KYayh7>ar^VH!)$OPcQNs_j5}cf`yr*=TWN z2RK}x>&6WtwX?BL4Z`-M~jD?EYFKSm-pD`UsM>brqJe&!de6(eC{Ff4^Tl1 zDcpZcqZ};%W5dVD&h)_N6P^qm|+Y-PkZ={e$a1&7`B%D1O6)c<#oL${+RKz6`s{R=$ZMi`XqNn&Y zL&0jwfH4w=X6^dQ_=?N7;I?v-9nlH%db)`_b}U{NwDw_33b`v66sTvi5kj(&tAA zO5A@hp&q9y>-TN+?)y5gH07j#f%HSk`SoUWuGvlGz6|89Y*mbPivjCoZW0dA50UdJ zTm}?C>Q5lR4;kpR3;~IH zgH;)c9l!Tj4=gvIm!z#RtFF%JUMZdcSEbjmAI0P#l7=uK?M9b%L$0?!9$dHgQR^N+ z@*u<+o%7cp8Zf%VEXqf4&W_pjjO0&H6%$o>$+J)tE*hxx;I;WB&k)$l2COdA{=c&_ zM^3w2uwkaH7qrxk6P8-AT4vm0eXH&7!OzcSt&1?Ku8r?xK=fnnoSh9;kt$!2r{ZX= z!X3owroV^ji=eYk4$if>kJ^2iz0}S#=UFOOXx)8|WtmCKgQKXc&8N5JKvEJkCtg(c zQVxH&$_rcTwVsf!jvosKxK`E~Tgs}g%)7{=cW!-aHViB{z&BF8=xoFsrrEX(3TrXh z%f5fCllpTET?W_&C{%Z?A}sY7n*SZZg*b?OcM4e(x)gr$p2MY)g0^@xl@5dkl%P_I~ICNaViGE_wfJqHP{h21b9C!MkDf zQ$V+9x;`QC%3x`Q(bC{ALdALPJRT6eQm^CCnU&V!->#i8;Y#j14rFm`L`6G#sNZWr zC97{z;F6?Gw%AfFsPDEdJE4?{_&v>*^$RL{t=jupOMSEpQ*ki(f14OzAR##k>T<0@nW3v% z^`_nK2=otx#d*%AQD6>J*i|eAYOF28bN7UvzBPER0D_%XOP@19!|o9@x{EON4Y)*S zc!oo=pG&56kxD$|JQx~d-`!U~Z$BD>LJ=U&Y#Idgk);Z5hC=7>q+ z4C6#N;|wPg>a2DGDzdH+tf?qUQ0 z{@xSeHvkEA`j^5Jkxqeu@1q(st%8`z?JCNxYyPQZ@7Jxx}q*447 z=1K|AQ>V}9MUxV+=FYd}LLfnwBOi4;d*X%rb|6wIm0(GRpW|muqDFOdDH3z*tS_~OhtD=j4fhC{640140U~-s|iJTT@ ze_2^}?)$zd+n8hBkT@LDy&7jD{_UbkK6U_c>`05eSgv61zIG}XdM~W5uL(i9SaVt; z&#o*=j;2{oto!E?vMx2%k%`erJ}7#BH_1zN>D<~!l~pE^JrT1z@oF-H;G9=@m+l3s zaDP3)q7aGmW3LYKz>h+(*(wc-8wl$TJT5g<8x9e4DI7yH(MSPMWlLsc5p+M-GI9?qJq^&I0h*rLEgVy7@#t@OH^Eh*B#?BGDQ=_; z5Z~N(?Ic+guG+w;$&Uo7w;d8X)3j%?+%o{wp#uK{w=~;(b74p4Ff8qYrI$rzh%bKW z`N`F;IE{_6Z$?`=oe~?S)`M4DGtTavAXQN_UDP0Q2|w_&L5|Xaaste-j&^{PuKV~k z4Rq*eqmgZ^rvr#lZo*Ss3{=r;e)KT|m#kP2=!Tq{1XcUu()|cBeFU#F{ulA$d8b$1 zRs#S-ke=#6BA#;>&QZz&{G?r>6 zfGZ)w#yCYu4|e{KI+m<=NKIEft<)0gHE#Tn22hV(A#tE1VOg5i%Uff3nQ_kLT_cq0 z4jlzNFky^ISUMYK&n1Tv+vEg?(yCXOQ%TIhzZ>7Lm-WDXmIapHd6oreDucg{uEl)T z=;r*p(9SGS{ zjHTBoMty8e@HUe59n?fPN}bfLI>GHRFP#^?yUPsq_NrdTx|^8f)^t;w-Y|0Q<@aAR z87_G#2Zvt8p?9Hl+aI^J+6CCAa5`8j%4!Vxt%t*~MNMc%?39@l=!~mvIB%`TnY`abkSL0cx z4euMj5+}WJ=5rG3*rg*v>6)Y?txKVD=gBG`5RfcLD?cO^lzm1WdoOVk9Tf}B9$kvX z18z}x*+=1~rHn*%pzS{OOw>nJe31eLy`EuIhi#pqdTJfj88N=*$uYGY729stzJ;f( zee?F6boPF|Eqy<3W9aJhQCQcxmyp58o974DH@rr!C8qySTr<)C|HU;E!@nem|F!5u zEv%hQ9O*=@4V+DcO^ob}O?Y`Botzy_3~V6XH@dYXVvX8idRA-i@XVuMK*-U{95??Q zrHF0^W(7`Voy5KWhRGu~-%HF|vCZ8y`}%o#e}35%IS(@00Vjjg z^TP)A?%((8-_K_OBLi-f#P0dw{JP9`veeEF!DwAc6QB(Ys(b3+=u`fpoCHxn z0evYGz{PwiqDyxxG0^D8jsz@+MECi3RFz-juXVGX1NN24MmbDNGbhHWsA`$ zBo|>HIe$>C>)STV0oNhu;>H&U0ibF$s4|wH# zq!jYX)dl4nWiW%kI#qf|7GOYos{RDealr8n@K#agI<`BKvY3&UXX?gU#^cS6N5j%r zz*S2jePrYY)a_gQnp#V0mi`-!yda@tFOp4yzn5{wZ9HVhW*HS;0swVd}ib* z+6?jwc;@eifwvo~!>!{9B;)bAlLN1Bqjr~FvkY3a%d1re^VB#@FO(QzvZR=jnoI*&bGd{()L8QW- zVLO{3^L1{ZZ&wCiI%+Kl#mgDin)h@MrVzA9?yL;*eY{mXcF{v!UV^6!^o~nu!QwN+ z2j&isENK)sg6Oa_NWrjFHF)s_1M8fhGS~JUtW^D6HY!2x!E`Xf9{u^eZN>RlA9Qo_>etfOz@|PKej7+$s6-=ST1cX8OrwQ6+zeAUEmO<%P?XV!Omi zhLEJik?IM93G+hFX_KNKp@WvOhO@$EG%RgVHf!Wj zVsTNi8R|@kJ?^TchG+yWNu_@p+&^*veyI&MccemplERnvs2?F36b00*^IZ~@Z-9;m z%NW(QHY>#vcu+^W(+#OvQYcmtxmSC}4j1@T>cnSkKtg{zh2757t4nlvwFza=Z|<6H zcy!?GGt>p~pvp7yBe*8D`bohX*;~Sa7*aI$=7rn#JM?>GrBx1Vu5fVz4>&lwB{(cb z^E0c-o3<$(o$N5mSU*Y;@Y9yxLc#Bnwulob zPx0T`Cb_q5UCPc_dJNmNvzVM<-}8Yp;D(P!$2ymxa;SY04IYzW@^P$~C!KN>m~AKJ zX5)_@Cy*K^9t-7!l^U(lBVG={FkABKY_)guVLeCB^K*96_L;95rSF!-1Y2jP>H1=5 z+~URYd}1|CVs2Zv(x4)ET#0_lTGKh3lWlo*5Ft;_NJCfOI8n5#r)PaNXJH`@(x%JA zVcGx<%d{kD=fIhmE#$Dsa!=Pt>^}>|T#Hnlf~oGiHN;`a!=W&Gr`y|O=AZf+#w&#N z^E32TShkgHH#w*JO8Vin&^~*-aw?20{m*W}LzF_$lj$FFuGd0w6}i@W*sw;H^3<$< za|K5U1Z5Ox#}ja&A@uc9y!! zT9DZY%msz8)j}1AvhHb@G{TaqktC_+uox^EKQNZCW`v=nC~D;GO4D5o8-Io*h{Zg{ zNAM#NlJ1a&PQDu`#c_^R=@ckm4AsuDOd-h0$B=gQ#5ixFx zP0>dKXQR^X*1AmLDa<@PslcNXmvg(5;v+Cx*O7X;k9Q_rP*jGNk5f!_XHhO>UvX;_ zsc*Nd1ZFq3tUVe|0p=(w_B6ns8zOXJx8up=!D_InFSnp@*o)cCkN(84>M>EQ=Il;qJxUT81mTsT~k+&-`QV)dN;#F?T=9=KXczvCLZiypps&%B$hs zYICW}wlSMmaKwqlb1#+YAnP;pW-p3{?lmUIVyx;{B?T=WY$%@;c> z$}w)wj@37<8(MilTFkcNopq#Rof7Jt$vq;qSr1!i3UH3F4ffMcKS~D}l{6)3Vs3nz zKMptfbH;8TjH6II?r<>nmuYlzY|U=GK2s4i_2DWs_xS!9QGw07tJ-Skv|4QbEP?QD zr=NwF>LxRHF7mks`8Gyo<$iceNREx8Myd6;{@$R%dP|U^998X_`1I_q6Yw`vuduzd zX8vml5Zb(fX4NuBS8)SZ!sZ5X+tZAn;>g%C8>?K#AQd-xxr7UBJtU+>6HPoZE22EJ z-lZ-Jk#H!0@bDWlyhJZ#mjoB5vsQSut|;tMVmto^R|z6X))Cfo{PMss@nFdXjGv`d z{z|XD>`Q&IGeE{mei3oo`a;241HHcqBJ)zzB0c^kwQq8Pv!uwwfJB0#rzC+` zS%TypTRXKV2$)LgmaWb$5cFoX z+wvWew*KnZ3BZfh(^+3|mJ^YcjV`CoQvP=;m-Yu4(q9?O$s`+`QL?FcA1R>Gh?)Y_ z#VEXhoeO2gwYL7{+kGYgKT4C~j9USXSA}RB90H6GTX$fF(6F~8c|4a_J*`FGzj6eJ zY;?v*5p;*bv!v%*?x8ve__Pr1^i5)KA!&owVV-JBI9OG99Y;}F%|Cf&FIM>%kgL)k z`94^qSq;6$yRiVCKubETjmk87+t*p~m?`tlEmhNApV>^D11SkJvR-s~$(1V7UwvokOsCsA7A)#Y>G2~Z|BsLr08x*Qx4GxOUxh>>uJ37cG<`Adry0@T?QeS!SABH*FDG}JBI`>}+rYkS1ryFXEn7-N< zAAt}bIF8)(;?@P-3zg9QaOeY~o!xqbunwVF32kCCcekwja^7#MLm7*X4Q|M--EX;G z7C8zg%cJK&7CvP&m2$0Cz2TuV0g9>YT?4mM9lo>YB`+dHrya<8Rz-M#?pT`M>$@9? zZQfqLo?rZ6Nf^EUgFa#4VE8ZdU)jUngig-TQpwqdP8Oemp8lUcaddLV=U`|5zX)D- z7W)5|cKM$OUhH<5pBz1ce+XVYS)zDC3Y0K_b}1*B_)bs>$R?I3L!(-x(<~jM?(^c` z9=K+%m~9<4Uk$8PfO|(%W<(JlVmwKrb?PGgb<43S+9v)AcuUBw3MdY6uT08*O9ufV z632eQW#7`!ln*VMCc{{KdGofoEoS3hL`f3kiX9W8sFaQ&g47E;!>X!a2VlA~el!_) z%@;EoW2a~G{hV~}z@$IQOub<{70jt~T2kLI0m}FaCH(8lBfI=d-lWyQ2L(T&pp+}S zEYjScSn^R-$asH7%1(@o)rt1uiV)drJyFHKx2poeKX`(QYA8AkWr4!yYU*AEY3h*u zARp_=ji3+uHa?WPwAQ`yA;)2)g6BI-AaIg~>M-(y5+eCb0+(!{4w1`_6(Nd|Z(~W2 z>q8mZLJW026Y!IFq(YZIc%Bs7Ukl=hs|is3zl5~dx}h3lPfpN_?q)L-j&J)%C*2J%c^Qne#|X)a!>LkBN&nbGumG0 z>s3cV`=wLHTvYd%B42?3usA-%Y1H#~q+m#Wrkg<)du&tu&v@Y``!)5P3gr_$xQzO^ zpIu3mX?G$e%7(SQn9DbE2bA=g{UFuKRdu}lOI+~?^s8CfV4H7ek>6PsEtFk%uCYT??kijSB~UmJkwc|UGC_osX1N(U3y zt$VO_{X9FLD$zz8^#<;~y&c$fu1MZ|H}HO#x$%70CMzS=7K4s)sgW=;%)ThECL|q> z%_s;(ui)f>I{bLP*!`IBazgDit){BOnQbTpz?OIUMtZp@6xv2W+oB}JCF1=*E0g3y zoFr%<;trwJA7GOJY6{y)ibS1KOVsOFHLQ?}WpJP)rz?ty-Kop~zHT_{iq?!yB*EIe zjr)Emao~d^nfEaLRfX|}8fZAJ@lf|!j-Kn%$sx1wmBIt}azhM>2?V&+gZH*c+_~n-SUfm7w8x;;#p9j3hx5k$>8D4>Um#RH*&P`M zBSPeb1JOW8cft^Zomy&-YVUb+%d-{oiBb0JixEHA)xj-0C$^ zyq|g9Q!L(JSvLHu-8Cdm`M9oq50G}yBEk&!idqJf_I5I9v-{OUy%;$kNrxVHwzuWG zM{ie0?o3(KUv8bLT^dq6KHS+IAA#HJLoq|(h?PI0BMbF_(qmy5y~JG@{Ek2rR#D`N zaey@8-r@ML^2Rv`c{%KC+oys-2>p<-FVCufFU7gNqf_uH=hJHD6G%pZNL^hf=N;nH z3QL!*nv}!ApH|Uvj#w^YzFs1=bYAu&Yut?dUZjC^ThHfok@S1Cx^^VwHQ{s!9%;C< zR}S^=oKL4(@1C^j+&wisI*>k_^$X?2@~cC#T7-kJK332%m*TMFsj5XDC;!3G9;US~ zUx-Ddg434<5jk^TlLY2jFfL-3G`9h@oKpM~g!I8dD7W}BS7VY1 zm3+}j&;vA7S=6ohJpxGf5~tLOH;kh=0_qx8F{51OBLYppB;`X#jg;>`)b}&=NBsY$ zrtVpJIB`%~GVtTMlm#B4o2OpsbM#?=xH!@Hn>;R12SyjLgJo_5NhM__1XqGHOYg-x zGwgXGe7h_-w=Z*EP_cK8yJ(WGF4fF4D*gE__SzHNq?pnP#6A~|D|F1n7rW*jL#RHF zy2aVz@n<<@uH(y}c(4hds`MXG=a`o%%ln{1u>g@SsLOj<>H3p<&H~~h_xv?M@~7+v zs-gj=E&{RBp_&>9HI&})9nnzYhfSn?Z7+-5JhFV<2jCK$pX*?}Np=A(VAvB&Kf29T z{~nzBL;?MgVv;s5)H@izNcZ_DhPlWB4A+Lr2%-`+W*Ips@fgx<18@$$2itsDsic|_ zgx#JTbnR3oFQA39a%{pqqM!i&S}+_l``13fTy!rRvGSHG0%=(WM^l8c^6#v@>K+d3 zmOzE{*kVt$vf(awQ4Sts0X=nhK2Tn~2IODRF%m~9lb$16tC9C)V2AQ$&MP!gnSxbw zh~@&j2;D*wkK&qNG+*jWYIWP;K#|@z2aIxCjPjZyEtDSh>$8wde+klE#$mf%UQzXy zDYp%vkH^x)!|}z#LLzm~`%7boGsiFchR8rRFWSQ%Eikp)&rp>1V8aA&BJ15T^|Rg& zUyL@tVfW&IU_$cK&<`YDm);RaJ@^mF1*DCHC-xR88o$mNLz_X3DceKpjnN#JtM!o_oB#K429r=HE|^h;r_KZHC#4*y zJz%q2hh(JP(`ZjpOeEwRhm}Nf^-FR>;U_c_a_~)t1iK|G?b9Xh`J8KiD^cLHiBMEX zNJiY=o4~e^iuc4@e61#;IMxO;g}3kR5e)lWXS_qgLE&625D$+D`uE5)D4-8QifaU! zUFFI1?s5UbC{pxGA+YeFB#AfkMj^rm1kW*31{C)_G*KnP%Z^mQ_|+4_9Dl%0;L%IB z<>#ijqGGo7O9V&(QqhRuibE{vpOEF+i|+~(95wm^Y2{6oz@jXxiO7cmX(E|aO~JbO zKNr{IjRzsVCYtU!He!OH$&#qe9T@93(nDSwvM5^r9j&CPKG+2ib~UFTtKaArC1*v) z;bn-qc8MTsuN>*Y8wH+zv;$-uk@h`Tr%~MLp1&uZa2QBYMflvEd1TW2E2@8Y- zDe_AkHmM|qcqu56@%Su1jV?64w|B1*4j|#Dty$=YyX4_6)GiDysGp#PY#vE#0~P&N zn(CbdU_>0Vd5m6eD7HnNRVBS6kR2~e*$%O62?nMFToK){FGh@8!2Ope3}lM`090^| zI#&1hmoOE@H*c?Ry*26kZc3vY&UT(nHtYGc%cQsJ1bAeTUl7GwP$BJRfD0b(JM-@q zDL^}^|4^*Y*Hlhxnqa+nJEb})qzFIK)UV>V?K9`|XR+#GJ?`3O@t;neWVlpTeYzyL z*4-!_JYqd+JXNp(JqkQ?A95dE-X=OS*&mwOh^*E4>;Ju5lG`0{>j zRj#&RWCajoRy8>cIArv$H5XJkyeB8uItzeBKDI~~sh*xx=a3qJA19OuPZ_6X$Z}Ib zez0zffw{b59c0v-FxkRHvrv8tG07i5-N@yKma;khpslYW#7F`D1K0wfzmbil3Q%$w zij&KlTa%V=v>kpre>+P2uEomQg!btt*Rqrc#cpuirt%hMkn`A(_*?k!F$};dnfX$Meyl zQaicQ*HSvPq(lSN0EETQSBNu^(%!!FeAPrieM|$-Uyg5=J#F(2S!anEg!6yF1?Orw zxd_zJ03xgDwCucC5Kq7Xv<$xyP&#IQe%>#)Ut9nBVBApaO6)m*zJErMVh2igsq^_k zCuBCnMID79Z{9LwCj=sq+J$gx?v+_-M~1-SWP% zJS)a9C2>O7i6tLNW|_hS#d_Z2pQuhX9+EiD(uL6Fn2$_S1Twe@Cn}{=1js%V1Tj1W zaS0x`EmCM4N+=%RCcQzV&fa)6g-vDmt5ZL%ybFV{g{(@O6%qjVs;w5IV0{^+QfSO5 z*N>?E>KfB&DjJj@yY=AMpQt*U9IH*{=3=U_Zmc541$P`zH>8$0YObt%WuOSot*@(5 zEk(n!i>7G16VT3xJ7pRoxlgpOBad``(z#~7X0W)3CJ;yTOgW>kCu$G_4hGaz8kvGr zdbE?aBUCc9NTpj~Ju!4+1y?VN4}BA1>@2)!1`-ib3P|Y`9M55wX`zgih#_(uCG4oA zD$9aYv^dE}F(j8qODmPt3fd5*InK&KBWN#DR7pHI={`l!x7SEC2R_*P4b@Lh&+NmA zJPHg7UOoKMPf0pgxc|^73`^G@OPwfJ%M`5*1#;h%n8#UUMVfi_#xDHB-%pzRt|52d9$WLzqeIlh3$SuanUa~7WwddOfZcXUL) zF&Ab`q#QZsz^_adsjEt&urSuDLC&&4f*lDU8PhN9)E6;GuPNB?elniH)<0Nej7ham z7u1eZ8e#UiVUcho?L0N!F;A+VN?+v7`OLN3_N)Cj`AL%+z*SP5{qz2Qq$ds>sw!=6 z5j1(e+PnB#%I8%9LChelbix-Q*Xt|2o!I*KqbjyY+p0Lj9gzD@UOYiO9=qS{D@&n( z1Gwpo+6mn4-<%o`@Wbjc^vOO-C@}>F=PAaE+p{ za|FbA%IkhRCn$X7p{8W5+y~N{6uZR*jD7N(#tWFnD*Pml|a-1^%myT!Wh1QiiZ0g8Z~99^HZZMWCi37Lov)0yS_1X{w{pH$dXp zsR}S%Sj-TX{%xAF+W@qq$ETDHn5?{>^1ZZ1n}+DEqEmk~iAe0WBMaoQDw0KF3##-t zzER;x<{1EA1ITUu{t0m!^QiH7Xo)X3+_`Ln)OJ6w>*xO*aaf!^DRoVy7;GAlfD}ZB zT+J|Fd)J4)hoaO^%cIv-xDS_C=3r{VGO@4SQZfM=9BU#>cjse1`I|*5!u;|Ck-Ydrg_G(IM9SVBaiVi95tIZKa_@O)|w+r6~kT zy{Wco@TPeV5ZyXVYok|Qn9|SpZD^J}dd|>w(H?3~{>-deA$EtbG)P|BUZ<;s?<>+(7jC|`T*fPQZ30j&T+2`vR8%3+k%G7*h77cg_u_WmO_~9hJaXJrRoEbD(nw5N zTlAdF|9;{eipXUJAOxvsmcvq2)V~xdF8kCDvyh6x>13UB5Ep&paen) zs~|_%pA2FqW&UYNjh!Q3h04Zro!HBr<*aO{h^RF>RS#s_CE0C?Px{#te;GJsdR_)0}eiRm1VuyXO+} zCZ=Wf8CyRu<-kTcPYUI7UtoJ{1GDAV{`v9q#Aj{w-T$8|3?};ja{K-dI`>~U0_%Uz z(ZiC6A!@(Zt(^nQ5CV1MC(ldTw(MhLyD)t-o|>|N&H2T{-U^Z`X;?ZA@R2W1BE;~b zXT6`iMe}|CarE+gKc-zCW-JW}nf$av3(&LwqGIP|{xA&D7mb+w#7p(l<^T(-#p*#m zRXmtH_=VklzC@$Iu7StY!|EBjM5_emjR(?;+u4t)rTO~(An`_f8EG8wy$voRv#$O1 z{@sL{9g9iBs6-#2O9PQcHZ0NJdY;@qC(+4EQ}ErQfoF?;A|DdDw1?~oGh@wd86>$* zM;o*d+`-Szi_-BF27YZxo^@jA0*d<~%0opmX2*y}h7nj&6kHgwnVu@aGTv4r? zKJ77qbao3YJB37=374M^UibDroTB=d`jRcU$-8qPkGt^aQJ403J{yC>o)`)wP{QUU zQMZ@;-}KSDS~*j5G!s#?gr@*l(|T!~lkccq);oDG5J(~^mj0GNKfBbYd}N3~WzwN6 zaDNErin_ft7fV0%lWl)!;g_h zE!}UZBc=A71RVY%EiZ*8<)&o!^fyM$Xrm z?iNQ9>pu*Gt{i&>fFzcUP@y2Qg`bSG*l!aFq=54dtJRKo!9kgaCntmby(&rkTMus92WVZJUYdnVn9yQy8H}*id-bZOP5QjK)EJeG%kqZZH{}!M zNJQjI4o0w!YP9bD$_>|;TVbHLU4{4W_9ByT;-vlWww?%UqC3lnBT32Z{jWE2#;BME z)DDC46N1Bh;|md)B&@U}M|N4tKmzu%_NK!#Qj&On5N}Qh6?Y;%M3f!M3$f;@Ji^v* zzPZg+kUu=MKNteA`pfmi zU~OR1!+DET$_!P={TG3<&xs4(>zeNq0*`zWnYMZ5!j z6ycq43TRw7P7Wm(FAXm?lxFAgoeO82sK=c)zMqJn>lwe(g z_Gsu;U@R#aPktgb-&lA#BWsq(a~aBgPfYyLjJCkcy6P}zaMrYrb(nM7CUG!)LC~0K zR(!}SXttU}|HSg$NaddOvCdU0ZJ?~!skU5$}+x;gMJ)mjgWDqmAduB&0siN8Sl9Dp7)OAK8XqwY6uK_wNZ+jfFT9CPPB53b91L-^Ec;+v}P$NT4nLC*h+jE%4;#5d=qNL z>b$hxe(~;DyCpWgq|44ha)Eb7?F^d;-n=q8NrT0b=7AJSw0Z#_IfD56RZ33nRtgSj zWW;?=@UZ4U8B$$Uyc9`VV>2~~)}hSxL78> z=V2?SO0deYV!*n`9I(xq=CKlLH-ZI9^?@2@0nSe2H5;UId-P>GO$zrFp2lp_GZ9~L z>60=g?5CIjBjiY8L5|N~to&Y7my4DgY3b*)PlAvMt*KSBF5VTK#k@EE>1PMUl(vWlOkzvMhPD{)mq5a^$3pG#|*bc3sIBdZsmg%6=?a|5gQ6$wb@TG zcUg|^SNdo2HDy#y1_PF)uI|YTZTNahV=m z@X*xqdX_C`*Z9bIw-sv3EP@pehc86JxEi)mB*ZGww##m5c4EA5#Y09?llwx>Q@4bdK%Ezz24DMI9mpUgXqaJ-y9*eqe#N84PyUX>qI zAHv%K?)V8Kn7sr}f%-%wt$z7d@A$dE@;m<0ku^)JjGmvz-hO%z1ViRyQc#hcAkHs+ zWLr52=PPP_->D(e%taADmk6?GKBAT_C+yjnPu=Rkra0V^y_m6BTrFV8Ld#Tm(OyAa zWR7Y|^C7B05~ojFNsq>-X$NDxjB(E#;i9yUQEF{J7um1S&rhs=ibRc)ezV_G(X&*< z`J0pr;*dgCNTsMy)R=E46=K#B1dKQ&fTw*0KKpP6bVaJY+`q&9kM%CcTy@2E!US}WIA33jT)DS<; zKb<3t3B-{)Win43VWin=Z1Ukhh&5L=_?rHUkZ8{#fo9DJ-9GZTbE4>AGxg0a=4?Lm zDVN~-AVkx~H5`5+;Lik6ZQyEUfvT>Hi7T{@9D*0W*WRC zIjhZQ21)WVEx{8+YYT7i1)eNFbeo~6;itoL{42y;~U1ReKQ>tic${I*N3Rw_zVvNGB;;YqbtA~K-b z_(HO<3_2WajDi1Juvi4=5~yZj zQ&)hj%JLWcbe7@tVD0$Q+qp=?%+ z^rJ9Fk_BVx=#w>ukPl67uqQJZc4}@VQZCGOutYEO+bzh;zM4w@Ef4<(^UM9jz{4Az zaUpVogqi3;!J+JoyVMT;kDiXRT81R26wdSB@x^TOLim#y^#@DJwxJPS%@m&kV&Wv9 zwTn`1o`eaZUUaUh1iFc)znMz@k&D&O5hX^EyYXs&7GfpDenw7}koQiu#I1Z&^F9Xe>o{*Qy&(fo{H)WX0dPX# z&ZV3PeuNQl!O&mhiTaMa`8yFWCWh|n@_HdeO^lz7u~;OSQnzM=Ql=2t4c|%{X6tC@ z?K+%s1m1CY_HKR?G(wvCD+lXn+YHH0b9Eq%xY=$v4a{Qo7v+6Aa@0 z*N=-oO!4=2#m+d#@>5k5!DEM|4^qs7ST1G+(h@jobv&y92`e0p z9yfD;`zDmq$<^xR`g$gEKg%o!qkJAbd(-L;?e>g7B(a<|M)94aZ3D*1CH zjpwHJ`g}ho4h_#xJ@!MU<*KHr85)?NmT|!?6>y*S=7F5l-CYCmhBUK_@K~48w5#Ey zt{x-5Kvm~fBSR){sSS+Y;U1ThLbCRh#cAnT@qMaVB%vIw3vsTZqF&ovFI+SkRdE}ExuqI#@28%jqmn}{dv zb$Km+rED@e^uP6@welp=u(}jDr&8uyRif#oW0q>)elOzn(}A5NA&OckwcE}8@d=## zJXW^7OGLKs-9Gm#-GUCvYkURliB_S^{`sTh`@VYH`+dH-o9qwxJ56*n4tcE{QF{Aa z>O@FkBIma^3m&UvPezi!ypz*~JP{;VXz=v8c|LxDpX5-__7jhlST}FEErv-V4Lw(l zU?#)vL%ND-QN!m>L{law@4C1W=VwC6&iWgC&rJC{h4+)$F;M20mE+6B^S!~I4*dnT z%PZb%RD`GsGPfUHuremW4P1)PUl+okMQ%2YTqBmy^@lrSU)6~x=O+bG? z+X;@|yk#hgVPU`rHktt}E$}5zKe^-F2`58lMw%VlCSgt=q-6fV(JKk$z1|WxnI^O4 zon8Bi6;%sdA_>*+#vJSl=|zA_*9^3|B^|?+I7`#jYODTP6wAkoZ$mTQQ2kY@9;_yY zn%E#oT($EV+~=hsm06>m`Rv2Y-MMDWCKjlI2iRG>kqK(~>}B0X#MQpgXsUvtvduhe ze8Xz-Bb6>pyG7p>Xe~B$Up+~m<**K|!@~5c#)HkNO^`H+=AF#J() zatLR#-YbHA9A<1-JtiK=fVFqnIvZ0gY^FeZE~m!I&(eS#RjX~MPa&9EX!K|J&w1KK z%EPUtYw1@fVeQ0kZfQLhVUro?ylpxIkTWkh6_|}oMgYCdeku)_zpqHA+)s;Z35RtL zpT+$#qn*w@65l=td_qfGLSRHW+Rj>pI^9)LBfsCq{u{UALc2Ym;i*~@N5)Oyaaz+zD78HmhJkW4!t(?3AQ08-OTB_m8l zyIuRR(r3V9epTA|bT4<#4a@c$N%1b(E^-f3-Z2KH)0Pagm0RkmC!gz8QiqerXA(S* ztfN>;R#-OD59UB?wv+$!#S=4+d&FkNg_@s<%4krx>(s= z|E0ggtu(Rg)lE04M849cWFhxlwY$wO<4@23{BkfSs9rdP;>xah;q<9j*^;MF&zBJ} zm#dkr%u-ki7-rCa&bPp(d1mhY0CsO0Dc5Z$F;hUYvsmqkt(4oc{?^(B*}(q+%FJcd zOYU&;OOW@}_|~6{BCYZrekZpyg62!!xTU2&JhY^CjJn3&=;EA+Vj#TKZHu5*TYVH^ za|I)0;Lq8Jg(8s6o0aZLa}+ab#`beA5X;)6QC#n>yY@ZSyWt+Htw8OWTO`6LJLIP< zZeUrkHV~-bA)pECHMX)y0a=ajsMb83O!in?jL}s%-}i`(tuFGgtGS%Q6&X6aX`aXM zfwGh#niyUQGG~7H@zFhcsr!SEWY*d$!n(tOT6xuq=+)Hbb?rC!%7WM}hv|WAMJM-c zrRTF4MIO$s%V;-WpY~{_1!F=~#3Q%l?)^T|r1jFGLfHinPCF;|SS@?y5M^!tEgnBc zDvE$2iu0Uao(dHtk}rhrugex~8zp$sx9jYW$J7BkLkHh4><|Hm}uqQ*;m$XDmNXN81Z0-Jb|yEGJIm&R6UKS<0O4b$RRAHzERh zwdC$_+XrBjbtgOBS&T2#$IDx$zaN>(!%UeHyu z63Ua#OY-W5gpI;BL~iyu=2+=F&XPd_HSVA_*$%6anG=3opSRY~;5zm#%Q1;j z)pW^h8budnQL-VQm1=Ny!m~=2vCq>wgziCC5;f7h#51ySuFAEa%sJyN6^gtZw|TKrEm%F%;BUc_KK10(M2vm+kH@NybCw%t?Yu zJ%!rI+dufO0qAy}0Fa;Y`cd;VWYww(7I7XQ$4T8J99Ei)EI>EIoNR(j@Z??&`CBot zN$d=-a8BH+nkj4S2P)%^;6PRXKbU)*+ha5o}jH zVZ8(yB)zGb$F=uXx5)m`1g7ZA2&wsO&!)6!;*-8ode-nV(51bBBCWwVQKC z*4yu#;9|FyT|D}Ucwp9|mib8;uU`UvrqtrX+UVmA@NMo~dz!dd&%IoEm!7JOLpxRZofK zHM1Ufoh{sm^|d@+CIAp}YwnKXE{Eg$kPPe#W~ZG7$Z?JAlmi&+uo9t>ucBVCLewZi zf0VdUIGo@`hO==+6}*<~SsLB=uI#)LHo}(-u552PTfkkdHG-`I;gF(3sS3td2QCMp{?g0GgUgP(5LJeq|ldi@wq>swOU6 zQ6gj|ieOKlvV4|hxV9C`qBWNUJ%1CCD<*1^8JLz)5lg)KnWH2E+ND!~;wfD9fA%Sn ziY1f#8dlM)?0|b%m}bR5^wwEuSZwUH@WFoY=_O{FQZspj^DKNLoKP%MlF_bdqDHDy zmc+y6s6=x7dg;q@LhZdHPUqKc#{-sj3>eaqp;$^tY+`r~wyFWfNN!eEO;S+rDf*1CBva!5aK6*$CGO{ZO?-14w8NOKS4-797Y_*RR>a4} zcj~y5sJ--rN6|#KKA7O4OyG0zpWUHJt)ie1Av}SxNDa-@wlM% z@81helS#&?d~l!GSyk?P?Agb;h+KwrkH4hqY4Lj=+kNF-t9s&0UOU;WcRdO{RLuS< zj&@eX95T6b>#eEi(O^9&UQ>NyjUvO%JK?XvU4xz2Y3Kur-rFx_KS6!bK5b^~>%Tt# z1HH-(&7$8mmo-=Cg67t`&FkH3!(NfzXyE%?|2(|5wtn6^~w^BWSCE$%PB^%X4xwnrE5H zu7Z6|x8I@4pa6JHCzDcQGo>pheB{cF5TmX%#_ED#wAIX?fh-^0%g&xh_sX`IW%*5{ z#O8IPPmumh=+sk)V$iXzooohkAP?>4Djy0NMQC#++w~258;uqHnEMV!IhS-V#Wzrk z?y6V56T4JSE_&@-=4Glv+irPwi{ZG3-gh`{hq{!H?qK;v)fk!rEWs3e>)!{ zjc;cChYTdbKw<%%P@2)I<8;!3~p~H87UtxYs#d7(e(gN8x&WaJYyG|SzKZO7v z65HJmr={mW)+>r5Q^H`Bch^=5CjvkPLu^<CT7W&>b-v)@$YuoXiD`5~f z!5^&C+2wRPf&)Z2<#uy^`GNXVbN#1%1Ka=3XEQPXml=oYU(Xc|J5tYV?I}M&s7S*r zK(HW*22*?{@D`evI)>GWJ}uigp&$RS*xm9Lb78`YE?{+rY0|K#Z&d|eySL8a{hj@f z_v@KN<}hU3?$Z6I37{vz8NWDIQyT|>0V~Zc{UpC_v2tpSS4VWR=Hk(5XQ>>|w)ri~ zZ{s?6$FBPU%v?BFhw`_woHOsx&1mK;O^r;`{`;<=7*rEDf(^r{AK#B-e24~RV2s|u zsQ1gO_v@FuhMHy`Y?KJOz`*_65duDjfPs#BG7{j_{b=v+bxe*~W!vgqI`X~V zP!XHXkJcd_En&XO<*^)AK>a(9lK<=FA}yEy2O5O-mAQsM2O}WkyNQwmDqgmj zrzjhO4kNR@6fza2os%P6V+2LQN@fX*)7t*9-KCO>GR}G79wEUHif1VI;WhR#DNh4` zjZ%St(I%vkvMaBQrLx)Q=TkA&r&t8Pb5{Bo%o#x-*|zFW0*Cu}z9`w&KoL{6nN!&o zF6*|VdJ4mVeW#Sc2)7;RKjCEc*CuBgG6lQ8Rk?I3@R*R0R5O)f8NbhcJ_L)E6{)yo zrjR7_uTZ^T7UP3-5= zoPSBD6OZ^D_wQp9RC#D%L~mEW7Q?2@N}_1wwrH=2n92KaHvT--q1Hn=q+AC2~RyMt@BF@F}#*>z6bKjya`n)9}})c-#6-oa=55E;x%A4>fC zmg;E)wNTY=`=_$zzfDLSlu0DG%EDfqOD8Qy9aqS^ZF9Kj8+czLCi|?KF3Yw~mI$s9 zZkC12e4aDqA9W9j_0ARpW8|*~Oo@}Vw2$S#<=*K*&*Vo3{}AUJfqW9EfP7|?_dWw^ z!JTDZC)-jEa_PTGmnO}xEKzyXPP9lnn&Cb-%#34VQA(R5{+LeJFc@MJO)SBoGys#B zzUWJ?rAx^2?C@$lBVEP%lTi^}m&RSHS>LRd_)(l8Z@NkT$b$)vdfG)Qu(Jq|CBTy} z^yv80BVn3>n2cruz{C6@b(T_JA+K?YLCV7v$8ygzI?<|zqZU6URAv{Lh-VM*hEL7N zDR-VJ9p@!EizNzL4U=sEFIf>nfB1VD09!^Bvad}oQ;5226`BxO+D|puRow}bdYe76 zpeq+r*{Om4jrQ1mzPo60)gN|Mx0+1MJ>k`iw42`P6)||Jv&2Xd?Y4Mck^&zBzj4-p z6M0Lh=gq;+yZAJgmq6soQ9Q{>k?WX0iYYjNx0Ah!%SkO47#>QH9Hs%G_%9|YAET7& zH|vB6os=*!20Ei=nxmqaMY(ocMaJD}GD8dT4OKOwRDTu!Qj<&(*FYLK@g@bSkXZ&} zJ6WQlNI@0Pwa8X3Rky=xdE~t2f?*e;&{hD2e8jlC9pcx3gLEsqRI=!ObiM!)bgij| zuWE*?y&J>{5;Yk%zYhwQG>*43U9G|Zv`k~`Xhr2NHneG4CN!REIbHr5yl zvp4eQI+DEZHIcQHQi7w_ngln}NK?$LQ^B0Bn8N7;b?B6X$V^hhk-lkU>!#BHYo?ar z{2coMyc6}Z zJB$uhq>&$nm{+y&G`S<-mHHVv_J4#HLGI`f(O!bXu8IrA} z?Ux)*gw2wk*05jIULJT2xgqQ#`c;dTRRSunfz|9=;-YaxSsS z?~Bj5jTEaP8*7@)d)rj4QQ@YH%igTFvom2TFcq##yfLiguBrsVzyI<&z#OZtv0c?Z z`KWeqIfYW++D+BfoT_ABh*(I3q$sb%O zYOpm9ERNqwR|}RTqbvHAey0}*$xFRxy8WAkuRYHdyj3=7u8G})aPF?x z(er${%Z0bnt7LR*2$9#VUBXMvlze}9`Um9&lZ!SemFB`<^K@q!XXD8@NASRVuUcJ5 z{HD>%`9_u2(e&9v5f|gq5V#!6y~T5@*cOU*ZhL8)J?_@;zK1iTd>m`ZJFdHiTFRod zhU(xObtqf99|^!;VW6plGELLX`0v@v!Fg(~(BkFsnWnS7w`{hEb@dBy7_yOG%lQ<*K7L9h|QSqW<94G<(rb#P3Hvyad# zlq@a;>6aCUiy(*nLnMA;3MX}Vb_I!m zXk)e2BOU}?K*h1gs@ssAh)R11AFUA%r-HM$wZ){>&-W1dm`p`s5onIQAI{ z#SFs^yz&j{zqHF%)r56Wq3cOldJM5!F%9MT=c#JT0-3y(*QNY^z&bO~oc~FC{U;1M z11INy_13ec$sKpd26O#Ce)lS(yL@naj9pttWCESQt3YMJL@JT{pD6j%&jRb&f84Er zitfDBlPDsJhhhsYAB~M$@br4yx;>qQF8#u;fE}&;T;%XopDwCkyl(xR2lFm=elES< z4QO53dWS?-h(}QO+!NXKwWkGB_B5+1bZ#E7hsGe;+Va=-Nf&?p^mHE@KW*ixdvgm0 zr3F{)(^XtEmQ_y1Tp)e4h=E}<9`r!u4N zg$ZrzjX85J;<-w(d>STz=uLVqKJZBD-FF3u{;1}hjB@tW1U&^#IrylJSa{OM=|(BT z*hkN42sw%vUw$KUHW%{SNx>Pi^pBYCsJ|TzXw3qfN38t#WII)Ra~C(dL==(-fq0sn zROE16TmJ37GiVr}P@8S6{@elku4qb}r8(MwKku#mb$j)ml5*5Xpmh9FGsoe_>Z{VZ zBt@;8K2Bb)+DFCI|QAqx^0fnCQ;N$x+B11`r$yqmCFkgy)0q%J*bM?u1Z+nDw!hn)P-B88db@ zN$qgT!ULf-N%dOcQ$UFcjhCcia*T9dJIkm%hhM_e9m0*L!Sg_a=104nW8TX(>mqQpnkan zzCG|vCLI81{A%_$v4$=x-2j2EC`pf|aIBwzYfIk*!I#gwt(-d%hRey?MeZkL> zpf^G495-p?oB9@TguK|XOVU~OLM*ciEyre1G5FhdEz?jMG+$T-)-0^Yv?Xo`eKy#7k>H9f9qtWWuc zZkg60iyDo4WbD4F*+b*5ieE@=mdkxyg5UeeHx}GSp^r3}QXWiocH){-G8krAP+$Jfk(%=8yLBvegYiAe9N%%)vV0sXGXBEGO9n?N*oVWjroIC~Ae z%)&HRhiC2;RuWCdx2g1mx`XypZH0?$!4Z>qMjH z0K?s!ABI3yn~+@AxI1wu+S5nd$%%7^01alw7vRAPiU*GH_{2AePttXh%8ySxlo7PC z4CN=#!3Zn7K^du~$qgaK=u$`aL%`{$7-Q*wyKT;x!kNJxN|fhNz(K9;&EbFai2K{C zdC>uD=6zs{FBQ-&5eR$zkTILvWorXZ3$;8f&Y9sL!%v_a?M)0Tp5m51la|DYzA|wN ztI}lckF|Yu2ZgQ4NkoY^m&(Dm)@JwkG!K9=EY+A@QKk%FRR2CneYcw#k#s-patMf^ zWtIw2hh7a3=&)^7^NMjiflAy!n*xaXtm{6rj1V?C);1x3S9KCP_&TF1ycyn)G8Dje zi344UkyW3+rVQ4d@J^1coyQc^=9@?HzG7(=v z^#zbTf`~`Dg#$VzsQ>sy?ciaq@??Q~=BnanTZ3BK4tCeKxdKLlenM@avK|~UQpC*P z&7!d_8It}5C4i$I-gvF5?tG{JY3I9C!>dnwqbo)Qy^AF$wEdd?Abx#EhuLAQJ!H2= zIw@kDym`9eJWc>Q2-hQ6Dy`77NUPKc?>a?r%*~f?R6?BeR1`4xAS zZlU|aZEE?PO6H`SO-3Gd!rETsESEI7Haoa?!UdJy7$b@mE7?)J&fD=`yS<*+M1D|8 z#r^h>sH@mPZqZz0EB)?ap0O-rj!BqHWz+8u$ZD3UGrlmW+_*DeJ)ivC$!hsr-eSD7 zvlQtrrq=Mx*$l8VpHd}}Q)2%6O9QzTG*H7UO>136ThEy96E=yj$k8p_pY5Zz;3p=pZkiCCuyCyr`tJIQtbs}7E z`D%Ft5cgDxGF_}>aizbKyQ2_4;fB3oiV)HY4h7prU09~kkhH)60}vIiSh=- zqRIC!rn5t_BIeN2E-5AK>G*m-IGJeA5~qXpO5YE?+n>bgZR4Kwr0XV!eM|T@ zR36!@4hVf{qm=lG9rY4a@)P>+2DsUO5+Ix`|H}@~$ie>KRqYLHPRAaw!Su{39fFEd zM;7_|i}+_>8V77^PF0_lpI%$QZ@us*H;{}bT9Z5QEC!KdYUPi`{WLx9jSAxT@OF3c z`fw5BX5GWg;B5Ec3*ec*L2KG-@^Ju|Ai~-4!~6NJtgE-{9uid}9y#7`O_Jm1B6d{) zq+XDqe^ZUm@)`rP^_1YQDS@W=Uee?1p5H)?`n_m0Fp z_pY{<`sIqQz*4pB=@U{2xxap#D0vI?O>nhWryy(ieL1~;KYB^IKt-dUrL?5B1C6K; zU&60|h1@9si59KU{7D4(Lxhrz{1AC)c95&b4>z67-=p(tTG&*Y+Axm_b6}Ye1l&?t ze;{NVKJaLfw;<84n;))QT<~SH=NT(V47-ZP7&onOQd>@ zA41VEl*Y11>0LH!E{Z}l$)qiB0&)JMo=KE?SJpF6LpO%-&4+v~k!+mu54+`psVwm* z*@kfPsZ|SfX0FKipAPgZluVSTDP8)rhNHsWiE@){F{%j_W^d27=wLMc-1sH#1MAA;V(~v?i zYv(6zj4!Ia*YjldU7jOuvz*NJv=3pXduH<4r1qRh@cL>U-z?6sE^`ip93wN6QCKc%_6s?nZ zX5SlA|AhHV#D3G=jKPqT!aj!vOwh$}r3WisSexY#XA)D-Xj6)H8tBM&$%))h#M7SY z7}@q~CshCyg zCSF8z<8Jn48uPb}?Akq=KA2JlnRCO4nHP&(>lxQMNLN$(jDqdV)C14m#?@E>a~ii` zI+|9>DvB&>CR7dDcPX#ey{}5QlY>BkqRn$@kKT?|X{OTv#9?D|E;-}iRxjeWL@8&4 zJmVZ8%x6PF^+9wDaa8)!Xx;YZ>tz2UATZp$tb_|1mG_kAw?(7g2A7sY6|DWrT;VTO zNmv~25Fy?kcNSL}q#mcUJbll@6rgwsF*tV?r#XcVr_)^3_TH4B(A`8vkn2wzuhZOp zhwpLTFZ5gjKC)liw10zDL#d-=+;nGJDT@<+-Sr<~ZlYZajw%{MPrNLf~EXH!z%Sms%nfm+dhwPwMrO z$6#};Z%_;3!CG@HwPc||pT;!<7wkTbD*o31{*ZRUC-9;h0}=zwm)_#b8@`dRzB(~xBF)_MCw z*?c^C-*~{Ct=HtpBZR2Ot9SlssBjmq>MhtY7*or~ldCt-TF15kb=W*CKc?4 zj((6=VWWTpbs{Yl0-LFtpyixph{r_aJ-z~o)=qXM%IIuTUW7>51z7^uN>xp$)e*utu8qf_9J(-T%ogneu2ftSC#<0Xgfs|U{<;z+O-<=zY$&TC zW2`Zxt}Y2&!u?L&PNyKMeWVyWcPkdKzWF|Ii#cKuWeb1$Nm`O}Cr(^I2|^0iu2JbG zpm?BF(XJHs&{ZAmc0yvnf3yxwi5JqNSC;6~$hQ&G1 zc6YM?(kU%T`}%?LW0~>sW)hsw99N9)`*2rG&519kY*4_)fjBghWyA93Jr&fb4QK=6 z&Ir2?h=SK(@LT*R^hKYgMo)JM4~txRs>W|K=+-Kb5|Pk)>zG#hhV8$x$XWJxH%T$u zvOuJRC7VlB8HKGxCL9{81(Q>z$90w(}*OfLFbD^;3CYr2%?LRhZo6SxcM`-insQeQl8c-v5;< zL1eZg!F>5=SHLyBZPCZ-)wL-NIPzBl5zO$5LJV@uj1kMxn;WbjRumXPcaKff>IPn) z?GcbRqu;g@MWcx$Ky{L+22IZ71u!(II;s?4zwl1yNXbYc@Ti;vOs9o+g)5)K5?glE zwMPdPM7+cl2l+|RQ|W=48_!JxU{zihlv8SHQxPu1l3cWP^5WgW752QO@kHAYZn~X$ z#wUE{D@!qC^taCMP-$4|M>y4{5!11VTjWQHEohSvAeY)FP1ZV_(bzpMJAjYyX%jYl zI)Ja&6v=_BXhg`8D|+X^{r2+e{%>gmXx+R-%9lRi0-7AutQT^=YmNiXmso_n6VXt` z`?g6CDX?%Sk9m*}r;?K{A#-Zi!^kvkb8JOnt#P)0+-HyV9e|^`mIQ|d!k%JD)O|aS zUdM0s?_uIf>6F&?#0!yIN;BSNF9Q>@cGIR^-{pf@&>!HL%?!f)m-ASDXiNmR&wQ96 za$>!xxK0`TlYbGpOzyt8%gWL)HW|tsL!}80m>Q=%P1^4YK81|f@tsJSGY~aUSb?Jr zcm6+&9;cGLu6jFeDYWeb73&EvDcu#J1^+0AiDife%TwSNL-#e4#?I}*W?$uGn~D!E z-`3fhX6AV)(Cs0no9-PVI*qTK&N}SKY-=P&b3ydZ6Exq}1pQ~(t+wjMrM}4p*hp=B z>9?K^d+LQw9Qn&-JM08Yv?Io{NC*|6QSBC=JS1&vZgIni8T?%*;(SQRK3uaZAm^l( zl~Z_RQ-sL#Mj|cGOj7aQ5zoiqehDaearD|#j-4FlDBF9&zDY+v1aL4HBy$a+rZP1; zIBnj?S!{dq3r+m8IzXjN-1)wfe14qLIv%7b9VX}P-NkWE4vA8Vy%R?s*f@!ySpeK| z8NM_R2Y!HGcRqzj1L}5;R5zZ%1(d{iCp9uO*4Nh$J9}^>ZO7^Mr50+g9H6@VBac4aeCzS5+F zdtv*rpTuzL1nQT}|NU?K8xbO+%`9140UNw9Bh{6)3sSh7A{tDh2s3DOMF?{OvgKp| z19Y=~I_@f)B017JDk5=n1YbIThBO+lZs_M0!ZQFeX_WxUVVN1L(CWvn=98PVv7jrp~O;#x}Or zw|LWbN9=lP!i|RhwxLuK_h6!h88S6VfilDK8uKQz#a+qi<8CC;vF#y74qWfhBrMH^ za#FGeATx*PP%o6y&HXR|3e`DL4l=`+xkHxbraz`u7Jx$GDwR5wk)Ngya+Q^vswH4j zF5FrP7v-dkOvR}!sjqrAe9W@Szg#HMvP4U{@xaFARC2@j^&BC2dlY#zHenwS+w!2| zQF{gvonYe&V+((*I(^~@h9&(<^l5<*S63|q@E6mv%Spf(;FkXFnbsZGn{T%jw^_2J zvo0?$2ZmO?T3Isw&g;&z%d*_7^=5fK0@wH^N~oEfg%)yq;C&OpREbV{$z3#%~IqDg1JYw@6&pnNLTNh_% z<8NU<1BE`Fa5>j7HGDfFSP{hvFSUL@qp)lKR3f0Vbh2_U*L75NKs7@UdbL^|*B@tR z&d<-*KXq>P#TGA~etb7($fJX^y*@cVw`jJHw&DlZ!_G{jyt;WK2&1k^=&D2hF9uZ< zR~*p_(*XF`{66d5IWq7&&ktMIPY>u@o!<}MH=3_{H@!D|Q^wnJ$0sXMp_to`CyP;Q z27Y|bY}}89A?KZECoQ4?;(drWd+(SvO(UKjos4ipQ5*mOc92V~K_Yn=9x*x1UjjOy zhc$V;Eb@#rpph<50~+DD{o!^z``B@>Y&?eo2z1~~a0|zC zVQk?Gbo#K6l?VP7y4Wt_d=&I5T>ziRDatU<=_CqUK<5-*U?=)Dco9Hwd!W06^`0wj zFul^h=@|?Fd`0+yp)qsl z5okzGs=ukoKvDq{!06158K5+T*4Lm8kMpk(OoTzif@toechZtC>y`B4E(A27+iJBiF*6P4-({#w~Th!nwx#WNHQvS!lW z%a|UQ(LAoAm>+r3KJp`c96W=jI`Dr%OhAnVWspHo*0Cla72#NGv+M-Zl?fcBD1n;Q z6%IN=I*{(|0bua2;M-vs<9hXfi`@I04u!4FYnPLCY6SeJF6ys9%v*gR1oxwWjbDpI zdm7Wk;mtPi>1E}f<78vwVl4IQ&!41l?ePUtr2z#QfM&fdGa<{6BK2g0|KL!*D{tj&&nr6^$alB)DA5NiFyP-!5A z1s|YN_2C|$ibjP5SxZUfryX$Rr#(R{ES8{u4`oacqTOP6tA#Sr@9_}cm2Ta=`Z_X} zp=8oN6BODVwdc50TTuUnaPP-ocdJFT*nbsppY&4=FJum0x$i{OX z9reb6kBgP85G#MwC-isW+W$&Ue_rgr6ZFH0LvlN59K6O~96uW`+R4?4VVKX=O(Cxp zZ;{Uhf`h$=y7m`q-Qph5`-u57ZIPjD#;QZQ>kZ|IFPz>gkk^+UIR6hQ8N#2vO6<2p zo1wg-^-d#C7ZihBbbti*@9MxZBch@F(yj^-M()gA0$Jdj({>_&c`%E(3$zD<(Ve`- zoT9p0Gp-XnAHFpd7!AGExN`px~kU2DHIKsZp2Xr@og515wfOe-861V{vh zJ34ff_Xt2?MW%h#y2LXuyI*ES_VH1*(#G`>w#^%zR3XbsxN4np{3!vox*{B2++&E! z>bqp+5~-s61Xq#30V?HKVI-B27kyzLRg@C31I7PyJfOK_Ls{&(gsugqIqLB7i3f`M zS39DEU>wjC>9X<@q5{QiK?FwlFGIEh%<_&@Cr~ z2?h}I9sPS{0U#yPM92f0iuCPJ^7}2z65R`LrC@TZcC;>9 z{eNsKyZ=SmA{bW*u%M#b?g3H&INJ~+Jw_@6@$8sGTDxgjb3Zvk3fy?3`d*R>a2i1- zx6B6u3bF=V=!>xh3ByMDov!Aqo$2LKBZ#T#qm~Pr`IPQXYAB%#d}h z!ggGb%BcAVn*laDOE{J;XZD3W;$n)wb4ou)qS$L1~S?z;{wQkYRs{--2OT+YjgC3d_wb`CGdRD#H} z!ZFZP|Kb4ga`$4RZwr6!jHrNIFQBt>WUv>XV5hBp_N}G%FhX_QeZlSz{OK3W;eU{} zER6pL===Xg|1dGI{&y{(-J0XEn`{W(FKUnQFfwSBZ2&=FJXaRL?ZfF>@k$6MheDq} zVJPeoMHJ=iCv%Iml2u3bt}#5{PRXOSVXbk4rBNe=sIkc*2cs{A``C#;RO3;hv8t2? zOa{g%##3-(c~UxClC={`Bbc1qLi z=`UlNe!)MEBWSPQyJ=tWaJS~0zD(Dk$Ct*n(84TKvA>_PlO|&JBiyxi!O7S$~|fvuaDmQ zDDqMqB9yP#^rZmE$JKiY;yDY2@q6I82F{TC_B0R@S)R0iZivT&JvAeHnakT?7tTtO zvTsIRdRE8`8%(*^J@<+(>fXE=`$er=3JMHB7fBM8kSMj(ilqt4YiJO?#} z7}d0*ShFxpsYljbl^>5wM&*<Gt|lkxS%mzEtCaRxIW&m|34~Q-=j7o?vP@!}IgTccj+)&lvq{+_78Kvpt#g!Ewj6S)+2jf(h5cYhoL zZB8j!XOdLIsy6RznKmi9w`h=qxj?5?m;kwD!$uwo+#t6YBlU2*IW4CB6eW~umv+$) zRA5QdrVw-+&WN6u z%EOUmtQ8%73@Xo41Lj#(Nb<=pO8|mlYv79kthqE5{iUiHEl))L8`CQafL9u+YHo(D zG0TaOy4gk(f3siIZVS9>KhQzrodq17f`b6-qCFYZrnY*)QzL7qJ zn;m0XnAoWGHJdF%g1ExBx@;zbC;DVW!U^7dMJK}eXX!%2jq+PKAHNvqk5pguzA^3f zl`=s4T~SZsgDwVxoSibut<22NFxqusiwqjm+S3rE2JNJ}BQO~`e=IAua>~k-1Df)AH(dEsRn4T`CedX$3p5aBGo;qU4K*?hQ!{#xxFw!*Lib9uU*2maAs zo;-$n!XGF9+@&1p01K+mAvLpcc&5N($sw~9{QBHN&>+jAg^Jh8My@zHr~X&P+cVD+ zBzsIhqE9o?N96#8DavIP|2hBu46A7;>5mR zakU-3^Y+e>;FtlLq}(d`+>u!vPEKx($>6XTU0qXPFNPPcprkFti{xBf$QY-PkBmGf zPpW(2`5570llMleaeS@Es(zxtimknJwRXJvE+i8RH`JwyMFSL@yz|5)O*#ohl}r>| zRfyQF(^J76bS)h`v>4T@`fKE<`7Q=EJ})BtA_5|nEgowvN!HukanDKj(Wv8spxI#~ z&{jlpg1Rhr!~A&=+TSj6v`?~m(6K8 zMd#(eoYgY}{szI|zl7VUxK}lZveEM&PnQ5*ePlBUr*9t!JI#`z+`Qt9lo(|uep&jP z0;?gRBfVx18MZ5{r%y3iTlc0}Zkv_A%33O^jt(b2@T$o?pqQ{H6cyC0y0Q|Amhz-A z8FDKlu&d>vE!cqXGV~iafrs*2-%DXZDxu_gEs8gCca9B~2g|7l*nfn2(mi3w6(G$m z)^^{D3>Gog#wLOp3>vXokU)x-$~voHHYq*&%lifl$pS3pMB$vFy)H`-Td<0RvRVA& zvX~>XxZT#KP&&$&*ztr=O%r*-zJhH11oMUlT%e$M{Zl&Ws+@7D1pLD6TWn32qfsi$ zjQ(zp_6@y(m^IjYgjRLZ;iI|NjP0nfcGW>?0BHXJQ&Z^RbG`d4tVrK~XxGbNCcaab{)=TaKQ7X$nhSr2u@fF@;41bG_NEQMjg~ zafZwUzL69fE0n_diL(5qk}(L+9JVusLmT%rwWr1$<|lf*I|AquH>BH1s1WQIcDDO# zaqDf_AXp`bBZej*?fN74HUYwP$))bj`oq44Ixd0;Nwj>kDMbes3@bZ#_c1&kvH^@Q zxe|LJ>j+3*#q?D}eS*7}i%|Jv)A_`|bdBkieDe}F=*N&YIrg6f1=D{J6s+w39ZPUn zYuuKE6R!J%dLLYpRAC7W1CpaL3wFu|s|WU&RBy6ZmlIrOHUsZa zThbHe%l534%O`1I0sYUsQ@&VM4<-r=5hyQ$-#|)E)X&%Bbnk-`FfIR%1|ct~rVxV7 zp6t)}>nOC`)NyWzPtfZ9TSuS zzOThj$g-^kVw(}%QyWxyICY|SLeWJ0A=>9UOZ3XmQM13guhW^8CiWoAy95u#tQg{Ux37Mg^CN%*g8vu(EdM?D`i;p z%6~yCkDoGp6#)*=A^7|oq@B9N&E`+9bhnu95I_@ZyOnS0Ze5cBt5TTAW>OygKT&=#AF>>8giB8bqrV5OV|w5=VWx6C(pSlbEp zQ+kv+sFWu*^#`=J78PY6Z&cP3H(a|NkoFJ?Su=@sZkls5w&KpubA-xPxA|tel;DK? zg+z%vF0*xACt{R)drfyrm@VWBD??HF<2{09QY2+Ld$Wh~IVa~4XA!&Y{_|1d;r@_C zBA%MhQUK0afJiAHC|(}!iwwS?^XV(?Hf=8HRw3aQ!IZk}tRe$98!=E+RAx$k>$G6aF~fhDa+EH&e5?#qDiUJH%Om}L*0Z@zbwu= zTsdw*2?|}QmPBErLO2`G(NPkNNgQQEyBPD^enL@)dl3O%dN>3m_+7eF=CAW3TFV}^e9a|QkF(4mGGOnmy)?0zR(eacYUC;Su!scJkI{q=h@_^ zG8=cM{5R%0>zt3_s{gl;fNO2^V_)zik71140aHwzG@54foL#QI_t8->UAaUP4f#)7ar zyhV`kW3ABDgqOtxRCz39Q+-kLcr%545cTC*6NH_8dRrv|(hM{luz@+7`V;eKJw6;S z&VxiHu^S84Kzjschsqr9T?_-M8ZorjUJL<*x3RrT_VO^h-V1u?k@{-CgA@bf&w+rH2A4gPI6fiACICh{aEst<5I%0aK*IOYlu zK8eyg?F7`ZwIFrFlCcakhz-34*7&l*zf04x*()&i@kxh`$w}MljAPLU+9OJlHJKzx zyh)|6%Wecp6oiF@gDRv=xBciAX)MN>nfpq71#(XQdnqNYw7qhj8b zkhOF8P*2Sqgk|ITpbtIB@!)jlbufR!{;TO)3YScc8rkQYi^0jyiADN!GWbkPeJ7Mc%imxrLjTYwbhTCjTS0hN)UX9J7f;dX2>gzfSKz$8 z`KIuxrat!wCmiko4pHy}v=RB2E@$1AhRKk+hj0Wt=BYHKmh zxC4z$jS|J}iBobiANv#Jj(>a~qqw(X2K(WNO2!?uVNtG#{zI-Sa27X^@vFCumm1k3 z8P8Uqx0B|+$&)j{mRC;fh_q1@xaz>QpeY7vdPO2wn!~ z!xHQDA&f#IR6!q{>H%+FVD6xie7EHVt~tx!>|-7nhN`RH18B^~@c9p8638dznk zIsN?#ZGZmBmwn-=6IK=Hmhg)8=rvdCN*P_yO$i7}h%-Ar96AGi2XdV|pmOSgY)VlA zq*|;C0vBVu9YkJVuSS6-&fv~T!IlP|XN}k3$u1=|AwbR2641;MNc7b@#2)90C+=m< zjl<2hn=U&u60NBAv?x`o)cM*F8Ot`!&792|xi}3WCfeg*b~&F!!!((o4Ur7Gj)51J z8)llO6sE`yK+*_nFsX<89U-WbqIkB!EpC1NSr&k41Y?BS`iCh0#*ZNUyZ$XILsv08 z;KGAWiQl~NYxK(-*+6Qo8HmG;Y}V8zxJo*%_`Zwk>LD(J#DYh0t)fC9*Q-0Ia%^r3 z5FAb`RJI2gODNqPnsZ&du-pHbSz)+1iE%)drRYZx!{vb>55XP|?=dyn>aR1%9YAfUaw&srBctG{` zl@*Ae17m=s7i9u^UKrYn$cebgd7bwB?*^j`~{0yMpHiqQ=tuC(7T@0|$wk7Jm?F7z>LJ6LbLbk~%x>KgVyEMmD);lv{pA+gp5)gs z8^Kre1QC-cNa^Qf6NYyaUxBQhN@42I99?){g0PX0h4S5t2=51^2>nB>5swJwh&n8bDvpr-X%cOi!pfB4 zxQR%G+)pC&1(qCU; zTuQ~McBEe2ei3rw=z3Z^MEG{h)b&(La}+`jNAiC$_Kq>4L|yl1+qQ1owr$(CZQHhO z+qP}@ZQr)7={Ga~WHRqF$@8U>s!uy7sXDv%S--UaZI*K%(XI&SG*pY#xW#m+Wyem) zGsqz;s3Y%teo{)k)>w1eFHMrAotSiKy^`+3qY`v-UT_g%C3~yvp5@|loGNYL6cYq52O8eg;-<9)$V}|BY#C z28!2|j{Y&>KX2M}8@t7zJ|%~Y7>9r7{01LDgsKaE#b*~JXh^>X7Yo|GVq8v~3q)kh z4Au%t$UNr6r~t$cKulz!*oKZyZi(p^pJ~L6P9ET>kPmde7$|RjfTOPjr}jtWjK{!( z7o}A-@qYMmkt`zhTP^0p#-D&&w6&rAN=y`Q0wlXd~zTih`cE9k#^tFpWWjm|I;UyneBhk4~z`-%>R|V zaz=B?7Ml%a=Yr}4eERka0H!Dv8S@`)fSU-q$b4~ByZNGsU*G9H3vo$;@r2QEzdBar z%fJxV3$AX2oE{l3k8P`5mK#?I*;qHCtgM_KX#hO?H*~Ck6)71=lccoV+>%{ewp5f= zl$28~3T@bL?DWaCC}bSw;9t*vl55*+Gz*(U62sBZ3C9VPwx!ckSfBh5gVm4;juZEE-%k#o z4R4$lG_4^kkV#HHw`2Eo`FW|qAL)>HO z&UkxW#Bz-9-?8?QcuAGiXe&|7DP-A|LReF7rj4SEG~N#6miQ$v8}%}a%(l2li_$_O zUoVFj%+cPS*);&7RKw;X-DOo(X1Aro@4Civ+ z;*oHdX@Dq!m^4)*u15TyBUgc%+ZuWEfw{#1Xe?5^O#Q_o4#T>zk6aQ4P~)7BE1W5vQ6l8^j|!u`$=Wy9Bi*rxGU1+gVKa*H}=sL4T;@^^Sy{9t?gaynO3}5B)erk91uQ4 zIAKh}x9b`I;8tgs4h8i~I;(&5e^NE<%dSZpw>LTPpkFW32pn-gz@m1hcfdxf8rl|h zm8EMXnNB&Gw9@I@2KA62(BP+UY#u+l{kpw}_oS?x-9XG)yjSg8#J|s+)um=a7SxsW zId+Kl@;I;^=`ID-8ve|WJbp9Sr}C zANfeq;*jEEKfsmhR5_HL_-J$UUvIEYo%u0n{xOVI^o%Rr#*I@p%NSEIjGyEJmF2WW z%lQInC&M^kOF0Y-a`pf7>+4Df{Q)=*NueoO@3y#`}OcNMVI%30Au*G zs64M(?1%XIm~9(ls@{#X)aD&`ghw1p7zi2<&9g5}1kBPArT^!Z+lE=ZT2+yCsdu5= zaMo#QI>s1_L~#Zzv*18zSzR=$$L>o1&XN^zO?fAuYcbK}4DDVd()P^qW=dK7i^Zl_ zIx7xS#i*o+!gyp1DWFfNe6ZCXmVfRc-jTZ9zZnfZ05a9}XxtpPm|ph)DtfRRnOmWK`A zTnKQMVKgsr>|Og(zrRy(OXXlazwqR*&4-ZQoET#sup!p=vGL@`jgX~<72I_4Gz+{; z<#Hf=1*4B|HTyJHY|cVqO)*be=fAVs$+a5khv3c09u6A^YYHdzylRI<5@z& z(&*P#>7>@h_{i^R62&JfbdJbLTi4@fkeZ(2Y|3}W#b}6Z%Ci0$@xCyv0{MleLsx~o z>a-#-hd_JH5T}h@-;~y+gkUDVZE&R7Y#znIH?Hr#VmS`0S?+^U0wgCZ%RBF)eqs*< zwMT}A4E3a+i1+jmW3<3ODpSuMl9Vra6-5R34B`dzH7_ymDR=9aE7(s|B#(|oaZglo zM&1begFXdxkXXUu%v3KV;8bNFiNCL&j|68k^pob^68xs>xeT0Y?TsuPR9gNbXJZRe zc9-_$C8&ML^;-U&y0m|=$CW4~A*$3a<;co(6-(}+4V}aI*8N|ph#7d9w5t(a z%IrdOIxm^JKY`_ql93CM(*`ez^Hc-dR+=4EV$W=pzrw z%94A{qJ&pY8wEiaw9jBHE?6VxpP8%rmE4x{9-?OQf&kb|5VR~{FI8(9F>4Q5ev^=q z5e5Wm&EM|&a1>=~?FVez7^S^KsMGQoBY{wS$V}8xe}6}1*CEn;j3{Oa8Hane(4|k| z1K15BM?SajY=lvQSf!?c&X|{B^m_PbQ6P#CG5#%7$m0W(7C;;j)x!9oV*)Ow#A-<6 z0$Y+Gj`fZ_0XQhM{HVlCGjR;Hr*S=lOb{A$_Q5=!=g7fo#Q$@zeFYjTFBbM|wY9rm zsS&~4N?NNQU6V<5cJLZm{LQ!MKEL{(x)4^z|J8*suyFi$#|SeTQg&PH2)~fWKltEZ zO)VWheSEu%e~(SVmZ4mfs~nH@&yRuGE0V}m<8SOCd?U3a&g?@LrlQ=BtfyzMmuJU^ zGd;5hDz$sIZm(QF9rI7%iGUdye13Mo+40!pTF~mhSI>i}X4X);xgX%YtLt6O^wna;?3m zHzMbAZ-QFA!UYPddTY#yD#rWfPeJC(Q&@2xut<YiW^uN_U%+XWx3S!>pk6PhEj5qor8&hQV` z1=G4sm|iJvqnLO?$2*VRye6Lra|veKZrv)rMq?rfT_)WV-K7}8Cz>M?kyVprT7MO? zow&@`Vb>v31-WrG`!V`}r3{b1Z~$l83Xy@Qt~}h|?;T(E5O43ik2l7?-yF#3AgUd6 zza}W`%JTL~Z`}N1g`H@=-rHJW@Afug)&sy5u z(#)}QY08i*gGfnmFq?OXPK*yAiSeo`Q`65TwaD{lStIy2u zPr}?@41}X(Byuh8rCoLc#kTk9qDNySL9pFni%=(Ih1>xfDsltFgkd|eqHm9i zgB(izF;ze1^Q43h$|9nI?nhmipE7>5JfTLPO`}wd7h@~Tk*I{TU*w;59Otwtb;a2k z@Cw^7>0USf!KR)bdShQ`Ju(80FtdqsB#=V^O@U<)OE+Ie|i3K?RB0NDkbGw;O1y29l66ZO=we z!?j8ptm3joLcF}7m|2!i?%(o=b}ujD$VbyVpyU)yloacK*Uv9#0twDBruw`Kl3YYsUVDxigP(xd7z zkYBsvvvLzvf$GLI+$)7KEoX=70d^7-y(6KhCRnM}JruJK{IZAkkpFLSRUDLkaeJne zB-{e9npFp}LVdbf_7oW>V|F@=t?!}tU{1*;3XHTG%H(n;;oxPTV_~SO+9lWh_jBu3 zt7a7NhJ(&^8QV~finLCU>C?J1R8<&k=K*Q-Mr`KToaQzGueQ4_vzygAXZJo%!~OP? z1CQ-Z*Nnj)5BiQIDOqtOB^jeL?;H%g6S8PnuN8Mr9lBY;heD+$$5Dc9P;2ffEz|Uu zXJp11{PE_*wo4QD45p|D{f)aKB!==l&4UsAALY*uzOJjb8LesEU-Nm7%!ExJCv_%GvkN3b|-iP`Aa zs7`guVUi6Bma(nZQ53PkQ zT@2Bg^#}dx<5t4f?7&Cxh<{WP!D0VYD-QZ|c7L;fz7dzOerCT4PyoI*eD)pcaqgo=|>M0Y>M{%eTTrCPiR05k8N;v`;a%(7Pcpr54v)TeSD;jA&4ck zJRyNCaD+h#QQtZqkq&OSfglx>E*5<=CPow`98MC*4XksZC=NzW{<;6->&pj2I4#OlD+RT4U2@A+Km8n0VXc7Tv{f6A&LIk;$Z8Rk8fzeQ*H?(A+q3T{xjH~vj zDBj9E-*teH!mk9NpI(gy;5=FAoz)S-i~@HB;650IVy&P-l8H2LYb?i?Y7;c=FKl+c zL9HpAWk^TpuaCS!P*hKkshKPQd`HP)jQTXcr-Pu1Q6fr>o!CB1qH0^-jlaAisNE3X zBd_JFx7r*yJ1Fi9SpPf7c^9 z^tq6Yu){{o50~h;Ty-0O9jwo#fOA-6S4c}En9vP|OQOKa(LB?hKy}lOvJR#dcxD7; z_*}^3>^KOmB9WWHh^%wQvGk#MtnF-+iLbY&T2-Lh#STeK@|k*2;5~J` zGU>>%P=(b}`C53G_76{jJ*_)w#>5DFz+qX#xKDNPOpzy-c;@`Hg^R$$Lf;J^01ZK7}JngB5cy zVu37@%ILW~P8Cc593G_gIC(uYQG@uqvG`Qpeu8f)gfNqUu;5z)Wj#lo02t)Gt2ctV zfFE6zs>ra(_y|s(LpiyX>AG<<5vZTCNka?REI+wzxw>=Sp|NK$x;X65r@z5;=pIMd zq_O{KZ^xENgR~nLGDS-uBtPPFu9?S>#d>*p5opxZ=v+nHxzg1cKC#zB@ss)JHGY#y zwd&fP$75Vr@}PW0>Sp9)nxqH72xcNumffqh#BhX#2D+ zxj6}>gt1oJ^|4(?pG% zWbZzN&#)!AEt zO7_tViE4vC3zR1S7(|-bN`|--T~XdSjtaatF&95jFi*1N6sC6CvI?E3vGbC{ZHt6t zQ!P(>R2a@!+o3zPg)|D24G2i%bhInuKe-5%4VczhqKFq;%>g29-I+KeiCw&`kqX~5 zCsTh0l~IyflCAF$%4F0!QcJhDQ;&<(J|4)WD8j_^UQ2&JXNkc zzVl9;O%1(0?YE)FB%#LkSDrm>fqVuX_2Ivj7EAy^6d8DaF?_vANSeHIK7=S*&ZHgx z{P9~nQwTaF^MCEU1uYYc>UU$lEmr=L!g^(v=dc~>z4Z#A6 z8zg6|m2Zn`lSdKAx46PY-#YA!N7VcX_!~*9Xum8@01PP-VeS?d;fT?`LQhYQvl$TK zI+0dH#yB*SKDl~BbGw~2VUOd*gE^DuxSMZ%+P<-T+@3=%MxT*D*xxx+g9@ha&1rqR zIzb@tmqWxg`uvo7ZA+%co$LctZ;o3xF@=ck1lk+^QU*?SJ)-*#j6=auw=v!_OcSw6E>*I*O{(sq74S&4YF_S|lSmDtT<@p;9mm=6 z7hVpt{7%ysZKQ|`Af*a9)1E>g;v`Ciy6aipjmdu@70^^NVU&V9ja~@Wt9HPGXgH-k z_O+U@a&b80d5q^B#P`}x3zmVhu_&A#QMtHLXS6P^B%?IJFB|DDYvqeQw9Y|8^3y2-4Ytqo=PDVz zVdLTfXuAv(g#kSgvjM{JpHkt5lI|La&1zX^CTsjRqBJA&0LBUAmz)Tsej?D%^->C24X@oihp0BG zNLkzl=rWt@ODsOe(ix>dnAuT1G9L2}@J-3f8eBfv2iYx`imO)GMyqB?obuXBr%iQI z?Rf2CfqqFNCM+Yiri8F|N)G=Cf@n!ol0!;eL2`l&ze)R4nyILu`VP0&qFzkn&lT&< zeKdxv6(`ny%^x3upt>`t&3c^1d@)LZDiK7IyWJWdQ7gKLnpRq`(VgH@LDa?QR`7Sm zEmHlw=we>I5K2ibf~&w)*cD|!N1ElsNn68z&mLAMHJ?~^k0YWilboNUedl0`CSHbu zu`w<~=Vh}ey^9iE_IMqZvvQg=%{T|5e5X5PFBd5WzuCf@(pOW6@nKJF6Am4e;Es8h zsfbu$yAZsB^`>K4tG>%x4;G^`P4Fi_(pO&OV(!&#_m3DE#nw5Xt~`(YU7aP(r*eAx z^Qs$7@Ir+{9IiE(VI%q6qVFtJZ1qG7X2J!BNJ&(x3PD1%KIXp&sC@ zt0M%m-uvqB8uQ8KTlac$PNqTG3=Vb2^nznJgb&g$*8GiVL$`}ogR0mzS}6ZOSHyJn zNh>160Uxs4VGD0@_$q!9PmV+)B-w<*Yt>ZTl2BsfP{hsAr#uY?@(|WI2~sfC%8Sk3 z?*^8jx_K@tOP9#8t9?gCy@bJ~wzv_Ml#tX(1F7R)u~j^p5%M>2efh?zg}Lk#i3{zBO2Ik(w>U~quC zgzw)tW~+2J6P~AuoMVqysS05BIP;6SQf-a=APT-&&YlrWPtVELW0K zZ!%s@bT-$gXhXxy@g2FR?*yN3@1LU|>iA#<2hdTQYyyf{Z~M{iHqAie5#18Aq;t20 z^KaIjonjSoTOo}Z)2x8Zv*8bB8D6b+yy>>d3$kB{IA863vaweI5%nj|Q*+Utb^Vny z^e|V|n2^>mK>`f+W$&5rFL#B%j%t!+DAupTo&wynSg;zh5F@3LzH zS~#!q)?=z?S{#D4D4j1jjbV#TlyX)VY?Dp%&-$a&@AA0PGjnr7?B{zT0$r6;?DJC2 zo8*)?TFO_G?R4LqQh~=W!;p`dqZ|*~qfs>7lTbER!PntceW||GMcieh|@G7 zdpzxMMqz;&ZQXx>`H3Q@{zG@f@~gc1|IS7j8Q9qVE3Lo^)`aag>m#pT0UrI(OFQsr zey)Udej7+HDi4Zi67E6aR6*a~OS?EqOEhz9(yBjogb;79Pm%FUNz%^H{-e9QTb=W1 zFx%gHug`73um3wBqtpptkn$gHURR!NiLlgK1T9U8qBDo*voqTmHfXM?f5C+`I*wg7 z7?uJ*dMVfLlFP~IA?(kn6%n;A9yfU?zn8zM_*fpEANP24HOjy}(cWeod|VhGJkNP~ za6>`UC}jLR4-eieIIO5TI;SuqznkCJrVp>TbwO%Rrk8OtnJt7x4Fi#A0qW@MtR_ja zQ;0%lIK6N)L7_~(8{sm76%2#4QRl&>WcYgvAyi*v%W3L#tkZB7nkLHGVZxC2c{aMCkpuyOGJTb?~Pzbq(r3IgdIg zQS*o^D64d|`-bz`13rw$Ec@()&jMDYWC1cnWoxJh0lHQAfvLlLHx<@RLI;1Eny~xP ztnuTLkU~2JEnEnkW#AO)JNi*9kPWoGXuZ^>KuvIqC(wSj2C_?z#z7*b*$F=6hH=P2 zhsH$OZ#-78>xFY&VMQ@X%pDC#`Y9ASQ8!T`F$avr{bdsKLlcWdiQCL2F(4^}VgxZ(2bUEZ5Bo{0MGuQ>eg^I{m4@K zQutbwW6NbAS@qcT^Gk+zmb!z$_Gpq&qh(S1SQAlzg!&sT6G5#b+>cNLCmnuzs%A^T zrjX>=_8IqJ00Vj>OBt5Yt?x2Ala0&G!3|y>?(b! z{iAolyVbE3wLuiJu3mf{zFsA_g4jh*Nf#^<@>Nq`b;ttFBCJJbk$1i8dV02N@dn($ z$EL6{auqOzYErl+1@RrkbBNB6A~u|$o`GEh=0#JIo-JCfF{CF7A}BZ z0!Uz(x^*<0<^&)?eEvqg81yZnDT6}}NrEA`K||ulWnq}G6}gC2el4Og@CxO6?K&3w z{t&ear+@!srzD}@Y^D6;_VJ(3d{Ryr?kHcL6~d1w1R}wxF&MmcU5kd~g(#BrqF+Ug z?<_(*4FA*wtvMs8^o-A8%83jV3q(w9$nv=~D>o8Y$&8P+r-DJj(|CBFmBGTn{lQ=% zpu32{f}nfSpkd0jOo#|DfmlsMwS-^)rZ1i-eKjEj)c8z>>oL{36YYV*J+f&}q?31@ z*3{s_(Xn;ZN@CblM|$ef#e`?;vEkuHow963*L2gzKTJtq6Uo&Rx{w84DXLUCN0c_03T!MbqaVo$8ao#Sm&q$3 z-nt%NuM?~qK2%)CU0#kBZ<>zT z6{4#IaS@;<m4Tt9? z3nt>XJ>al7%aF(lDn?k5t`VAyjx=CuIu9}hIkEjWe40B{xMpP-h#xV~sojH(s?&CSlMmAbey1W1JMymzk>N5y}iHBDskM9??cjMlh+RT1n` z%YUy+M93on5}EPs0+xg*hvelzpIB$0-PjDr+!%(YELv_nAnGKL6V>{oqa>Ra(-RVC zvqv}djK?J1lCYDM`f1Y}cN2$4mHXM(vA$_o#3ox_pR}>3DnC!PMTm^qyvIv(5tnv^aCaXx};Hc%_xBw&O(r&5*Co(~7fN;ILXkf?Imu#bin zwAB*0Qwe?HHe%(f3>|7xDOz8F4ojIim#WbrvGsx-h-7E8Rd{FD4GYxJLixcT1M#7g zOn0w1ser*A@Q0Y*twR_+u=0l~pXh0t)QJtFZ`&IY@ScJ zYi0 z{pL*rk_Q1vYOG!3C*5jp)DRL2(yCb>m!9^#P>iR|l&#)$_2Dq-DFwnE{*b^a!GpXf z!gyTJo#%Z?Gg4Cwp(VrOP$A_Xban@&ng7tvFw_6Pq>ul9K3@#<^sN8q9Eg$mzm%S@ zXbIS9alrMys6nhxT@rXAQA8~3%jYxg%%Y87qRD`-?+}8MIh5weT=hGE?fCWKne?q= zf`=!ifjt*6H*OIfOPI^7 zl134+gcVcPIr&LQHppFo!B!Eaa5`RP{1WXlv9b)E zpzNhPe*m3RQe|KwD;iNMQhAalmP$_OrYJ~RHdadZiKaEIi>5R-JCA%RY%3y?47R(n z1uN8pdIQpf#^7R9z2V@VFO6noT3R$RvHW(x^YSSBrha;B46g{u|Vb@P$7;po}du~7PFMiTcb?gG_ z8>Z{k(CE zR`J6YN}urN&d|$9wWn=9dv?$168xoaxS^BRBR;Sre7?W17%@kdXSG zUO^noF`xYh^#SBv!yX@%m&8ZC4?Ds0oI{JBQwqkac1gcVBxn~4+s2V5I|^aaTz1=E zkY106T_1a%P3NBWmF@FZMxEu3j!*2q!O}XvQQ6`*pa3ZEU6}te9v-IwyXQ8 zM{Dnf`iV?rpYt>{qYAfU<}F|f^%$KzZ#{-B#M&*Rq(Z#L|hm>Kwn zdvg&`6GgTgflP|Gs_mD+%l5neSSMrrGLcl}1)aml*GoLHJOV=qrNnli^RR>Bx07B5 zI~?N!1PG4lUcfy*>P~h?P`o!`US^{HVW2QDx1b)|p8jmbJ8=McQo%sPzfZ&)Cp8mM zBN8;nb;q=J^Y0*cF02A-C)aksm6ohcNde9%roH#>Ae9 zu@iWX$Aq7ytHyK9F~`suY2K}ZfIQLSj@(e^3x3kidDWdHOlLH}Qtw}@SNG1DTq}7k zcH>mRQ1FGAp2LxHDe4X~`uoZ+gMgML(Pq54a!VZL20KUXkthFxt)BMeEnSXyX1_Rz zPR0BZegG}GiM-6}sGAU~B;2IxDUDF79dQaBc0NbFPYEBZV%J)D9{NIzMF;9rQ<4$9 zS7N%Qs&1A4`iGT^&^1OHiq9onnPW4!r+ke=pq28;{(Uv;#-WX&l8_)RVQJR!f!CvOlPIFx8?TMbX4_f|eD`C)tUzO}Yh}mhy&~meLJ+>)lfJq^8?M{*ptw=6?Yn zbu%4y6RibniZ@1NeN(KOf_R+H>hYl{!M_DpF?N%;#9iN-i(X`|(S0{b7vJ&lZy}^u zBlA}yRgUyuGp5g~ajN32VxQ+NZj7iyiBff!K+G0gRxg2D0W^9ZWfETe3Z8k@pzgvLOWA zQX0cw^O(+G(+IV^h_15;Zg~dW@))4`!3KsE_LQRE==$f3R9#eR)?>{^)u5>bt_KH5 zd(!I0Um=4)YA6wuuT$R>SbcLC z+0}l<^R4m+`eutCk>ZD~(N$MW%MI%)?yDudw@TO=(JFge1vClq;4Pz|PM}yaq{2N> z&t-wHu7b;uH`Hg2d@=(!ck`*`Y9~RkV&g?)ur>f3;qCe-h+z1uc}V)^v48MnKhi_^ zAWW>>TkIr&S#hSJbblswf6yz6V!T;WAvrJL5Jy3v7%8DA*+Ku9U^vM!QgFCX&Ct6a zc`#3@rV00}@Imi|K^z6q^<5JG_acGfAerP(i4Xv^H~F0hP9U)CpD?@?=oMFmwd)0@ z0djKQBtG+}z~#&!mclEfd;kCfWEkahr;Z>^Iccr$5(xy%_&A0Z5SWQCqMiMMvVuS( zgs|?#waFT_{FPc0QZJU)3aFMJ2L#L5XnIPLWGzdc+3A7d+yU$o`F8cofp%h+wv!}NUo3P^>M$QAMW@}Pevz~n#BP2K|b z^{m>LlAu;CZ>l%@D)jbZ0OxFmU}GF&wf=sLt7+C{$8ZlKwb8J3>4G+IA5yc8tF1e1 zO@4Wj%pL9QrgrBQx)=tW)|0P2-F(H(!pvgjbZ<|Ve805ce7huF{AGSC4$mGuMRtGsR_k%*vuYX}7lzZrzKMV`KJtm2{3y=ho*cJd4`r7$7LG3()Opq= z>SO)t?yIakeLMTh9>9udHKh-QQ@XHgE?J9vg~it%#AMpqlR^p=x#{rF2qkN($8{J# zWOFfbZF~Y!IS#F^L{#4k)KZr#%`!^ck4&NJL@pX-4aWh?A?qfA(KE1cnR)}bk~my9 z7S(?tHS-_M>^qeIr!Vq`A}NEpvjI-XxBg3^wIfSFO%07{lFA^9(jh=H^LVYe1e8DV ziva)@)4Gq}xQXVXIStl=+U>D5P%{?6^6W;KM|Hvq0jq;vl94ng$DTUW!vm6K*7<@}md*%p z)(7FE$J5|Uzqgl4Yfd>HGt<)rx>mF8D&JU<5KNOkP5qWf3<26@>BWYQCfCrl<$2x6 z^G01t`$71U4)AzOH;xhi+_o*>8B(ZWtm3EzOW94?1MMLk#U|-vyM5Y@1f=g zM*|JZRBRoqz@yr3NPiyr(Rk)+?o)HI`7BUjzk{>6GT7_%509WF*$oA&)p2)}xx`9% zH~(0fq{5lRw}fl;N zl|2QJpZ)!+d8dDX6oGJD*WWG#CsHn{GA;bD5b%Fa=Ka|ZKaCj`xpqA&x=EVYKKIG; zx#uP+`T}F~9S1^eIK#$?!M+}l5(r^i3b9*xa@hLO(Q;zSP6KBWxQx9iL`#U4A5&`t999%x{j1*W2k7^QR-7HBdn*PNFH%oSLik4I) zybJIp%=~;}KVF`hhrsz|n31OB?BCyKd7vGrn?#)~N2BZkaF`sgfw$6qQogG%?55b8 z`0`dAlZ;?=C^8i4OhS)Jk3)yRJjTSOkOunKQ$N!GmLWV00-Ne3#|!KMQhd~m4>i!Z zSd~q&3>OhVh{%TX39jc+*GcxLaR6n7x5>-YI2cs{+Erq+x2F^`JA#OEAiHS*?k+Py~GePF!8 zg(OyNPsAee+$q0C+*I@IR_CDpo(MigH6?10J#kb~{`&6{I_b#5!i9}uauV*1RO%B%Ur+TE(RCwcg^4i-j@uu9imtngx} zwNyky-;ip_XBtC8Z(J|!YcYZxhQQbo2(66}svRGravQ8}c!pAENZrv}{9NuYY5-`l zTY1v`5T8kUNTo({WdMGUL`<$l$5mYx_-abGu*$Pk?EEKMym z+?o4pbe`?IhZD!RcEyaWb`zxnjy*%ks~g&ODi_w5Y7J}>Fe{hWhj#!FD4D>&WKO@d z=O?QNhbLN{Ee9nbb&p5X^pY;Xo2tDu7Ee&aVtPV|%7GDNeDbI~51yB4o!tb{jD;iW zC?*w69s9M>8_>OxC~?^e8rE3P8Z4c0cHDuhmiD(c4-w zzG1C(k?KuV1q|st{d&F~QFQE4-eLXF%ZW3yjh)s$(D3nMd~%GG9$BTP?u>qUW^h?rXTuWhE-!X!<-5koyGL0e{@Zj~x4qk>FJpU4`} zF5R(kzAuhaE&qF9~QtSbm^4a5D?cEk%s4FG)Ls9B`XP=aq zjetLDB}yx6R`cw@9-$|ceS%}(m}psjk4>&xCb>E;oEMN6Pk&@_QK3TG+25+V@*T{L zwjH93^t)umQdeE-UnBgw-I@;hbdbvEH@x=Tm)K1 z`1C4aZZvGpkMQbA!!knRHh1sU?>_c>@h2+OU+43-*R`nC?MM0sUV&i%NY~TRxZ1r$k;bfUiOuz2 z2o)C&bNhLFKgP@Zkq<=sWUI~h7qhH|*n0W26t6%%8*jTmw_uMqk|&gZ4nzLcpe7QX zn0)?DLGV35L6aMm|F%KE0P&#y*qB7t$Cj!b{V9)+`$rjX;d2o%El(8hs^k%FhbX0i zt!Keg7g=|=*7u;S`BZmyYr^SWo>+_nUZ|@S| zz4`oedSkMqrunqU!;}jy@(mYL;y1qE6&}HtpiyNyb;O;Pvr(}utDR9UQWjWIo3RQ* zlJG$Uz zzk~bu*-G!MM(;G1jTmzhPkZ{-*3VFJO{ZaUP~zW< zv74`|qUrPh#n?N9iPCk!nq}LzZQHhO+qO^HHcr{L?K)-KHoI>3pa=IG{F8k4B!@en z$h9KgNJCB0d(niP-FS5=u9_cq@@af_>z_AE*~oodPH_W8x(HlW%D&o}=2_MHm?{L& zg$_)vue`PfWBqvVuXdeJT+8X~G4GV*U_YTh*-6YcbFSTfP$^r$+1TPTMLFzN3r4s$ zFktUAjUY--aJZ^n|DJ5R+--r=#l53<@^Jc3)GST4Yc|m?|t7d za8Lf8dF4wx(ShiO`Du4lPF4d*vj$iJbOW|+VnM19*;KqptT=Z;JGVdG2xa)!(zhbD zsbm1ngL}ViOzPWt7`YwFV2?-09Z$UwL^5M)cYC*3DblG#Yjd}V?Q1x8#8Y@k4JG-= zC95GQWjZn=-HVVg(n~^=(4B^=NbEv9_R4sDxFFusxfQwiQJ4H2O`;BY1!hi{Z2mbR zN}2$s8|q3a^T^wI`$iG067d<#`@*gzbIsfJitd^SUlUUN6{D67mVWvqwtN z;#csL=|TYiWPGtnoGMru5?lrq);)s2@y4RNyG{4Fg>YFYBdiYsSA3z$ zg{6&Qk*GUG5teVY=wb^tV!P*V3) z$c!Mxlr7yeWozu=f&J@iiv_AR{)-pr-u$cd(`F45L~T}#L5Y%+ZdN=#WLi|4@X}Iz zUMcagT6i()Uy)OnWL0gtaEOMc#Bm&rOG?P3W8k6zFb^2!H-Z?S>${cTOG7FD@-pvq z9dytBC5;yy#oV`V@G6Y?p5+HeLtM+kGLsFKeChTwz`$a+{8i-scwFOAAWN2PAas#1 z5>b-Qxs5>)lrG3B!oL5N}YjXD1kJBWWENej0c|5yL z^BCdKupP9(_?R{%W)mRq!%6dQ{@)^qr%6;=g1;_t(hn|?a=2ji#&8=-oc5CEV^nrQ z!yz?Cl8a`+&?ELZGyT`2p)U?r1^E*NBO4;Agr`1&z2oGIsrGY%7 zM_^|LWQ@#mG#0QqIYJ%wluj*5CFa9Iis4J@68m~{q}sWWn?4en#)TOXR9T%mN3y_a z8;$jqasbxFzfn+^Jy7px<|3g1?uALNsA1~Ni$C3~Q3o>9f)1L+EVdHJOH%+X%8vA> zgBQu7i|9aqDJHL|EA8(}5u9|SfBdnT!puV4$i54GEP3}9o;0>_You^i5Ne@C7m%Dg zm^|h*7>&$i(*|k0FSm{@f1_$DI7umFQzO7MG^gP}~^md+G+Wi&o`L0MR;g zB>9P&uVC*^y+5nnlh7yqMNjh)v!T6=?y^oKkG~jIQJE@E6%DdM^DZTMbkIP-Vk9fI z`ofxVo^9C+KRHygxq0ZC=znjMk}J$QbE#@>A6d;gPtQL365uglwi3>2P?IGBCA2B! zG6R-IlXRV9e=8JGWdWnX-jmG%EJ5T}X44{rZF&o_f;?^`tvXS|aaM}`nz~o{xJZBM zf|6yJS`}oyCL`_2FhE2B5bTXn?8q&oJw6oC0}jEAfb3UzxWXyPU#rStY)H&Y=*uW~ z#KxcK@TP1moJ_KLpz-FKc|$sGdLjINHuUiFYJYPb!Ql|4o0iS%-FZb<0-!Z?ENtfz zHZ0ruX7p`;<4BxV40E(X{-MCzvQodNw1v@>rf{lGIS)qg)FUM~LAvDB1e^leGi z&a_U=dHT0J{DCrSn#HktgYyZFQqvrm z@^9{G9UyhfmQx77dI< zE(Y{NGtib6kfG>kP3ye;+OoXX*DLoLhZIhrn=`vh)sf|^NhhbeE%!Wk|9#zlcHC4J zbhuko6PTk+ESH@MuG&~FmzNy-?=^+pUtc|=YneaTfnLtH9ZHU_nlqC|b<}HGH72IW zyUTXCKBQnIbN~|$xrg}4b+yf zM5K}mZ_&P;T6D}?;kieSu$V*6szdR#L2T5BVsB1HM1*eo%*~-DTp_K|YAo4c40$fd zXG4Zq&t(&Jv;q!mRL7}W!BLeV6unnvRlZ<8bP?{?#!LhF0L&Z(OVJ&?`kHCkw%f^1 z0vZ)Tdb`(kRWbXq#a0fZ{Cj%`wHZmtS+H+wmqa&N$`zCwd0XeZ@fK&LV`0$^zGz5e z(t>48{NHD3>E9_%?T}3SRrdGc`e@l#W>zlr^idR;?)yVsrvi?&weGTA%b9^A2~77X z9y!_m`X8qOO7fAtD<@kBfsz$G_nkes4iq<~eJ|Vyuxbwuu`l5L0>8CV@P_&qMd8Fl z-q^%N&={Dj&-E*ut6NtYQ!q7*&MC-KQz$=P*?Ct2eF=ezE3ps0qn?4C7d|Js0GawH zG}!&IT$3&1r!;A9X}NmGS*kjWumkpLUtEgA@XCK>K|+WpKW`5I^xL0W<34kSfH-Uq z*=>J)T%_^)e{M+&5qZQWzK}zNVSBugW(m%_LrAQ>VSX z?F;dbBg~bA#|1WZZxZ}w$ERbiwa~=DGbecHloMytzUv8-Iy_?l{*Boss0S{~cPjGW2LYK z1o7DP^qfK`vXKyU6^{qn0)8Aajw&A+0}jBs{Nj~Qd-jOpeL3~XU$^Xy($*#v?HEk& zF}?iU_rw-XF>^C;3EB5UPmb0s2j3~zE5ouS-*qtC58`z$CkNLN_}b0Xxcanz8?ntL zeLBLsN(ME8Y+%R!vcAnM;XSrw^WZ(}tuBpE*bP+z*H{P#^WALl2ZFne%GUEW%duxj z#RId-p@o{78Vk-cl?Ns4TZR-r{Lm4B>V$M!Ai4A-r7WHN-sCP{eDz>QN64~5%vLN2 zu_tJTSBozM9&4|DaPxeCZheI_4#`182}OX+yLSh1)Y5Y@iN=?hXXY3uqTcsCK%;vBzt$+wW>>PdAYW_8s&Agd<3_!JHoYS_#7Y zB65OpO~}GO{VK-x*Z&l+OdJAwc}<(4TAQmT#L4fF@%i%T@ZtM)Q1Wsf$2d5>f4U;w z1`XQx8_s2pL-to8EuP>n>Tf&J(fZKc&Sz7D;)DBpzp|ATA>o-pq!aGOAe0p?0*NJ; zd8)r|F0?w85%>Hte%;QE)pD?90_&q6IIGS3@!1ujG4J2cdu8SGef4=gVo0nBHfKve zn~VeQnUi8TIwIlmnLJzRmDh*Q6RR?%g(Emi+gq&NDK$JaN6LL6;IXS_%((>tk31h= z??dU48d$vHWbdm2BeXEk0ZvkKkpU8Gj8Jq|2*zX#%5G1j7zqirET;d7GI1vsaO<}~ zQSOh!5S5qDxk_iXYTA^hnl&omgg z!DM!ou2xe6pJ$yhoxw8BRXOiQT%DX_4yYH4(GN?TCc(;4&=Pt7SM#uMSKCF~I8sgB zwabigg6Zm$+7gdJEi)n0I?-;a^x{gRJRwD?p;K(cvo(oouTCB>NFa7Pt+*m>k zJGP}Nf?wV(bce_}Ov%6Tv8072Ks64jPIH7Reu=i4e22=oAfvvPB^_^%`1zhmugwVH zQOXP~8s4i4&hkdkdQ4~dFY&lg%Nv6r6SU%+t4}nByZ4$*itrSypnJ`4HAn@;JB!ve9{)w1)#0 z)!Yj`T?IYljw2sNPoX5HO!#ppL1#~4KT7xw7y>(6rN~7uiEMnNpPq5m`-P5|&s0Pi z^${M8pu~JR)&-`U!Hbj>i0)DAF>QI;1EQN&u3Dx{l;&V{z^C|k|Ar2P_M(o#e0gn+ z7;5&*<45L(4;1jSF5;PVkB8hu1-juA@Z^40Xt^#WY{?Kw7kHCfiR>d&VXm^!NuVA( zBjMK-go8jgbDy2^0IRjAnIgZRQGNo7fKyY1@qlc+Lw8IQ?-Z-aIJyM^o;I+NfMhg?piEzyl`HcshBDiR3RwJLDGJ#5(McM*^phPqH3(!A3>yL`BN?PK{8ciGt~hl7$qEh$)C=x{rFnRNn^f{?51Q>q^t zDKT>a{#a{P%H9QZ4Pc^oxeZ<9+?5kjWP&!r=Kq96(fyJ}s17q^mRtS-$NUp-xMG~d zQD2+7!JleT4rDRdR?Y{dVfu=2tQIIbK46kCipI2hk^!DEO zWnD->wa%z>3R#`E^+oPRs8LyL&sva6{GF*Elv1we7z+{&Xf2I@lPFm&wq50@l(`p^V%W;jE0ypvo4^=6LM>(E* z){#isWFEc3N|DDvP8Y?vi`cLNh*x5;6~DWzKgK{2AFjr1yqEE2ud&OT`dUX9sMq3b zRWwI$jtWM1e8Oms(l(pYwHiI=QNFR2@b=d0LuXfla1^ZeMn$MsxIP0Dd^I$XroJt!RRqe!}ix}D2Jtl9~ z=$bx364be9An$Z9TQ4eqf+ih{+}YB=VqW4$& z3^*%mLu(%e#o3Tedn*P=`y}Y_$9_!o_Emaji2Q9b_S~t3nd_h%*P4<}ARDs?Mo$(B z!`LswV11Nw2Grq}mifzkzz`s?oJ}uINlRb~3=EF{>tbVt-}f!c0N~a>Bme=l{0~6h zX98YK*qPkx88@$Xmz?=+kZQoDqWlOmGLXzzfa&g}OTZks5B5&9->BkhYjP6%0E&f`A`@iAsUcBzmBScTSWdV=Uga-pL96=vcWQ<+5BDd zZO-5YbHQwdOo%cO>II&V*0ktFqCdnOw_hpqsq;(}8BZS0Lef=TA!4C(R-tP=3k=!e z0O}+0;rA~bJwyS4D`9up&`?Yt7pGO zPpL#TZ3mdW>B)1CJlx5Q9?l^Xr^VUwaGcacbCb3d(j^!*RTe<9rd0kvX^1mcCte(W%;m8AFZ4zbu zIV8Er{)}-)|0W*%Erc;^&X_Jx-&j3g2>1t_s$uuil{(-m{aBpwokB^;tB!jPL;e*c zB7Zxdm(AOG(rg^5F%*mw2@KiVVe)vO3auZ6|H;Q~H;pCv1- z0;K4!G5(PXH{jP3mFVAhN#=qfq@NIA+biQI!ObqU@Y*I}u z#XZR!IYaOad6^6gAbsxIQC(7B?oY>4&41S|Kvvl#lwtgPU;Lo&IXZSnEV!@zQSxPK{4H(OX<#yR0-fplL`o&e65vlEo}v8Dx6+lc6FSICGR{Ct+cpVXGJfX zTHHthqg=l{X5)RN#6np~sZa!%XFW9PI&VtJnDN^@YP9V#{gJ6@TG^;;f4AvMqN<#% z&}em)jg1{fK;5-deBsYHD?{7Y-!aMRIHWWX>g0hpk~xKPtK=C+6+lpHf=awzqAx=>e?TPW+`tUA6J~2MFX(_sV~1akl@^;w-HH zn-;&q9=AJWd)Cu0*fa}BC&YKpSH$S#vLk4P^MO8QuqfsYza|*RIevL)qfe}$NV~*{ z#Ew@j9BZ{dR9-xDEL;p9{Egssdef1~Mw?)jhR-4oqNDsUMFmUAWil3WWa0J5@pl)Y zpy;`KKuU3rN*~w1!q>--*~OE= zQ9K(lF-O@~;W9Q(|5*#bP6+38ZU1(6h*wWT`{7d=wBTx_D^= z*fa=5Iw2I4Cj#$?#C=c*$Rlc=Lx30var5_saeJ}&PZ&+g0hGu1KsJ}($q+(`CO92^z| z$T?xrPC?>6Xi>?Vv=~7S@P!O(y<6@iY{o|3;zXA@CFg3D5TfNZLFlJ!6{Y;cCTFO(Rx^JjN)30y@F*>g73G;u0ohU>BMEaELe55^TO(Z*CcGX)N$nZkRu zQH-PUGGWQC7}2DPOd~IaeiYhEs4e$DH^u!Kd;YucBC~3lhgqOEoQ^)mcyPnDVJgiOVU88w1jre>(PYrS_Dwm zM=HHu%uee8?!$V{4UCfVJ%wea;e9#SLUX#?tl0xN{{DIHh$~>0mO8!^Y7}-hq{`G2 zc*DvP2O8^*e=o`hsHBC<*X=8@&gkar6(+?yMDx^Syc+Ywn|SmFE1N{9T?1GCh>ml@ zwVn*nM$Ux`dHJgi${X)pBnUZmC1}@WJ*h{L`dB7GW8%<~| z|MA2cm8U&QTA#5TFA$~-(NLJey%X%)ffY0EwxoJs<^rwSG?5H&f{{fYca1uD4sti( zLzuboLA5~XqX9#RVf36wJkDj;=WecL`=Rsh6eo2gV-G4bz1(kOcTUSYa!0ZR!o!nI z|BHl2czA-Zv3$kV77 zKNUyC{v&0q)nj52R`amp*X5;{*+~8T#=XJeFlI$d4fA;W{5;PYMP^R*ahz1U%KbJ-4^`H`=r%8GyHN!d^pBis z+D$G+o>ln9VQVG3;E@<;h_Fi^l5?KDc{mV>f;i4*U4`3eW6($|h?+{FEAzHF99^wT zPNj@Zbkcw{;-0e%Jj$kFh7ke#)V~O{#cBm0GZ#MpdqgN-Q!%IYF`F+Hz&_t3h94C` z_KATA^f#42X_&*KRl9I`RIZ2>mU2>Z9CmHop=K|#XHoCZ5BBnmlp!cS3H1Be(5PI= zccZDc$4CL(*EmmmKmE*HU^J(B9*&B99Mda9JldgVdd(V+$YTHtHv6x2{zm;t%!l^# ztLXQXTt(tQk<(ti!4|fze&;i@@zpbT+HOUfr^GMq76Y0D8}CWC-o&%ac-ZwN@zvU5 zUucbdsgD`o6TVdR4S)rNW&))sqr=9lKx#_wfQmj1nLf&brSi*EYe z%x&0vWFU!PU9)xd%5vNd9-0#aY@Upt{UqU&!4x~}|uAwtlVTD>FXfikN7iA0ocM`{Zu4`ZUb@8G$$#dOffECJC5>)u(Teh;xIEz01?3s9y`>Cwc~8UV%k1KD%lY~ z6_PT z=XjSd4jOnEboE;R&%1J*6r2`fEPo=78rDT*C3;zk2IibeFvj=^$z6wl^g0ue!bCS6`LyJkYBD3cvi%pl^bZ`Sab99#CcvG=(lT;9&G* z82!AY!}82k?$23$aGNlBL9jO#bD9@s=Q(S5B?+*)Bng=xWfKFeGIoXwX54&`9`l8JplrLNwvYeq<6LF zg$|BHM=*cF=(8%G&nam zVS)4=KB+l?V(_XErYIOUd0=|GPIR!kT08(xr1nhjS_eC~t5O^|gmxhU?L$_pXdyx< z(nhXs*GD@WvRJ#J8NBS-tPyZrMgm@k-5xHcXQ^}3kEXESC0oDG&dr`Y|25jR887rZ zeAE@9=YuHA6^cw13i$u#2uEWVxfb#CD;6Ox(Q#Zh*$ZB6ek7V9A&U&+GAGFSU14C}cx!#!K?uOJ# zmHZPM%{HLL^Xe07?DI}L%8Cqu?7`lZa>v;~HQ3jIshI#?jpTxE3jZ=W*0@|ol8kPd zJXUmIvk;d#%u^Nv%Q*Hzt}2rhVIc%nN_0vb%_EDT9K8YJ2Ix8c@;L!wX5kuDO8O4| z=q6@W8akVqYqCThttlLju|p0wg;Eqa-sXxoZK1VWG^Mf*CE~hJdV?`;?6SN$X5itT zVrkQW%_kc4%$xwBPKp6p+(?=tx`~2}I;%|pD3ewG1gVxid^B$~nRz?k(by(Zyis)X zOaM0B)x6%^qn$5|9^>lsa{$kRTGsc7G9ItOebmWw#FC;oR3cJ=nJ|(7kdcpp_0jj2 z5y=T3=->npTo2xmg-8Jpc)eE`fSHihL&Q9!E^LnKQ(VsG>ALpg7sKH%Of&e!&w^4! zokY=rjkjL}R?0v!zNhTPHl^WW8*G3V%qw+@ff-AK487~70f-f#u&z2M5ApR;L6`&Im5|F-Jh1s>iYk zQ#LU}+L*#%CSLITMBsC(ASlJ6yvGiBrb+BbSrikRuvvM&dweAxt{sqLNG9G{Qk7{V=Ff3vDhG+u;A82Ehqi zYvjjIEr$>RsDtY$4kb+SPX>I9I;fg|6DD3Rrl304N7_*r4}`BanFxGz4=-~+T(&u% z7q}k|->u7$xP{duDht57CUi(fbd$kBHX-uF zA0-p!EJY@r*SrJ1&dqqnUktrRD@wd9SM){WREuE?iv1Kzr*W4ePgwXkbFH8O6b}u- zj$$iawv)H_tz2RICWn@J&Q#vRT9Nx(jidaL$UC7?M`2ib$hmG)qu^|YL}Qp%Kv?a3 z1eq9Z)%4ugORKTZr7piFgcKHBNPOA_x2ha#yjl4BZ~>Zk{N!vJR0_~nNAwensSP!9 zT56>FAaMGFx5*h5L1FWb^w z17U^SL)-(zVXDpReDIz~+ArF@PKZHLi>N%u1gEsGd1*DF%!1~!piE&9^aptO23N z+r5TEfYuoL#7sylcxLWa$>LVX83KMMgy!%=Dx)>p$lg}oB8^rwG7(Sf6{rOO`37=B z93v^xEUQ!D;F2rxZaZ&b#J!W}sB!7W-67t5Vvn?en;u2%vZPA8&^B(Ob46AZ#bDq`JFXBf23|rxW&+a-2QlXS$uRc#EHy)99k{Mb6 z@savN21v)S#iA#7mP9^Y(Q_PR)!7#h@pY<6OD?LiTLY9Q7_Fj~H+dVpxHW@0`)OPT z@@fHqsraW^KFU^sVwzP)m!Vzbo02uK*Hf33sYN2)QLghvR8qNaexxJ+CJSZp8&l2^ z@dyX55@naebDz_z zMJ)@s4CKDD^$b-cH(G%3F2rZpm6P#V>sB!!KMLhKGdE%A=hKatn(9@yPP|I1jVyQ` z^LD9@)HXAvE{EG2>}Z+lU~dm(HfJKr2 z!62*dJZtmGNbK|)NVVh;;zRTq<2$M_%E^u~z!;|Fn;pTEDWYHDWeYwG*=t=xwV5NMMU9+)vTuf^0{j~SMv)_RgoSqV^%jG}o8vtDP49{Hpy6;?W2<4jjC z5u7sMUDy@4JQmHa?5vyAs^U897*&H`geeM2_*>*q)l+#i za+f0Q&>M6v@#4s?ptin!&Y7HYysp*?h-Nu})%%b_SOd>O;bLXNkciM zIy=uWGSr;-?v(YrgCC)R#s_-s0;mnH~ zq)kHXyY8JccJ4y%&0yy$+IH4MH8tEqc|$gzbJ3Z8EVF0}^C{+X$5M%DlE{6W7MuC7 zHibu*x9M;a-~3eV;W?xeCzf22e-vRoxuPt^21;6MZ8GMFxsFECgC0czV|M97CAk4V zF#aT@VSa3X3hrwecwr8bC<0?R!cMKQQ`Rt(07r01jzp>E8Hs*(xFRgRN6vA3yz;!n z^z#{oG6G$Cp&($y{2u_+0eUi1-5(XH|Q%yC7NmmpXnCM(O(GX2uA+(TA)CA<{#KGg>@N?xc zS5r5^{!J&>ZB3+I92Xv?<}V4R1Nn5c3Td!nyxYhL6&Pv0k-r#V72@e zU7RR&1*cEkw4Am*=Y}Qnl#%xa5;&EeE6>AdH$k-EnsOiLCQg;2&v2_yE`wl{>qhF4 za0sG*Pb(-6LlkBJn&BsNH8&Mxt_hEqlt{uMPMEqQ=&Z^KiI{4)Y!h-18$~?9_OL1% zhC`ryD{8LbAgJNtF>AGP#v25E@M%H`5@nr}sXMc538MDXjy>06w3ZR~*PjU_2D7d# zUq(o7?}h6q@;CWVBp=TJJ+f1LiQg`5yAg*Lvb;%&;*w=Mq?%|#GnQ^IJo2hUc}Ck> zl|0VZ&v|(;4$ZeSEz@jh8zwM8T#d06?*YtYRiC=6uB_ZYms@Lc!xMCPG!}|6XrK48 zj0r|1xE#G5?1Dt3;NfHY$<@F9J}ZsKN>_Gxzqru-g|{0Z2@?f~p|F(M`{(iPd~GMn zj`JRHn7uB1K3+|hTfT{OqMj&7Z(>wa&kitLHgQ=RXCxm;@y2{(s?nZ;52-l(?j2%3 z@V1m}fIB-9YE*WaeMO%uQ{_eH*uiXpwI=$?ltHFOV^D2x(kBG^!dGT*Xp|ck|LH{S zJN|@A*`K%l2^?uUR{yV;KyVJmcAB2-eQ8Ggy8huD22z zvd|85UX}f`KlTT|f`-6rkD=|0hGH1aRgk{IdHu=IVC3^;Hu5kjv3h%STy6(kq^RT~ z4Zts;21O3E9k6q9sOw`9kVd@%ivi$Y!I|MUR>-8}SU{r+vMyDa{q{?(3oW;S$dP(y zSh-*pr0Hm2Y9AU(B2xT!pl;G`MTwfRi~pjWDNi%q2ky23h;WiF8m@EOPKG;9wa(WH z3jEG5>qYRUQl^4&X6}*qTuUmCak;isa3q^4S~OR&0fqs`Ovxij2u7(_zqmb2N+yZ5 z<(oN4W{UO1lazS12l7B|)_2&nC%l)L#_}SLC0#nlby3BW%5{KMhzldUeqM6ZW?;;y#h?l{G$JA4us_jX!2_3@)H zwL@Hqe8jl7y~=;qk3SM*LZ_t<{$&&VBnkotgXU-~HO%nZ;YD?^%!2q&uz-iA=`7yi z*1bLjec;i|9fZvYrvvU_nbt7p@xah>;C$@WHoAqkNcgdF{NF`L&Hsy|3z9TgneO{aKhJQj2z7jmx*jRLfg13KsCP;{@zliZVB z;Bya+3V%u)8!mC8E(R`wQrr@c|L1*DK}yZa3xXlL0`FcKtAR(F@L*YUf^d+AcvmJR z0N-w%c1uLCBvk-^K#J+rX6Y%_@XGGb&|HD5?jp;DJF@`sV{@?U=nNCI76T&6hJs`( z%6&{=*zx6>k3WpYp?y*-sEuPTmwR>@d7;e2tG+jn0gLj)*VrOpA8aLk6vl`0X4rmU z88GZo%3@&Y3*hf*`1j=Y{lbmAI-<^nn?5(`jq(@qyy|%?^NL1+d)BLn*4=;qt!@k7 zVwB^QShuM3FMTb$XegqHYu9u;kg8DTHhA(0b`?nFy|9TI_+2!F|v+p^eYiMjr}Ntv2KREr4Bq-^<`^g zAJ??mHqgYukjV+fTA$tL8d`nHJl)EhP>{hiQVAc9`2`*Ta4ab54*6$aTL;T*cFLPp z&CMl#?3!2=7eez{e|3`S=9CzzsR9)W+BucNdJcqQ6yRFTk0p>RDe(-ASch4WE4}^w zkvE2H+3Ll#v1Me?(5;hPx^ph$MZh)?>J*VET{fX)s=RrS3x=p1V3RjXcEr~iF-nIM zDE)*L<&(k9uPnuR#BHq>Lmws&`;D~D*)LlbayHp<*9^8N=Uq7M6y7{=HcaO_;rnnH z4n~ZmI~sQ0#7D#`w%i9~mjSX)9wxVXd7140Gd|7n9~z29)J=U$mzM z-41-8g-M6`x`3VDE7~CfM!j<#dS{lfAHOQepJEBiC3sKpxuzlUdW{>Z#Q)Ffm(7pw z*G~2SJN@SR_j-5dET#`b4Adge9^%gM@j24aa+!HDolABdZ?E@OvSXz@FbEAo0`Lgs z#LGaNDDp;iciT(#kL1KJ|JbhD%Zt;tv4QjxBro#w|9tf^H)MnUseN7a@Al>UbUamT z6=NbSqvwZPtw}MMn3NPUXIRYp$?d`8dlHyb5|e$}`K^trIa-n7h6gd))G{_}LdJop zAh!lqUQMwm13JMvH8Ze(Puynh0hVo&Z(;!2)_rFaFn^6UuE*W^XMN2~PLh`}NAke3 zlVI%)k7_sw0x!Tgi=se891UR+qKCkbOB?Rmz4S`vIHhgG-mCN{AR)DPv}3b_)Jsi@ zEQRK9&~~Fko-793SpF6x=1>H9qagSCbP_Q1-KFwN6t`myXLIs~Cz{)A6|yhPXt z<_;pl*oXZyF+2h@XPJTs_IC6YPcg)VgevzVe)u?Xj=4hfMyLW)olhJ}30mGGe(a3; ziKL*2KEp6@9SWPTxc^)y)z0mbN#iba&82J^OF`j4x3)!(3A?2!bujvI_Lc;;F}1My zo41;kkbyc1>2xLRmp5lR+k(oS&$%kMC@f+tSdx+^Lm2Zq-y88XuDx!ya@Gf>*esnBzG^wYe8P#s(b3$Hmt3bJlvj{{P;$kZ zWH+!_V)wZ$Zro&mX-nKB26P8AMZ)jKL4o*X99RGWq-={nrK?jRLHqzGRc-)4K>Qc9 zb`Q6cH#zqh#;0kdVN2ja67t%q+Rc(K+?_A zQ2<3%OwP%mR$l1&@4M_7E{q?tc5y;gWU#q$S=*d2jXqI>Ne|M9Pgt_WlEM($fPwFj%yrH0gg!Gh^0TZ!!PSak#iqds|;w5E1uX_v6mVQ@|achbR!DH5oof$O_P}02!r(H4yvi7s5R&5DzB}Ud^DYF#s}s* z%shuFC1wNf-tDohl|t)P&WsI%naP&L?BR3NG&@wf7I2Csm8hVu3-7{VW?3-SaY$k2 zNJ7Pa!&_$wEc>4#u!D^NrCq`-D-3STP;3IlmEo#du;g%!wNT%S#ec zEV~aY0SG%CXmhN_DVL*cDn6A)@SggQR9!DxC8T~oj;NsM=2TA8P^wQCI_(ISNMk-} zi7V2$s?a*aE}1;vrnyt%Qe|&!2iMp=8(~7_Kxn*@Ys`X>o+&oqL@CgrzqH;^BzV=O zka!!Kzmm}J5YKP56y=oQTti2(q|I>qLEv4TA*Qq(C~Ly0KJ87%EQdse_+K)Xv)rZs z1S*>s^bq2?UJbv#q`jF+1;53*iWlmIx&_h%i+7ml*y05wlN>UdNvwM*^cO&mWiUL@ z?x7mIr~z#Uwn&T@z}bGi0NHgNV}Z#*3OmcOvj64+C2L<)eu3@IJ^CnsL36-%))n!U zQ(LFzD*b|g>Uf7(RS8rtDc0Vl+po5)jy%l7jGipaQ>90fw;lotg4+fGg~1&U0t&Eg z$8bAX8d9w9T z7THp~A}>bmXI}lW)krA2tn=zfT{*oukc-l zwicJgba|o6$KaP-X}t991f`@!9;~6`A9V^eZ8lP0WDV!Yt?nx7jMHaN08?Xcl&MgO zr&|k3UDvBeXyKNeAf(-1igqoV6S$+4WGm)%TY}-y(U&h)=A+Te>&YZg1(2n7Cs~}H zr;v4V`BAIEOmC4tjw?}@ud!ChGQ2%gBAtLesPSHAj23v+8# zSsu&-xhLcF)DjC>q1hxM^ooynK0COH&YVPy=^WWLO71E1v?YbsyY{5l=sA4jD*?ai zFU1^O?hUdOV?tOl;sQq+z1T4lGinyvKhXsa0IPbgYIi}f*2sFsOiAOv1PbZ%S>Yvn zWYw4o_koAN_+_}D_Fg(9ZOk5hIUz|cASyUBh}>(!nY!?P{(Z^53#h`$P7&bJ=jlPQ z=-{m@ALaNmoV4Zi(A;>redca|B(NEIZt8f#aUa%S!f0O&1&`}ux979~ef1zA;UnfU-_Sw?1dDy-I&LyYDr=2A~9=@sr3lM_DAX|w0?^XhHsHTf; z+`c{g{-!mx-+FDwHy0Pw5OC>~1iriPwKu)Jw?j1Mav!zd`ac&BA4k3PycYsh$VF-X zKX3c?0Z1~Mo(bzrCqqZIKRSN?Z{qSTG9zahui$S-wfuBjDf*IL%ZZO|%Mme;Amj-H zqSm9yy{IMN_}RqOXcABY)ZmGQDAQDtL^Dbta$bG8M3Iq2BvK^$5Xr=>V7aru%YYpn z!e?mH>WsODG8)f8bxhj;OXBzWVuzaIm6PwcYQuamO-M%mUSgiaxsNx?D~m*xB$r8h zfBBnZX{piddhEAEsB{%4Il5}U(--r7(M}kO$b_`xiP{~sJJNZ^V7s{tY38vAT6#di zm5{X%MoZk^7})X{X9f?sV${^T@r8#4*6u&M8J3t-qU~p4L>y#>+ZGcji*&JnaePKl zVKoq2$~sJ;Hc>ewg#FY05%4aMFdUL-43g_&TQhBlH#xIv?IK|VIpz1M`-t;JMiXnf z`-!KG=Nt2XlUf<2jY^>PSJbD68SP3KWS}<3s*{5N+f((l-~$RoI%di9Jw#-v`?OzC z+u5U5QO@Ldd)k#8Yuiks;1?c{L8CZ2p-AU|4L#2N@c7z|GAEhu))bd!JBw2nh|`v0 z`36awQSjS~?Y45HfpD*YM4K?}=>bFIiCWVe3w9H!nAdGtl3(Y|HK1OPUW=Qh+1(Xd z#!eTNkMSRlPf?id6fBv@m}os^Or;b)Q;muyl2u@)`#L`-B9%X1LGbLx2_b4TzkDna z@9%Tzvs3&%Cxm~E2+*;oo3|m$WvLE@Z!aiYi^n^PUIyP=r^r*iMX!CIo%6C7kBP;7 z!7sFg3*1r4Hbmr88_R^O3|^Uyw_$_XOI9B1^ZGL|BhhALgrq zyu+B^RVaTTFRW^o%raI0Q#H4f@jORv`G3A|8&kTR0qJ_m4rG~qm{74RrKT7bkPoFn zesn5%i~%Y6I(9qEtH(gd7gfVF>p-O|3@EGr_?w9iQ?a*-2?D=@cA&yXZ<|38eqQ;=vuyDZqYZQHhO+qP}n?!DW#ZQJhM zwrzJ$pEEb^OvL>s=B!vx>!}`ARAps;nW@z`nvc++jd=C20gyBW%2_KurR*sE;#JtH%?W-<;Th(h6&M$1s7=MG zKjwZArLtIcLrZa#8HhWix|=44NrUi?wtkqAv#X+2Zg{r%3I4Rkb&YaWU`Z9~v8^?= z?0FQaD~JJ%T#?G{vkmL)XS|$xnd}V2x2sbhMNgI?x)Gz-0L!@8q zlZp1XGWC{aswe|l#6?XWk(Vuj8s$LD7?gF#tP4F(?8Z(3cMY;cp7Ca{f#?YIPxplcIMJM}&<< z{#OVG&(adB`IRvyDq5>3PrmWdCPB_e11_bk>2TA{VGYy{RcYy~w&`$3L-OH>Q08~E zSP&#J^0Tfdn>wUl4AtNEskOa|2P75GSJ?Tu$*;(viW5Q%1ucSiO}Egsh7~fD;!2?{ z10~;-v@2WAI9cbQ*jW(B9c_Bl6J*x_&7?=7FI#J@F1@0}?i?=!3-dcN$wD`)#ZrY5 zfnoxj-uxP0{S_PE*5`t?3#x#n5A4O}`>Lz*++!jNPQ%R%zu1$~zpG-mlljkyoeCLF zz`(qN-#D-wt4BGCZQcMXl$8@W17j~**{nkgsN6?}cT_5UnK=^^GIk~anR)vfh$*VRyJ>CINHQ~4y=M)fsE}bGi@C$kI{nM0-#Mo| zMvzwDT}ik~_EM4~l91dCy`!Wvvy;-y4;g;mGDF@%j=A(*W`_#d23olfJO|zF4&fjeOL5& z{Ad$IlG3Ugl;2}^1}(>xIml2cfwej1N=dxp@U!+gvaJCyt+s7-fE8lHgVjoKqii>j zO+lv>8DxBaERhNH*Xke%`WbKf&?{$cu>n*Dsi?iI&SQi(f;jEGCZfYzlH22bczi7~ zff5~ghe_4{#(BIv{0!yWMzJEX-KWNTyeRqnqvie*aEBzDK>9f@0^WM#Q4nV>W*ppn z+_CTm<60O|7k7lj1yBKlS^N>enaw4V=}-Fl7^b#tIPfZ&w?r?nfPm~BMAqiFf|5prJ~AmQe}>9F)8r?p^V52 zXfuka(oh(75)7e~4+xGsuOx)KyCSYyLC$68x(K{Jl+XVV@3niI)nyBlO|@JXJQ7|mE$hk zXJ=!1WX83jdk@2cyEG3X^$ov^5#LaaRhQ`|eb;+2tfX7_l_&qFR;s0o$sIF6SI zRx+ZVU0zlHZCV9u&sD27iM{QDro;GW=9ZU3zwzo($LA@(lxCFxSzDa+Q>FNwPCnbm zp1biC1MXJt_j*CUd<~eYsly{a*CkVmtda{sd&sCT!3(3^--eY|wh~u*V?j?Qe;h$; zcyVnchcRJ@kJHf1$J8nU*FA|OosqV?UrCe38HIke+s2tFU_s8FApaG!OMQP~Dh$}2IHqON>1$nP#^(Z-eMA3hamHAZXJz<5&~{#|tKEC2Vg zJ(Sr$3>BYAO>3G}xG}%!Lq74{f0F6_Kbfo982?}G1OF?rmWh$=f2LY@Ymdhrh{1Hf zsK0`Dl%O@BS>7F{Agz=wp6rzB?-VVi#kq3{NEx3xJZ>$L z=jg}Yi{wWL&7&62)WV@;Gxp5sp1zLdj%4c}G`rC0wVtReAk{hbd1U#2e4dG-85TpZ z`NiUYuD;Bs`|GuxuIJV1W&8bnkm>;xhTOe_01PB7{CqpUKOC9Qw6w;MKZQ1-Io8FH zJ)6*22Q%C)m|zlICAfg=_KeCmptRZ04mrU+xDrgCRi@lXF17$ko(_%|pobMvL5q-` zfoVaUb$)7eL1qCQWT+(AQUsK(=lcI})id{go??IsPH~X0&-$@rv0@=DI9sVy0%1}2 zy%B@paN0t0D3LePLzgM$L5V|fIISZ&6oF~`6u+u$-kbU1!UY%504-a!{Wr{(Ow5d`*fI5qzdFdD!MK7jH zHrg~1^?(^z8xGKJMA@#-i|9P%d`j}JX(RO5EB@$B!BXE)iW+a(Ezl_s zf}5KoZ*mgec4-_`lUs+n89c3@&yAr~YC9if_ps_#U%q*gk_lRyxsoXtNo8}SQCVEy z*q)xtN>R1fq+!e=ltuu0SVh2~Lg{~uOP*F_qvDF|@SJanND7G>HzbMJ#R3RB4uf|F zvkw_c`yp_V+qTcjIje_~l@>M08rLqKN3_|&Vm1*VagR zYMtlXByi9VBnOSDwI^NvRN||-(k*Qp56+U%N@;8#ak?x)5fS3(LxKds5zvrzphd!g zkk$aEzazh$iq$9mvazH3uW6y)b&FgLIyI4t_NF6hw*yBHhxkhkcgx!mL$e}K()W_N ztMFJlMTqkyMy854b?-JthR2DI2ss|7m5Fij(rSqQ1l9?&ktevV&{#Uc-oTUeY&p#~ zZ|83jx@w{thJrW?4?!sF7^mK1G1rjCC?Z_H$v+2(mTzPvBtSBOW@S3sZifZBiDIuq zt%cs~b(gK?%d@_F?gbz6^_%&g6R?<0EKBqfep2*50hTha91iR`F!|FsZ5M=4*0Qpa zOR~W^O`sY~iqV~56T+)h<8CW4Yv?k-pOh2cTzXr~)mnCd6>o{`&FwUg)j}QK^~HVV z#n)Q#J>?T!A0vTB&)jbPn1E;}opnnq2Cn&&DiHI}SE{9NwjZFVvyT{7Ry$}mmT{24 z42`?oK$V!4k)IM(BOG`E%NV1uRU>8b0;8?u@^wTZ-AUFe^FMEDRqUYReGJ0UL_EM@ zn7AR!vjK)N4}hxaj+af#gR=bb>P0?WwTi1)}VBbtV_hY^D zSYB7@0o;qr-_)eF1WRNN;Snm%)J+ zbZahs4moV-m7`zDu-Q&EoHaQIO^qIo!>X~u3w)MXDXV5gMP*Y|sxz;gBzEMe>S}9v z)Q_+%9-ds*zS9{x)8)sn;A%xM1|#MeKP}1iI0gg8Ej( zIq~sSCjfRqnSi=u-raa~bC!fk4M+X*=NaX3GpKA*1Y0pyPq~3zheOYzvQo*JJ--<1 zL#(~klHKVdcc;wSe)k_F;LiJT7Oc=>#^o?4(ni>aekL`jj3OYjS4jR7;-HbECG9-# zTuODz9NJi!O8H>O0n+N;RC9q20j;*E{6mdyUcnST2D&G>%cB?ty4n5MK?y%-*1axG zUOIge4|xMY0}0~mHaj@`-1E}zd*q z=qUyLu=N*LtMVX~e>q}6@G)G{Em-Kf+0v#8j7a=RYf%@mFznm8CYAhqhK+DU9KG^X zwgMJ~=r#@ZQ}eMiHAZ16qfR{w*o#g3;*Qt5Ih>0$4jvlj#&XSF4>T_K7Pxx=?2A7@dXM4t#!HkF3E1`#;g)dQil(J z(3Oj#+>EbjLI z3&Kop=%?$~Dp^VAn!g96jLePB|H`{}&(jq0)F{;oF5=}I?BG!~7_%2-?_D!HBU?Sg z-oHrN-hM|wvQGx^;N_~d)t^_=?739^@r9!q4rHD-D-2uAFMuOd{hQ#Y1b0_dD$D)f zVxTArS`=IXjQ|%wuIY%vi(u|en}_&ft-{LM8&v%~4{ol=Xzth^i!&DGu=Or-sb}*M zxk`HwZZqX}bmx7tMLMhpMq3xic+gQ`8&L1#_yhQY6yN1 zlAK>(*WZPIm7gtpzoqgyV!j>k5*v0U|9C`Q{m39umc5an&?z=>7%x=#@=gRgH;T=Y z-a9UwuI?Ynci}kQ*aRcASS(0XxR$~HPcE%J>rX2Nr8M3Lh31PXl7hz7D6Y1BhHFB1 zq(3VjcJn_iDlf!~*ef-kn-9wjCOOEnD{q!!VCRys53X@<5$k}kCNSt~KxNm`aY#8R zojZsYw@5UD_O(o7xS1CvHOU-D2{slr4xP(3RBtMX6PvvYZ{!_DWK9{b@t-4^^e&bu zyyBWH=;P)cZ|h)j16J@vgyYz0h_6DBz^gyF9hQ=59Dc3E} za}Lq%9o9GKhnZCPuIGg!Zd*IKPglWoD1yZsC<7#us=#w_ZK8h^%AfC^ zuTS^Sk2|4(h}n5x^gnMGl-s`;moO7kej;FUr&s^mYvj*&DqdDDR7 zli%5y_R`b89k@E@EE02VYl;+~y{(tJ)}rU;klxjrLb3cN%IPd)_7~p1S={61e(gG)z$ZTwcGP0i4b>MmRi0h3V%#IudkPQ+vWwF^*#zAh1(d` zWjE3;z*>auA$eKfBd~n=R<=Q{tjgMP+^XNpGhT`r6^}Jh%j{*R0Gv?agaN2@y<+fa z2GgM~+NW=~AVL&!3{$`>DQ2%?IL`^ln+bV>&cYOBu~T?+S3?^PEQR5rg*aKykIG_W zE0XYVycFDNVCdX7EgS>$!q~SW4C6*QGMd(a%mSI-?Cf$pXsxsTQB(BQgx~DP9Bhk@ zSMW<4GNdt|NFYBN$y!|HumHFxTE;5qZEG?!i;Ugck0|Z%{pJA=RNSYBi<<83kit2f z)fkwv$tK1*U%2#)9E(S7r&8`z#kkxo(@eJ`D#A-Nznj*jH{2Ne%YX+KT;q;z^Zw<2S=+FcAos&e!E!pv|HG<&f9-pKZPj`o^5hk(Yzi`lk!6Z(?CQhsik2u&3@9f5EtANm5&2i$sh$e4|u)q!;tShGL zE2N0Gnj1Cq7MgEZ%56Vn!o$mRmv6;tUYQsk>x7z8cc^#poqHP=7N;!hpFsbM?;7V0 zgKLR+hVVhFSk5W@Kgkxyb~?!ipEOlijc!f(hOjS=cXv4vC1kJFu@fj)Ah&vW6Tq>1 zSX81be6R*$YL>ff-snO&=Qz*};fCl04`P%o#8BpOf zqW_A7aQ%CMd-qyAH{&`WeAfM$-r#tFu>un3p(+#t6^$00rc{=gN;cA z3N)Y|0~4O@CKfh$jw}`iJe-}lSC;O-KBgc^Jm=$L!lCf?n7B9g#BHS~zZX-ms=Qh0 z6%3-U_6+B!d9K&{{=?6NgG+A__}$f0ll8Cc!Vad#OvS6IYdK;L2a!NN)>P=bMNlao zhGgU>y|wfQFoMjZ^*=yWRtDDpM;rhDs`}*QVE^AupX@CEGa_zT%hn#J74iF8UocO9 z0e;WPZ0xTgB8Ec}7i2<{*ddTDtZzcG^QFi<<~^t6k8kc;ck@iQGR>qlYM@?R=O}6T zpr>cfUW*z>>XKF>Ns`tTuV%EhybcU(0SSqtc(Ow*_o+SawT4m@-_*E?&Eui!bv}IQ zZz&Y1qUC(17122(QnSdw!EQ#G)l|G=*^{G(yvbrKZzA<@8>u3GZzzaN)k}tuKvZDt z{OQ3ZEu-{QX!&1Xp9Li7(W)455o24KNNdP5svg^Yi{>N^>nQ?^*_e6=iV$zin`IJH zoqU$EK_R0+K9l#Aq@^=$`2`k|01Tr!+G7eyodW$(s!p-qiSo2@8&s0a; z=HhiR*rl9`mV{a=EnX8lj}`5haR26bCU%~A+8hfFm;3|)M$W&6aT+Y%Q}c789FIuB zE0!szmyF^zA&z5JuLIhrR7*DpHG;ERMz3JNic$GS$SB$<&W}Y*SimX3q9b`~$#Q8% zDJqm=Y&?dA-#A}Bo8C4lUht50AXg2jV-sbua0mNHVn_2<2gpFd*y@L<&r*ctttMK= zD61yNjN0_$?-t$Ja~1jg>`g}98nRA7mieHaM|BlosGTW)fRhK)M$LIW7d_Cn_tZwn zrJTac^F+tJDP-!mx`*&6yULv{B=(4PyTm7zYh%6?FknR@z3YDPfDIa@&e7mX5nAJ) zYj6Kt+g^s7dtU~H$)_OI6z_=@TU3DrDeNgS{3ArA^tx%B4WrNPtAYOf_}I(+d3PV6 z!(jW_e|men`}zRqQmDVILu<1f$#C;3*^7R9d%r(D8b70w;>os+4^h6QP4fx>q*puV37jA!-XyeKmrydtx8*U#)?;sc% z$M|!049R$6_K(bGfEjU~!+i+XL;t!PcLzI8kAG_@V5g_;)zahE>~(QE`f1pK<@4af ze*Y%qJ=lkub)VxwZ>_(1l_UGH_0hYz#4Q3yTgmjJT_cCy>xJA1^tAcPK`W$@H{>F zVU;}di4^R8u~j73kNVNP%y3l5XH*CUt>DL49DkK-dzDDznI`Cr4Xyucg2+N^^v_&N zEEoIw=3Kj>^Wcft4qF>eT~+JUe%;@B7skJ9ZIBWSTg-y~CcM}+)SIhIapB;QgZQxe z)%dmH^o!(HLmB|YPL8Du(W78D7Po9d5Qrgl>_P-LM^R&L*$5#qijavdWdyM9Je>h3 zja2{kEM2E=3r`%w$+@ni38A1L6d;gd3BJ^H1<+TVU`-lQ3zTLda#x}56jcb-oB;v) z*-pk#Q+dQI%;+^WZ>)ry4iWuWC4}nWdrEnrnWI>q9g)os1XdQ!1 z$9f)e#p|3TT7TSDL3+>hO9L!26JrE)9%;l9B|iDe&s`r54J!FR#KUB1T<%6 zfO`a2SRrKrbO%Zeb#g`!?XQX9DJOKX-cSeCsPZ;X_<`G2O{iW+BJ4Qni++U;h(m}4 z!Ha>?l=j@AvT_h!!0L+A6xj2P`~on8%z+IKsX-Q^4*?t`HmUWMW%yUg=oe}*5Wv(j z?!ErpbDHo zc$80^46Jt;C-7uy4}gn6QVWF^WRj~2vcM69VMc}dZFy&X#BO55(h#5-BAG=|d;;WN z&{Z4_(7*DvR0O2Vg(EG(1pH>SPjvA%7Z0RWV5Q9fkwKKgD8R>|>i7seDOm=QwjXfC z)5R11uPDBFJf81&3*YZaDvTS{#ctl)V^R3sE6k2&DsVkhc`*%I3+&T=cb!_ z^b#cVujxxJ>J6j)g^cWz&=q2Xzksn*_PW^}SLE_#Ju>BI_%KI2NIz&FZV|( zLU;VwAs3-UUJX=|cCe`y_(ip}iayI|C!rowkb6Y{5a{8c_jM0FFa|74gjQt4m6k=g ze%MB5FYupEd=t&n zn+c#q!I~=(^V8y`hhP?Xt6XXjH>WJf2|Rjt2^F_;|BO`l^EfPFx7+ct0wy67+M1O> z;XoA8Zo?sj(LmR#5&rFPP;{t4Gys{K217CM-=aJqk&6lKLiRCC6>0|o9hOP$KNGe- z#__1F>QRCdN#Lq@ZyWS3vwEe~mh3$BCQqPN2)( z#sd=uBnm(UB#F0!OifgEnQAX?aIPK%Z^5aDatCY9;{)N3>CFoqv55ksb}~`tF!Rnn z54+kmwdXqz9*51wVhWF`SiREkPGJxI2ZYS_Tb9Z|U~gmv#l!QzQ82?VZ2q5+xx<>$ z_M2=7zb5Ka_&DF&|(1NbRQ*54Z6 zJ9q5ac+E~-LU&NZ_9 z!k9paq|%qc3qw-G)Dh{Ay8hwrWRW8U5YjV7~E96fN1k8c*{hZ;ZdhnzSgdxX7{Q5Ew7#}FYf{6G0DF4oeIH6KE>3{9C z2t7S8y?Q%%-=1Y9fV5+;kzJ^2vi@Hl5VMMj3@h>g1Jqf5-@Lxwuf8N1#5SLCqr~rm zSi&q1z!-u!2x3-y*=M+jF|+fjCgOT}KcAm`u<|{AmiyN9EM%9Q)h<3}+Hb!KUveYZEOAy7EVN={Q!d+=Vz64xTZ-bno&kc4GXFwRtkHrl1$?dq zPA3qFsbdBct@?vW98;5I<>-h*X1ElzWJ|Pw8bRsyB>Rp6u$BN1Ho*?I+pI>Ab!Ul{ zV%Dj?k|;%{ucpwKTdpjMHpPsy_;Di(!#a`TlKjJl@S~wc=ZHa(3G5RMYq!189ub=zNai%StTY=7!=+g8>b}jP zVNn2U&k5~9S>JDa2VTSE$fu;E1CLT~AaF=6c>{?3yvfZ5e6w*<{Z)JU2J|vnJ82f3 z(?a(M#E}(}OrK4Nd-{|>X6DWLoCDmr{uxd>`SXr6kpPy7SLk9U9+L4k^DADjCG)jR za5|8rv`$(`=4jXYC@VVYma0{$-Xy1AVNhU*M_RW z91e+q+G^P|Ti3I7z=0rDUF_kNqQLI?u9^-P5Ts-7${(7Uic2-4!t1*~iBiD6V7;re ziglvkrt+Ys4g-^fCA6T8i6Ear>Qf4TH=HdyK>$HXy1YsvAshrkm@wA?ES5sum zYUaj59^!+c_BSYkKx}5@IoDu_;$ixHg&H=FL#bv1wQel-9^tJefYoUpt|3&DE-LN%>=l zmb(Ts;<{ycTG01eV=kp@!sd$jzWHAA_Ki_#>Cfi3@QIiBlrnaRwu2xF*@En_YNm_N{3tR%-qU9^WhU|k*vR*=~>Se)V>M->|QDM9M zgmn=%zWP0z`p;ZpD#6m$67PdFa8k06$HWQyK(*RgiW>9K8Z_OBZf1K%BZ5Ofyb%tL zZ6lM`qD1jbev(SI*8JfgC2^R2GVcuBdwO36o5k<7DOp^|jj3LTK*IVpD&-6xTOt^A zV!nXEO}rmRND-va;9`2&feR8|*s@$(mm1p_jJ#dNyox>)S~yQXb?sCygT~=97K|l? z-VqAalwL++wH%P&&c0m>8zGw&Fe=rb65&53NjJr^|R*#oop*_Zip3>rx!qQ!KTXWEq0imw?>wR?A{L$F@)OSGcPiHxoH%Tw1 zIf2L-Ou*_FjF$p={gp3(h;`Pr37LAH<;dr}cL^oiOT#`IUz-Qf)a(HCwjhYEO<&(^ z!sM$(XDeAJ9vb_Ux0SfpU!xRRcWv%0?l^@4ZRgC_zq3P+duRntAqtKC^jOh0P<~f4 zfAX^~2|V~u5@d_Oddh)3Z`y)!t2tv~7ULY2u}1!ckKlUO5W8&#Q`CkCt(pgvxTtvS zXyh;l4zgMqN7L#bb0pRNO-&Z!>}^KQuXHjIO;WWQalTr{r?`X)^fCoMXx?)TIs|FD z#iL&-_~U>tX92p3oSJM8t4Ey^r?^D8a948az6(OqRLbkt>$~io9lak?HZAT`Kg}yN zod%FJTiNWb^9abw3!!vPtoQLJO^#6jMpXCMliL!%$M->wqZGV^0Dh-WubXND-7Hv5 zS6aZ@(#<=^hI15M=}F51-ox4H6@A6+g6%&+g#Q#x$Ikh`O4k2>^xolLg9$MwQuhb- zBd}Rw|1KB?7)h$Cz)pukYkwBlqVxIS;}1Sr8(F$ewactvTGlv;@kz7+N$=;$06o8+ zU9VmbFNq#ZqZCHl=lcQCDOhQ5(4uHHoft$(@$Z+1`*`*l!Nn6X{6ih7cZ_%2GwtqP zDMQPUJj9@Dh`Vnqg*jBq|1y~1-DzjMsQc6FJiI)8P(#I0&E}mN@BE5(t>`%sv?+lm zQk~IkV-`6XOvT&%vr#O>NTCx$J5t`~ZN0(Y>G%gXlv=uy{A5*+SBA?~G*u=NOs8rj zNbNvgT-8BC*b6^WMa!P74_zsOQe+A*%m=*Fbc_na9*jh54sMu z<6^pDs=WAiVczt2{aP#xcKN4rV%C8y@lKAZMCpB*p3zJSlGlMVnqHR#=$VH|CYJm5 z_mP_G2;)#X^(NYqUoCcj%l_1t>*|oUS0&N#Qz7 zc5S!}wTq}AnX#mWwGlPA7NnSpO%#e)_7`D>^axK|H%UOHZ^8gc6~u2n!Btfwyag zb@4?LmzU;fV}s1lECtWrv~CBTk$t;Kb5XN4S}`SM*sGiR3xuIXXusxq6Pu&HrD2^^ zeQK_X?|87}lPcfKYiSFf!2nLqYyqzQVkG017inL~;FjLYgcU$9y#(Uu zsMDs!j1%d&Ite>+9OW{d)VFMsq)?P|DG46MG$SC-Ni>Ndg0*UzM zAwm#pNU@LgO5>CIDK#@R;u8&fNoUuN%qP! zX{kWSA4nc&MWRUyCM0>ln4b^O-h)ew6Snn!Sy)| zsj0oFoKSU)de(-JwK7BTA=D?WdR>}{5beQJZ7AR$hISxm4e~2S_5_6LlvQhmE^hEb_paXV`!AFbxFDO5PEC&+N-6N7iNTy@abwS5_kojJg)h-5nA>)b z?8;ix+fbReO;py1YkFMLN|#ZCmq`ZPp!ko26n`iJO z?*VF{6f3%-lA;^lLaHNVK53-#T;eI_H4m|#!amwG;Uz}ZX%)C)8&-rt(u#h zLK0;4MWdl>CY)gg9AI}PM$D$tTKaQt}>t$5)w zptAA6>U&)|<>jEtzhSyw(sDof_gdjGGF`_ajpucq-L4%lMrCS|A*&!&&#iPYa^%FPP62H5|n-u6UNQri>0)yz*r85;RrYr=ht0J9($e^NHC=wDQlrm}~XD z4jjPCn+#0%?4iI~fu?Zd+4=P;c111M4VUocGXvxNWFmh47A6`e5iAypjKb1#ck=tt zoWM`=+hv{dSELLM*M?kI%Y#)3&Oc}3^e1ukXxOB;AgKa;$8HN4aKTFirC*+Vnk?E; z*(r?IMeFloX5a>%D;Tj7pt3PDb&6KW(=P8k$dc_8A9p$GNt5AtPMOq*goHjShd>q4vDH`6DP-S z^saq8SawZ8#vl^d0m8+_3FKpD58|A%M>-wDM_=i9qi?SE5(SXaA!*b(KA)c-f@en5 zCg&(x4C~@j#>&$oMO~s+_YgV9kdfA4oFeUzaA}w*e_NO|ed0Z1Xd4$YInJL9D5UQ0 zWOXnzs|Y7Cc8WL+Q^ZK*tLT*Uj*U$k*f7+)EcO3Prc*ky(s@M{E_>+t`3#KO6w6ab zZGW5{deZic1Oc_)7WDI2^HRr{qBdQbN2X?WWT}~a3aS5FInoF;*;P`%!;k$YZms6k z81^CrzbbKC5X;y7M?<)9>CB>oEXg~G!2g|n&49l)L@U~$vOq&$HZG2FR5Y3D-QcT; zh?e@SVH4Y)a?ib7V%=n(X}w%hzqa1|o~NWcnq&zsF-&Wk6Qwe416i*YR^95RnB-8ezMS#XZu!)Ca z)fg1c?q4~-tX^yk>PIgb;iDkK_WFBA&_ielA%lsa287-C!|3DtofRMFJ-#%Z6^&V2 z|J@jqE^ol+sJn-VE})*9DxQLiS5tRzDU3dlm^iXz<=euFu%zjY!~Vk;d$7nG^U_AB zm7Ois5c5uaRr8bvB> zENmdBLKmIT5u_c4UxiRAUR5vuT4kgN^}P#AInTDG0b}cgim?#XlYzcCEdJ!NG%^2s z*`|0S6B;bE|EZGQuG1~{kn=gY-A-2SEu=ty6Pdd|%!L%{qC?EvomCR|mpsWIp>69`LmTG`20y zvsjZquzSy`lNs?RyKwg7z6*k$y;Fc~GZjf!=vtW##>we6;2-|LUo~JI5BoD<9huFI zf!D5A)_Lh2cGh_xK5MH2?v3Beuq>R!zQmvESQbW=5ob|gS|sn)ivmmws8j2yx;{4E z4^&CT-G+JiOBI>8MMx(SSqyeakRMuZkR2W$Xw`k$d z+cDLaPWPRi%EE#ZW-CC;TkR?jmSLY=|F$}vLp5_F9_pcSxJ!DRhT;y8M5(;Gny&Ok zqe@DzI+nOu?PT%&vRa*N0c}-g3(S8MG?>9qq2#vUe~qvM+;15*2SD5uN%P>O+0*es z&C$_q@%yI1^bB7yA&Huf(g z^+Z}S(+cbd`}IZ^f~7bkdsf8TNwi42R!ILL4%TWnrO?Sg+Qfovp6I`r#vL%vgxbus;vLrkZBvCd;`_2=CExX zoR@=WtYu7xWQ)p2TA%4{hBw$5sF+oRVfTy#Bj$|liTlRFYs&CJF?mCN|D`7R2-%hclTg%lcDR`dRfh@ynVl5oD`gh2F$#1)0V?7d zlyaeL`{`3`58+OBo(<^5yIzLsU~hZ%mQ#qjs!af*bgD{@GSvb4x4Jd>qGLxsEsJD8 zR;Iic`uhvE9H#L0Kb^ju|7S7^Bgb#z-Ty?}+WHL${x5CordGiY_BXlN=@lpjwCleT zg0=oTA(;2S6N1C-m5`d(J+MJ|$Fvl)_IP?Rm5vv8kaPKPpqld;BD*GbNt{y-h zgBJC7S<0480RE&gbo>7G^WWF8=#XX4V*$1Ro5Kz`_?@mqv|Q|B z)=l?FKYrca31$4z!^cP9sF)I*fAaY}xJn0>A3z%q`DLvnu}y|bCBjC*0dq=;yhJZ3 z_wysz!_0rw=CoZNNj^7tl#Zh%f=QBrI{4jx2L*ZDA8~9oqqhmvxPGv|ZltryT{J`0 z`jj(ti{~vtCL$(2fm37eLsh9!Yn)p8_2SVhS9qup|2SFMwc=ul)Lb|cRU4&E=1`9% zOEBp-Z1!srdEx3l(jZT0F*=61XqF#7ruuZ_d|fRnP=k!K3=m=EBtIrxYjQV`f|}p5 zX3!Y_UyQv2bEa|E?HN1ibnK*K+qP}nwr$(CZQHh;JGRlm>9^+0nW>s*s-CLrBV1K` z|JVMlwb0FoWEP-U)tZABca|Iaqv!Voa7k!{TIg{~YRYtpvq+C6qNwLMAR53Pm&-yE z?==8sIwZd&N|{g%L*ZJM3HmZfWN=23t2qW1wZ(VI9|aA~GK^*JLXk;3oiGTAFqPrjX>;#!nnv80 zxk?{QvCwS?8RIiDs>dG)g01J7>br>z^32jPO=~$=dhSVi$QEEuY0UxD<*I?=!yD?v zRygQNN1en97Z1rv(!!Z{Tg?-!Z6FgEL;ho)WIE**m^numhG_mYnQC6)e+9w|BWoOP zCadW2qr4(~md3n=b8^NDGZYL-f%>df%aHu@F)^qQt`f&tbsv0IV5&_5`)yk%apdE> zF!SZ@9Kq!YXLR4fKf3`2uA#t7HFZWK(pG8O(e^2;L##@Z<(AaOmc~XYkK4vd8boe{ z8Eh*K(>HWZFP7`oP0I(i3%ZA)M9BM+?MnR;zhP11g^{o-l-MDw_HlBh;B;V}1}NsX z4UZARtZ7_rDheIu<$jkF!LX7Lyi+W6wDza(hGuM$+LpvtrSAOWHeeJ5S#%U=JSQ#e z5d8i!dwKeBeKuX8$4dk(<>?{#;s`Lri0Di->b^c0K0FA?Ix3HaT4Iqb{sm!nGVpwzl=UVF zHbyHX6|yRdui2Jcwi8cIah5=kUeOQgSz4uEPKPHP0&v^q{>fVju@W?4RcE9(A|rem zZU&_nOl*thB9!do4(*0o0drD1jlzGzW@Y;JVPXfAge=nnC6>}k*O68pn9;e%m@q=i zB`cml`f6u|%hHid^#F7Qn|;3@%du~W&fZxriaky!+)wUjJX%`PCT0{}WgJ5+gZ{d# zyqhP)kG0lZ5=hU_rzXTnjmYu<>X-OZlYqO*DlBKX(K1=}HG9-f9Jo{jy=oY6CIDPA zkhiSFb?b_=da}7{D3deM?ADx%T^iozv&l)wGA5#tHE-ig6_S`lw*{$G%vx^=&oM)t9jfX}E!2;+$GwUBsL1Cz#%|99t@OyyC+R zLFv?C7;}tDil)0cnfe?pTp3oAQVs1i{!3;JVAaWgd~cLIPWr`G`RSfJ&IWtex(SjSFn zds8OdwN}w>a^C9dbB=69>$;XwD_NGj%;EXxDKfs>1ozZ0f(dCDOv&~#KBG)gKV62| zOg+%en#kW8yEqzJ1}eo@gjTpl;5!T9U73|mwhMNEJ-qc*1sVdaJghkM;0Ty32Eg5h z?7I0C%HQ+TxCpQ{3AhA)xrYNIzvYIWTQrcf*uB0sEY(v!xCOPFrgz_@TG95yZSJLfoL+8@<-T$ag^RnXz5W8` z3zE4m_*QzBLLHVPGuyD#knO;mWg9zGreEanaw@1lI|T9VzG39G-sGJfW}Q)ZuN=f6 z$9(uhUtWohpBXa_HDnX}UOK_xt8rB4yNp;R+bR;TSVZ;OqT61BH80>?ksIR&;nRmY zR1Wx&CP6)@F+L?WPDQr^t}FWx#IC9PsfR;jI#$dcjcy64#;24qPA|2KiQB6({)p4i z-f|`}y^29ldwZ95YhpkrA5CpP8hJet2+#9>vo02}IIUB)5u%;Ggn);6G0egCvbbp` zY$l9wj#j_!a^CzhTZU-$+J4;S2@ezJFxPl3NSo$v>+Hh(fHi34>i@&IW~2WPC<+79 ze^+(6qxtX7#D@6q&h!B}T^~6DPY%n`7ewX#n>@Z=;Y@YMePo;R{}GuX}pjY zQkK+8RgXEx7t_S~TG->(5M5m)DOEN^)Y4WO^jip^kHBO8Yyt$TNZ<1>=hrU7=nVHo(wSqhiE2qDS$&7GoI!-)&4NJ*%CFIp z8)f&0cjKf{kPrc>L!4Z>y0UzngnC8*(t$&zTweu!pv9KG^*WYXhK!c&eU~jbjEDS3 z?B1ywa`O(a2oHpefOXoiqaj(urD_OC4cNJWfk45$B5t|$D+g6Bv*@Mjef0dMjCZko zdFA0mwKMAw3fS|%X5IyHcS}?;wa+0f?@l#JE5d_Q5<+zfQi$=3hzhhxc^6UMBWdoM z?}(T6=z82)t_FUUzTfm&cNGl{o&4AZ>#3cn0!N@m?j1Q`p}6Z@Pt5%v@2cQsjP<$T z%s?4_MRS9}9@K%^-~@VWz^3lv7n3C&*!!+URzNqgzL5T0SO`G2X86F>jh8TcUi48u z6hz^bNz4zfvdN~8Enl);=B963;CtYtkZgQc?ck+<4#sP9@c&)f;Gk?tj6oI}`j+2V z&50}pW>a-+qYc;`&NuqBF64scw)nlswD~)AerIbtW=eB#Dx1xBXRi(J=-D zId}_QInJm(dc89imLvBbeISma;=U_+7jBo~hP8L(pMNat6EY3>#n*t9^C8@wSwE>6PS|0^g z{^ZQK6}0~zee-KrI~F$7eT*ZFfjLfX3qBu=>=n!G z9XxFH1o8;#H_5(d$#-ZFtT%HD3t1Q~URbM-$h_k2r)#r)g)e_|sf9v5MJfbtcbTT- z7wfq*sfjioR8txLp2ScWeLR}lt_uWl9z~-ai)Wi1Fb0aCujH*zTp3<7u&^0JWc*+a z9e$j-XZV&c|DiTch;OjsXsgIvF^ZdoZg#aur-&NQ4BF&?+nkD1(j>XY6n!G{o_qRhdZS$&HS&zhk#+gX=N_`edQGAO{l22Fs(q(6 z6wpP!7z$`3o_+3&|AVPj*e(rrOo%#Jn+TiocC+h^2pqz4n}DF}5Ei@-&IP!fd5wi| zmVE3?>Ld=98GKNbM_zs^z|`o#KXdJt+gN3$q1fMt3>w!VFknPSu?%1$uQU7$#k;zEJC zR&P%6tf{p0GGJb}mc8z|0?Kl$6ohA}U=vz#ryur$l2NvscC{7Y${jxBYsF0p)QhM*)rLtK-Q(!SgpKB`e4y=oj-IMM9uMVq{HzCcqdSi^GvG6|P*4|rax@;Q zl|Eb=2gNm=6A0QK?9;U%|Isa>Qk7Y5WYOeVwQreYqo9&MSE&3;ftUa#VbxSgXAfz? zT5_aV*x}G6R(7Je1E1M+TYy1Z;E-HFgJpu1iEP?|gH;{gvX`}?mUH^@u6gdIFQMzs zb%jY+^1=ZEJ9s26v&7pfq@=G<%l4ES`p#nm!qy61Yw5D*pG1g=;LtyTe^|_H|6=@+ zf?Wf(@8rIAoMS68I$2zE4s(!ARrF0cz?_Yz!xC~>!}SQ0JIF_-e*TfNz^5q6t{^o5 zqGW&}TA;fz?KJ70vaYCzb|RjuR{a5Bu9Mf_L~b0_PJOKH0Ge$2%C5py$QO&iJueJt zF;84YyR|q;@Ld@+g5M0zzNOV%vwAD7DwuM`wrgGAD5XN(SG{r@`CIBS7ZrK!9fn%i zFqnAx-Z`jMaJ){a()R$WMbwX%cYVaANpvr}_Wh$pWCLnl$G9^MT#O`KDRMQ+D!!KG z?&0gZyY3_McQLXgWhv@vY-;Vz-ZN-)8-T0#qRU?V&`hNQUe)3=X zhr<-Aq7#8F5zz8|cYj`nI8~gV#`wlN0evt$b(P4u_&^w(!wc9!c@hpkZ{+8r)}Qxa z|0ANv(l49*&{jX4e0)R)6ilEZeQnqLe%{8A<%S(kntxXOp8R@#+&^xW{^)=xZR#{L zO4~cU&*jN|1H+6oJD^i!AiMvAXQpoDey$2kwRg<)lSyppYg-iIi;7JpH=%A%+}cRtiKR z5yAvsA()(Av04HF%0kq+UGkFz-`U}#st-%atj1ZpM3u^+SPOB=Vf~1c9tK zX@RLy=XPoK3M^ca*Wkyt@EIa9VqlOyy*!pzXZOS}g+Xjj>^U{1@3IXM0o z7VHHi%^3hjc~B}@h{T|Ttl5$m>aESx>mWjZVzrzWn#C`;ay`$!hMLF8#X_9@8G>qg zAPq8i02;_}Lu;6Z*Z5ldXG0Ag@(rtBLY(fbi! zVj|lS0=7I2@`NTx759~3LM6d@rwDb$<|bJ?@o!b!^{lG}7K4C)&Ol>p~pZNIto?q)63G{)7qzKE(XvyUkL|TU)rRbWyOOc)%QkGbK zNe#q$jr-IN)co87$oRIxq;6y$^*!Db;;j-B3`y~mUTtud)maaPUER@B*{8V zY^|5BjXHyV&BtsrK2bQ6N#z`8ykouj$t6!TR%Rj_BnZal!+v>;(fpLCdRu$aDdk5k zds@lIJ|W7~`9*#r_;XZC9ow`4^c_sFfb$>GJxUh4j&n#Qg{j-hyH@lJK`(;inAojS z(LV9dbfl5%I_&pVJ*qY)TAO|iz?o>|R3o@!E(d;=T)9C+H5Rs(rxvB0l%lfOGfz;S zdIDU^K1{|-bE=&td!lj5t@Cl(w>*Z+3W?`HnX(V8K?;3FU_uVVQ+lxq@nK;MQ<$s2 zKYW&RDkcx_6v(@Ke8D14)>f!Z{aCnMTTF zo;9#VGghk)K@Cn&^)9GskQzYetV3G>dmb(#S&llh<8S?mt$`07IAs{4Cd9s0d}A6i1UATX4VqtZq4n}tFR zdFiy!z1yIo_~G7#eP^*go1_p5P;aPkQaB<98#FGqok(Y}~dkr5kcM+H@pzgXcmJp0$)w&v*{I5)R6SPWrtKSa)5i0qcBQ~9d18Q@| z=9}n3HH4Fnso}MH4eP>m^;z!Wba$N}5WCqu2Ll_AVRnC%O_X+*ySw8GOHPcO{P5h( zeufrpKS6U9BhgZaV$km-dvfMK3ExBbIDMMp`GQ!CR2C zJD(#H0W@cBUeT>ro`cP(m>j)<2}fWI=s>}?2K`swWKDRfGa`b$l)~Tzb{|iht&^B6 zZ5+4Kr==fKsvzkkYaOJm zDpOYMD)}(YKcKVrj%w<0E}1em)=+>8YxdZ;Fu7BsR@TJ|u|H&V}0{ zd#mWQqOIH8S6B90!7AvN4fDjtJnJOrB>`U1B#WU{u*a4$DRevav$R7u+i_DHf;`=_ z_BR&Kt8y0dB$F^IJaN_miFDcT~AW>yI)oYCtdt~B#gO9^;*Trwk_%vc0<>rBKvMoj!^`2 zuH7hs%Eo1qU`SFGkjZ;L@-6+T7e0(e{X)nibYDEa=7yi7+UPG%u}c!Cq4?v( z^jV`YW~UD>_RSmp5(m+TEab&Jt?m?<^nDUWEOU_ps>Hc%HoNj^qb7idIRPtaRAO6G zN4s#zrRz!Y*oG`6Q=gJO@Lf3!1b%+*f8QUywwDOX_>rrs-Me>c@rZ@K`tbVYy14|< z?}wBBt3RAZzp@AZ)&98GJ0qe3;$zN)z83+Qi7u_KHjVv`(N#Fi z&AHhrjaOg_YAs`Bx8XWB!HK?Mum&qjM85q+1{)RsD3iE`Jbbl{)s}gfj}?px$*(~S zI^^XgN--N_7%UvB$hO8Mn`3>-Wfi)h8E4XgYpZ4pKJ}t%9~)C^wes*h`m-+F25EQC zj@_%X<#fUz`v#GmR2cTLU>mL^{kyPEq7fW@8s`2d%h(MJPrR`UH!t4!mD!qX1NoCI z(VAB~kT*sCZ*HnQSvv&3Nzw3}YVgal05sm;8_o%|=d|KAqBFYLTCL!z>6_s+ZjzGl z&}2$k*ilHS6j=sAHsl7rLbuH zZ(blrF-#_BppTz-LZ8H>FZ|+PKsEp2@xl5}5B)!Wz5l;N3kG_6hW}&cV`Ka8aHIc; zv_KI<`WI=ju;?@4V=uQR)wfI`NO&;*hl3MLxRcAcprr?abTn$!O8EPWhviaZ%N?C{ zmxVFHe={R9_u`_mEcfDEJ6#B-qaF;&MF2GIP!J*WL+g#?N)X<}w-Vbx&ivCZ`BZ!ng9w~8k^B5697z7xe44f9ZATkqrkm>qc3HR-!Z zkSSsoHV&##GB$!!g2b-~?ZC57TX@A2H?4TiJ}Uvu$9u^@wuv$Ya&iNRcy@BOL9R$J zj9WPr_{^5IpdYE{`+X-H0Mj7K@`)P*eoKio2pD37xFAXI7%$Sw?s^q=fvV4*kI%oU` zS*E}RdW%B&a#+-{e21Q6P%hxxW*+$wbD;S`D%D59^4!cA$?|##hH{0QG>U?loqA1K zkSNcY1U|-#FH2xB@X!`!CJh@YMD<=$94B+8PNF^-+`l;7lrGl+3U3%y$`lp$7j%(wHVuVtDu-XSquHJVug=c778~qpJ=mlzI6qHutMPYnj%*2Q_7vJ}K&&T6XyO*~s zYlaIQ9fIk%)h*yEZvKlo123km4%wgJ+U@5e*M+aI^gRy!XlTPqmZlLh9029?&#oJ; zZ)_Y4`_eTAJk)pPo6()=EI0T|SX@jgkyKgHHdOfIFVSaP0;>31_zFh!{4~9wD%KzI zuh0=utm4v;=H?ljc|!)hN8wbg%QWskEhpC7h;|_3!l5<;Fosbl5$ViWgoy_5I6_$1 zr(3M-4=f^sZ2RRV!%`c8WbLCTWHSya5&%uKnh9AoolXP2EOjJRG5{ zb}Mtw2h!zss+svOZjKyjJzosm*q}Gif`7e=GowpQ{f~J+pUi)ckFA-pAv5*dIXSWp zaODQPPP8vXUQxjMrCjKWq*<|y??|u5e4fg^cyn-iaprX0=JL3&bz}HuUg~K29~W+o zFq~Mi^JZpq3a7=~8F=%wrGJf`I;|e2`QqZ|MEhoXU!a%f6BMxD9KBQI3ZIL)IMnzG z%$*un`F+h^=Gwlac(%Gwj1!c@{$&F-^nlB!2iFAq1B%as>YpTg$qw>~2ung*`jvzI zXN5;M+LxUxBl{1#uh;$b&*z;h>tFltxZ1y8#xF021bDK$Znw0%e(O9~epkM@GrQk^ zhpsTanRrG8N8HMG2F?NbT)Zbn9Ne6h8?lbKWXcY-&cj978KUp|Z~ETUVi{eJ=LWA^ zSAZvDS4Q63UAfrNG7Ny7SB!~UT?FLeY-ztSNoSo1bs(_#{bopUupYlsn)0-E!mo*l zaG(q<_boKa($;V+I6_!v;SplN03bGScFL*5XlE=?G%$1XLFnJD)8WrW{R#Ob7EymtEQx9g|RcNP3vEH#v0-cFSqVf+63onNOGJ=i4Bm!a_zaE5PAJs}i6;;-^ zH>lQM_1y|-T`WlD#f3!fuQIgtXd#LOE>c8pexPhA5ZDPsMc5R*o{WUiybC$z_q$M^ z(C7ya$R07q#%7oGH8BVtWHA?1>k0&x8TF@pBKh}QXST)Te7oMx($$P3Z0f;C2b(CF z7ljX{YBJgVp&b6FKM^U%^OEjg?RQCa8m}Gt`d5~y<5GJe&l8L-TbDo+10`-&+L306 zzkqL4v+3(2!Mqi+Ar_bZL#=|pp!F3>@v>{Zt{QFvCS_%9yf1}ZYR2w(%9}hsLU*9}`x}V-ul<4~& z=BQ?rvbya3lvJ^}*}~aA(wp&exI-?<@y71q5Kf4anH`-Q&IPbJ zffk6E{YX2XL(2O;nZFx+92}W@GIFxx=J}mK))TlF`m}y6zEN$_*-WI?J3h??=&dQ6 zv+^%sWx_EUdBDpQpj~pB!bpbMb^Gch`I{s@@}$LdrNL0ONrs%~NQ!i+Qij?jur9-4 zy9!CO?ycS3qTKk{%O)F_O`f}wPzC-=%Q@sXLpVmGdT3SF|b01q5H7tm*xRncW9 z64Cq#C2u;@%Bsi+AjmAP@t*3eK8PU9{N)@+k@!v~8}>@l1+Bb5x}prrIHXBR$;L~n z@eRY*Ww&|^spb6L0nWGVcZZ7v%k;_J@Yz0~Cr8ak+8|EdB~8so=0Gt|a7Qpsa5h>^ zeZG=baEKqNjAv@XnHxK1hjwg1K0Cq+AV2xhMK#;wmw7HgGgIfy=*__Ka^TIAQOGrO zlB>VDiLg0P!Yn|4K^BQdz)@i#NGQU`7IKN%PPK{0SQL|o#oVA3^?==}PZv&Tr7tW- zQ_{5wZUvcFaA!Ep#C&f!NMo#rrdaDuHdzjUl-&3YfgaXm!f>$6VkfQxZId~U>QWMj z6yL`t7oM`iBl8U5@oZ$NM_jjtiUv^WemUpNB*+}LftMkcDYmpScO2-Ov@%CxEDh&T zmW2tluX29SX{Gz5-jnD2qTlPLR>TbEgt9>leVDXxO1;R*F4@jw08s@O{d#H&>p*n| zYdgmb&qxd;Q&rZrFB0zjE&py?fxn2e$Yd5Xv-z5uD;f9%XpBk1>v;ZK4ia1Ii`P+* zjs46)Iwcu~?^~_=!!duyTTkCEw;QU~gHJ!4yVcc8c;xQ{@CEXV5O1*@_r$l9fD-++E6~=$l z7NQyO@&ifg-aq~ymS;Am|3Db9GW~avZzEb$u|{kNJ8S>C7bFwNFThdYl6S6wnzHg; z1yqBGtEfqT`Y3ebS{{674&m7hnp zQ0k)cvHj;{eeCi>&wYRW_>2uKnj{KVnCykY0tKwJnu)4L?@ ztz3HB6AL|Qqc^TQuQu}Zkx*<~T=J5&VUg=pAI$^N57mY5gc=lVNZwh_1N-M5Dog7@F1|it33gour9CrPz=bl-hlMcSZBOsD zIm&LkuFf_^(oS(wS`vf_1uTx~{_1$Lp|Tfqlw}H4__VA8x2P16NzNaU-zEdC!~%G9 zXyJ^t0{;tdx&SQKTC{4h9X7%*YWZ#~S1m_klH^sb{YGEN*~Bd?#R!u?#6K8rGx;V& zZGw=SjMthB@3voI(H%ji3|)Q7=|FMt*v)yr9h|OZcnG_-3#qUfg2eDxHvrL;Y_uV@ zT|v$Wd%_cgEv|H*WR)kY4i6?*y7QD!b;ONiXz6hk-`$mwRix-tZ+09+=nE(6-M^!h%I{YfQ@(JE#=N3{x6af zgmcUr8o7zm$wsda_jpF`f~S+C}%ISXKL$aP0>I{_gq%II8q5Bd0SkCl+3K zP~2iob7H5}ZHbmq-MTW(p=g@y3)9yVn2gIqS6e|Hx#s+dN)@40%TbSbdWD4MAsV?7u<1)wj4`NTi#_Nqk*4LW#t!XQK&$c1THfNIJvqCE@6g zTD$eR(}l>0nS;R=`pS{NN5s`*mQN>wz>tUV8c#b;NrS`H)YF^a2jN2(#S~d)F;qGt*7PuG{j&Fb%dj89>U;GHa}%eu=V7)R7W|`5vMK7?R6_6 zEM}T>mj~?Rlms^D7wJJCbW!ywiO}kvmyeeO)013LX2o<3aeV+jse=75ta2Xe_!dXU zGU~14O3#5fnCd(*nCwl180;b6=E9h7?mG>|66C;BkW}^fLO_lk(wU=x4!INQiaEi3 zB<}}4jtc*)!CNEodWiq|P+kn2a*2Pu;?$Vh|o;D$Z?zS^akJZDWim0`T zG}=|Mcp}I89DBle2#rc}7m@B7muQzW9I`rRT{JJwz!f5+6{g6P!?HZ8|DO+=Ra|g0 z#ZHM%bVcSwZ3hf9?bzapPI(TmzsA4m?q|$QRvjSuy}*jGiO+F*K*$i)6Sd9_KyIj2 zLZIQ31+~Gf(b#Qv)Mcr@{aC6s6gk_9U|tfjV!2M4k}20E8aODR8+Xv!x}2G_18CDv zk(te5Qa18T?YAjY2*2MLdN+V`jS$jKc>#I1khxC9E*NHjv)c;X4y`=C_Ay;EPbEuEQsy8kWewK$2E6s@MgbGZgAh{n z@fwMg^4|J}#f|_YgZIZRcooCG9&9CgTmx_eE>12PnS6r*k=+c+C779mik^+0v+7A7 z&5S9`bYn~BrZik4F~n|GMON^JJ z6Qf{UVp^h}1cG9;3Koab*%o45%y)w$Y+A+~DHO$JN0KjM%kP~0FF#WaygH5X`BQdK%m68&gP%8NIbvBLxaj zLMZhlFfUCm*`Q7;&qLNRtPZD-?W9#{FNOt_eaP|KzXH-CnSf@&Cb*$6=n$w0k^2=Z zBaGt2rbNy|`x{4JCj;^Wps6w)_3^z!u}%e9O6q2=RzfeYLDxH0f#F&(kF%=Ewrt^8 zkOB6g3W7QsldNYG>I}9`t;+b7#^h3bQ}J7^(r8Vk_4l;AC}ph^4sZQ*HCFbBmVkzs z3)%^|;u_^zHAoL79=7SMsy_ZyY+u8Io7 zGW|vei?pFO+66#Qc4yWb@4j%=(IyD9G*RqBA3b_f@@Wub(&$I>A1gr@PYLFd1+lyc zn^l^ce_Dq{Ngdw;;gNiE{n4~QU#(}|p+mB|h)7o!mX?qWpQ;)oZ;6Tiq%Cd@yep=b^HJ7$=lKcm#mupuL4JHaZS zwwBc4`M0iZ6*9$zC|BCQ~q-Ue{ zXoIH>%SPv%_)X?Ki#a0x3Gj}yy-i5H{OS2oy|xh43b)v_LsOu>_RTg`_AXPjBWE30 zrph}N{^@gfvptX|aROUgZXMZ-sU3Q~Zmpw`M-zTOA^!=QR#IZ+s$dkbV{G7;Bm%V8 ztqq=PRwnJ%>YnPhSGK2e0+F7vLG+*S53sHbpX-i`Bbg$xA>A$C5=fX=?9aA1Mb=Kk z@L0YH9DN)KRh26Ig?)oX7dL}SJ4z=}M|^*j82;>wX{9O<4krgbQ+(D+wPZ}F|$JoB0lHm*XNilx=9NR>o-=`cU{@(j$cH@A=K7l zDCE?hVKv;;zgkRmE<8g&R@DURCEw2v24|kV-dIug}dmKM15Wh?Y-m1xRK91@Tm+A0oozJ2M}y#0t;S}Ik~|v1LEGo8QDQckL^P-tgz3JxsI*wXBT}%M z8qD}i{7qIujknr0n7pqR@o8)J~HlsGR!Zx?Lcm9z>9jczyF^ZwhJ3(V5ROu5WHMO%)c#C&g-(6LD4B`+XeDIShz z)!>nS3Xel286%G4P;{(4c`V%r|62}HDM=q9(Sy8$x^!^I1gsTTSOW8?oayS@*s7lZ zhaC+YeV&9%1J+Rwc7w_dNV+;3`U?R_7*%MC%fGirU##C+8OkWPcOpaW3WEHPL)plQ zEq^?^4&RZI8z}Xk2lg%aX?H}XqNLE;RSCV(rA3FxH(M!8sKjyY?YIe6Nhv0qq?jVw zrX1ahfpP5Btk}OzSCIoEH!!bhZBjRNij%craWZA7-;J^vIxPJ!8ds&Axh)=E<|5Ss5-QMFw|~+JI_*lorq?>|g!o?D~ucH3D-Po|Se4N*3={ ztV=o1;=Ml}ECtz+)KK}&I0KwoTMZs1yFn_tbll7wKxpe0-;ghjk$@O(JWMBE8c()- zR2g~Mmmwcz)BM(0b2>9skYV)gH^mD?0l~ZyqunTrVc!wP$7^Y#21Nq-cM0htDR}LE z#=!UmDyI;>a8r6Dm?g*sIKlX&zr{FZvYmm3h7C$|K1qheT_7(^ydj2#WnWazkc^T2 zJDP6R4dWg@@I(Cl>7Z-|>7MGfCKAX@i5@n9?n5+gXWefZ1Qx1sS}&lub+03Egv6f2 zxB9%NUKC>ihC4#*K6LPjg`m4=z1^sQ{)uxqJ*U-oN2KtrH)jZ9R9JSC;^bU~#Ux_l z_b;m2HPz-itAb%2`9r65JKN3YwXHwoiO2)n<uT@y@bS)Ojv`Taf4Lvp-#{UK`2!uzraCbCIrCIlSlTKuYylhm)x+S4*c8 z$WbjtqfWUPV!LEZRDO!Q8v%@?t$5S5Sx;V7_6%j(K<4Pc(K!Z1In1}r5sKK7`aU(j zYd>0)46kbLG6)Y+^NK!uyX1MA)XLS0j*nKDMKv<>5*03Mcxlz{D9GBy-Eg(Hb0vdC zle4_xdU7QdFUOV$V_jLu@!iDJ5JSE`I8f)>~&O z=jsh5cckHNJ6aB=criq<{psy>>J~C1BV{n_j%E8pZ;meP2O-6UxF7~Ux)p>N?&p&| z7!szLe)U)QU=Wt?HsWFy-Pz_s(%QL47cN{|2)cS)HRjdTe`kXzw@8QkJn2#p< zL=iM)PW4?oGn9>71(%6BJJmu7oPcIc_C=`?ueH=AV?|9Fqe>tza>Ohe710QeNwGLv z*;!l|UGFL&GNtmh2^dKPYRgALO|!{m4$-6ZRvIf_=HxEo@8Mn}z0&Xt$(b90nw%70 zP>m$z3;WQXBUkJ<7;4`XoC`U0_qM5o4|ZRX>JRYS8Hh_!tj&E3P$`g@_L{@chu*Z zBj-FBgsQ#pLBfeJO}_X94=GOq@3hKsqwK^!xxGNbBFi4r?SF;E6B%sqM-J(}swxl? zkbIVwnMcVn=a)wf=5atJL&h@rV{5Qu%%&jRNz8B)Mik+JPDq2p_NOB9jQQ_Fh>0j9 zat?edv-u$nRq2GQ+9{gKtO>Xj|nZ;uOS2<-mcEb7yu-@ zGuISaKKpXP+-Ke~_n#evCQWj)t`!wcnk?jAV{1B%A{kzxw9zA%iA^U8#h8)274eqZ zmhl8hg*nKnPh$pmr%eF)0j9GYrkC|Q2xnDp9<+(ccEjR$pW*xt$9=bG+L!jq;zW$9 z5A26qWm6?QagOck#o#+Ny)o>9ZIYIItk&PSpO3`*b(?m{F%IC(t05WS7ZGuQE5H zEY`z;eTZ|ue%pfUmpNF=lf~*FM`fl!ZmD?>dHT0-Zkk%N45Hp?JEHX=*`c)ZSihh~IQ1uM^`&n`4F+8P zf=Xm64(*4%Z5L`P(wonanB$YuQ*3xW35H@OCp_h5%?i;=sxAs{udEr>=xFGs(kEwu ztc6NspivO6DofC+&DM-&vDM6hGx6&2rnQf`w^YBa%B7^8xFk1C0}!2GozlxtwCLIb zetHAq*swc;P>?@wa_}WEtm)EPc@BrkY5S5Y4vG)fqSz)t`O=`T!dw23!A?g(X?aSI z0jC$sOd_NieM17vAYspA)?<6N%@oxsAcH@2!VTpG=JjNWs-8vH4x#r;GA+-V9F-$r z@kKD$Xt=fSqV$lf<@XC$S;5vwLT6bfY@PYoji}Y6qeLV7%dhG8@Ngm=?)b-N4|HJY z)d9U^H`K(+^Bfg4^S}3t&(h zX=1Ua>sl#%A+eguNrSIK9dv4};yy_mu3qTzY%>i!?r19rTU!C<^8xo8WxtTbHTve8 zf&f)+Cz9=pf}rQ*)?=M~w;5@Ft@USK5-b^Ib(xj!T%iK>HA6G1Ne%wa*P;aaXFoqT zjcf2P4TVt_y0n}}27MY~q50u*tc~u^&dTJDEwF0aFC~p-*5fkPQZCmQ#|&+~CGuXK zsRXftC&llvZ`6YJ($(48f^@8H*ZaXjX70zTzg9~GZ1`A}{ye!wZGdJ11@m)Xg>p?6 zcRm*JtW5{DK9?&mZr8!>tUXuY0MOZ=;p2Ds|Fj6O{l6-4{_p;2HunF{Wx0Yq6^qSr zb5mE2Utb9M41zVAif4wB}jZ{R@ zlGhva?e5_2)7Aa8QonxM!r=Js#RKsz@aQM-D1RXcH4u{|w9RgaFONM9f^Y5(cs6A) zZe$Ok@AL-oZO?)FgK-A+~v5yv?ck+00J=gVVVnSLl*c#jysgxs#(@w91#OQ6n4Vwx zxR0+FZfCp>ALcfZiZuDU;`i-P88TU9I1`?}cuqbm5frM2s}%Q?K8n64bpRjk8Jc+C zAKp=7NE)mwtHor0NyoylX+1fyA(HP!rVd>?qAE;`4k1yK5T$9YhGHX_>r@;60?CdtT1lAnT)wXa78xm&7wEvq+T@^-^`YjC8k8M>@||dw zlH}(cO&2_JiM1L`hLNRpG-T2Z9-_^a60P}7x(LSu?X$2z-^O_~wxZ?ENkA>Uc-5?} zWi%x*n2k4t{^-maPx2(ymec1$-Q31oQ>+S;3RMT&ycTLWpacSEqj3L@CP0}OLQeJw zRfRM+Q?w`+&P9Ue(14>}cmOmC1XBw1XYb-?tBD>~55L#j0g zf^SRtgj!60%OU`*{B9-j4ezrS)Q?JbroV>A;g`QMu62m1dNM^@sp~O;DWW>(tDgK6 zo1G=2OT5PspxpeEl(dfPjkwAZgq~{zHH*#W>yh5ED$q04Q94rwQ>X@(I%5? z?c-*1WoDyX20LWnN`^h?&?4jNWFvk5AJfitdeCVu;WuX{RRnnUmblwNBvDGj=$rj8NXRL0|Wt(}+colLGCL$8N+wW7=#w7V^R7^dAH5=#TP9Vbc`;e)OgmI~3 z;TBnTkqY$La*;U?kDAXOVjp7o@s8vG@tc>6mh^0bGCW!wN@%%HsT{ZL9NZ##7%2_+ zN|DUvUBSZcqduvOC0g?R)7pHG!>xanOc5Ri66e_%)~2Ff>k|ahgu_USLot(_kJ}hR z<9c}A%cPsjoy=`%FRW0x4mZrF?BcY?u&VYI(18D19X6`IX<9lY4_O^y6U=FBj(gO* zb!WAOk=j=j34)*0PQE2-bazb1{RN=i3k6$`UI5rX=!BkO`UT=Udqe1=BGVX0)IL@4 zf?$|WK1&XK<%t5GMX6X@W}>m-)`QVZg!1`=P`3yi_1 zf?BeeOA)k!$N>p3+*U(R;I#!Waw*tnhQcX@#D(6w^7agPkD4WbzF{q<6>^veH;M8S zNE>AP_`Zuw_UskFF1!A9M4DjqkBbp+1yHg&s&?a;E*W1}oh2>KCE<a9nRY$6j6uRPT;qtSiQlAgHY9uB!42 z-)#9Vju#6j>e^Z%>9?%OU~X3*Gt~ynseDY!Y&Q|sRc&6ILMZ8SzW7W3qUL5ili@PC zwvMnLjYCOI0}@wcTbO*h ze!{%PKx@Vij`c*xIUbZ6 z6Gc{{JN4uM!`zXZantx+$*|&03cQkFdPpwW_+i-}^T8y);bB6wPgmm_Qs_iKcg@TJ zYUpp>6Av_!KR5{&`KbBOY1!>MIoaAeO4`b;tnHO@G(!~w8_eU`%@;LCG9FEi&8+Q{ zjUPuf;B1qkKI}%tLS`55ER`z`e&x5hlU~ZVQ*&89ZKdeK%B(d;l#H*(RHYF6z^=>5 zK%HJLaxZ}UU%`lN2)|lv7Ig-c?&Z`G+6g*9gGc_m;YcR)6eNexX;rYd>qF(FvFjtj z+vc`sxuo$p;2{tAit8zWAJ|Wmv&G*F3OOHRV_16`MFv?rXB}Nt zJlr|GzE{4hxM+Y^irJKYG8nLVx(N0G8$T}uICWY`uV$EDvO-1J#{wLPnu|3Qvmwnh z^?v30iNZBtWIq)qr&P+KaBY0V^V%41->z}!sHPJNC`TWr#~a;j^ca_%Sy4uJq5(fM zlL-D&O;Ov^U5E|-*2GzjSobD>lu`H0bl1^6m7kUQh$c!FyG-&Qnf5;0m`xs zJ;>r^`O}62I8Rr-iGPZo9+cW&@WmC;MfYpqGhV-cMNq5g148#sjYMo!@VM@Rc37tq zdG_TkO2|yV)Hc6ny~JrsPkVm4#|@9JMO|*~VquxxK6jL|rhZ8dwXFA4BL5)AKlfa` z#&+<-tDn)_RKeFTH)Slg9!`pVAoG6Cn?+VG2o_Z68=#)O$W9^x=O7~6nD)k`_B7K; zy_rLOg0(*(TD$c@yDO(Hn<2zW6yTGJ+|VoF!e_B(NLCNp&-m5lp7n`KvcRa)r!*tu z^4Mnkio+z?V|hWGwH2Yn{t#rfZEono1_%Y?BIx?d8ay*RJA+4;QEfgC?RI(O z2r#k`WiNQ6Ec-JtN#u*QWX>1RU9Pa|KPhIm|NC`@ftm5YL*z7LOxhf^-R3ABZ-S!uU|9cRSF|VDi3=oI=s`5pC8+O zd%QX^)49V}-Fv*hdn>#O9QYF3&#jMB5@*RTuIeuG;uI~x)H3Se71O)9e`5c$krgfc zD?k<`_bO7pI3G9wj|g@Xu-d#8&5OO*$(6Fxxd@*GG>NuwEc^5M{t`%Jz^iSoR;+}n zubq_z>hDHb9JWkQ?3bhwj=BKU# z>Z*sX$||_ey%5!OLE_|*c&GmEo!?2@SWT4`d4}+C{>;F|?aTdXk0z|=jnuz(zF8~i z0Wbk^dWh82m+JfN`R?<|MPSX0zvlvZp4Hs#m0d^XVXC|WmSCG=ejtOmnmS;7j1Q0% z4$G(Xw42LYqJK0wITaBpAkJM=l5=0v{EmmHs4x~JxEaul`Ig{B5~Q5dg(_2SpIo$T zjw+AnF})cll{DanRzEhm*&f3mq=)i2=6^VqksLf8Rgc-;UoYaxVvoPtq^Z6rxH9X* zoP@vM(xkz9Z>-6%VFte}U`nLXp2+bABFlON*<=ham2hP?a7lj=T;4{oU*SlWUqjALi5!znMad?8F z3uLG+&EG~5Bm47plblY6%oc^I?CFUg{FiiL{=94PoR`Av=haZWmiQ7@?D}g$c>$OU z_uyp577oG?tjanvnS2p00F3jTe4|3+iQr|Uhgh?DV-X>_(uIcEnw(4UNVt(%H-;pnt=xms(f8f8^`&>e(a$x{now*18mOxLDUi zaan4G%w${<;lt?>I?FMWZiVyma?3V~iVk#8i!xe2e7k8pU_jXOXdR~kiJP@S^4vhM zhNZT9r7@=d6lvqmGLi1F=gE?zR4dxne47LeT^Y)5*9clRd&>mYx5QbNtpvb9d#GZR z;DyM!E|lIA4`xLQwH~WHcTsyntve#HQn(kSa6xzw8$MvhY_Ju| zmhV)`eYK=0VXbB*&9DScz+&!55x;DPDjbPYBG1>T#hm{y302cT0ER!!v3@j4LEyx) z5?e1 zqti&Ez{VMD-CqebPVO0IucW}1B~*t8%>;LS*9*S4<|S#TlpyhKI=yH;jh;=nUd$F`I(78C~r z92W^^PSwxpwXYci52}8oLT?xM9g~fiUQ<7dMhk3&m1} z+Bw!5#0@dpo&5;p%%-elj`4+t(cHpr4_`rE01Jh2gt4pZ%F{!Q{)B8a?lFc26kN7GklJ%&0(6{f`Q5HaJXj4s{%*SOJV*r3F#h`4pM|z(P~-DD zUlBVWgIbta80(6hk~!6RDtD6suZSEr#Tv@GqZ=^DlDb zNnSe_)6}0qgxHz0R7h8L*Yel9&}#JcRvCrk?xK~w&@Ul4jFa}+Q@vxt$YLIzA!T<` zV7Q^yWHD7p?Lk&5-rJx`c^YGKux$u)oXauE}d1);VEhsu$GZJns06mqXfk1b~8tkSeT+Its z(w`brJ^)v2*d%v99~pZVD#UynFn^y$i3SKQ*5F?9D>XT!30CZGBsZleXS5$OLrwna z^ke`$QT=84Jc2qIgGALf8IL^ubo5Ngbd=FI5~S8M8lIP(#|VmFSN~~^3yAS1Pb2cf zY~jMuU8N_io=b~{QByo0rM7z7YN55w7_Dr{rw;gtZHmS@UyY0fLt=c)NY zJu`YA`nx65A#v!H^bpz%Q87ARjqbw5lWZ38ZEVsJAA+73A<_xwppLIS7=Gn5rHo$} zAV^Tz80Ba_K(S&BR^xTcPaVt1%IEOxd7hJVQwqJE17$y7+hq@>+)KNDROn(0f%*3O z+5U$KT4u8$0TEL@m&_kKW=C1D&oFUGCoJtGPm(#ifODv@P{uZcPW1uvH!Tx}*Gg29 zB@+vCH-rm=l)Glr(!dTt(sRuCqhNCvKHAyVk5<{Gv1tX|y+Ca)W(+CsIBlPvo5!S- z+@8x53om-E{B9+wyHHZB?^X7_7CVoNNgpx;;ba2SbYW!1BNGA_6!R|v6O(X??b0Ro z$%UtSKA*yTgK*+)Fdf5I=W?kctUWlLcQbF~PZMr4Kly-Uc)~VmC*F*`)@FotCIlvK zG?}4rUl&5P(30ZHL&`ro=D2|e+Z^kx5WH~Qe+3=!Pd)K6i`a8og zJ9UjASV>dC(>VGTEjUv%3n%Bt_ zgRs&RA8w;Yl+b23J4Gw4k|QHF(DuHBI|T&LzSgb?5G?6>Y@YB%Jk3G&D|3U(C9{-C z+xOT7*V!?Xo?w*Cw`vQr&AhJqeCGQ4g@;x09e9dz#{6x0-8#R-c5|Q(C{Q0O* z>1^r4=J}#>Ur~6x)WiAp$Iw53;oc~N!h}SVD6;;N*8h==4xe;+3;!TDl!W&Egz;uV9e@gcSk5&{Qo%Zc$gJ12s{ zDp2}jLmthT+pG@PVT?Yd!=cfa&Nn@B*0B%(Ga%PY!SJTOAB1gFX7{wKwt;zXP^=hG zD0t1oJ*r>1(Suxo>tCvFnTrysk;Acha?t*XKrDH0M}5-0-1#l>@X6g_hx0=RH||F5 z&RKne2$37~ln}2462_kr3Xhv0`&3D}Kc`*V{YFbC2Uq zn~^C}j|`8%D9W;48165kraiZeD_=!R8)b_Hm+d;4xziMdZhNXzhAwI+eg_uG;$r>f z-33~+f5de(1epQ*AhXoaZ%T*FniJc3JJ@7QA0$Arxo8_L7yA*DK#ph30)Ob4p*Ea8 zylHTOjf=ZMIZDJ&^QOfr%Y@!sI=);!T|b_dw?b>dZG`0Xd~vjc_7TZrWD?J({E{Rs z-+kT}6t5THs~yW%v6Ugv&8Xzz!%2vXi4j_+O{7zr@#J6n*Cp@-TbLkVv!ybuh#d4w z3bx6(`54|}T{}vSEs^b_38G#Q?Ke!U9_6vbx9w;E`%8%3enDpGz)?RYY53HeqOI*` zJaPvx{eBoh_ZVHH?ohp0D1S~v$fDk{mxDitfJsxLx5^48kZQYA1(X;qxzQ6ybG@lx zEqk;_#(3&SU@9Bth1}>lLaeQFyXI@cSGeVmV5*UM#~?hjTQ&0KkGo{@c0dir5=hi< z>@AlEilco%o)36l7}W;_!fZ_8#~(KSw3)Xk!G-jd7M@I}2uskPkt+I|nxX($QF?3@ z5yP2$fP?1p@WI8$HvkSpAkVxbp)icg*c6S;wQnOC#^7`cQFdQQPX!$2TE3MLkWYi zcPZ!3d3IMYBx<#Ce-;<{PMnP+s%`S#=N6HKcz#UZkJm{FM z!EL-8s{%o`T-!HlPm5K0-LFhEK~ut84p&a@qJ{2Nj6^vg%;p|~%PjPw^S9~k(k^Df zqYoaAr~$2&)S9|}WNOmc1C=27nOFb^>jIxW-XBN*KT(KD$hOC8^SkYA(l?oYr2I^R zaD~NKoSc2#goBINziOjJwm}Vf3>t0iFV-KF8$8#I4JX#ExlblmrN-Y21TUN zHLo}s3Qsg3FlrW4Or%45bJpN?kt-Wp9|@UW3z6R;!k(&4(WBA;=@~VwXlcMcI()?@8*yHeG7@9WjF*;Bb|`cI=x&%q zymP%FpX`)V*rjHHtZY(6tVS53cGl5`qitj3VBC;mrfKe?BcTd&XCf^yv2UXCE&Vo0 z#Mi9hv@eBkweSV;Dw(%e9}m_>b}9qk1mv{>vQiZNK@$+)V9GiO)eXa_0E@QJE+#kL zI?+%KQ6RN+!Orm51_OVAqqb-aL05756r+bolu?7Fw0b>zT3{Jms^Gy$jWo4cU{ z56G>AXGSeObTd%ErY4RU7*RlGQB>-hx^z#45msR$jtSw&+I%n*W5y!2w1lb}5n0jL zokqMVpiV}DQW} z*I?fYV0DxXsSFHFd**1f9sId!NPLXeou?a|Yx-3-ih2gO2ba z!Td+2QZo?Z1bzl76*9OTrwI)Mnqp(ZC&n&ggz^=+k|`SV14Z-BZ~<|RloMv(sykDg zCgo*i8!Ry81hDy!N8Ze5#h5uL*g$_8oW2h1r71g>^*{^;mW+t-pfe3IYcsdMFYEJbZ3_ta_~@ zDN52RSyQ#_g=wc@L$+}Dh>HBt5J_t-2?%=kl#dRp-fD=Oe;x$sv5UzS)~P);FL61)rj53g07mnPE6Pd+ z7W?a$#l{;5dB5pPf|9UrN5zt$HBozmkm$;`xdf=j1(+y~YLVo~rL!KewIxQt2cv@| z2_-<(cB(1#2%>N5pTT{goA2sqgZAV$^H7pqe7hM?HIjO2Q&QHZqcc4>nqSN*gvJYu zYvhQ23pbwXOsSIaXO+A7&j$ml9dDYcpP#{(*DYhKk>zm4vNarx_H+Y(70v`&GA)Sl zqTeIswMrHTdbTvkR(9^jNCfS$O@5Mc!EhVO^BVG|LJ&o_Vvc0|TSJ3(#<032W_6Uc zLe2WWGYZ(_2+2d>daYD`&$*ZY&t#<_xUCXg>;$l%E_j@ z5;f5B8qZNZh=mYHxh8-tWf?$))Gaxn_bgZbh1X;HRF!hbC|9gMK-bviJ$ z;&%N%D(r`T&Eu&mK3(h*r&i~Ee4~T0uw}xK`!*lr{5`JY7v#G~1Jm0N&J+FargLH3KY zO?Danf!oXRS{!XeZ6&6XVJ2kw86JRD71e<`n`%dh#$~lH%b_K2&wP;KZrI3qi3nV( z@?{(VWif`f0U4CVTl$I&RzXV6CcF|-EDP#ws-V9eAhwKDmZ}0@8tYg!xQ%8u(AdKfgU!WOxCBKOsR5u3c{< zm8ZWS6UktB1yp6@Pul8Q`Y3ZZ%5ly`tUA z`(+dMJjcDZ(Y5D`k9hxP#6Z&dMUk1fpF-B zVPod@U*M~Tf~4(v_WW6JHq;@=i0`XPf;#&O_$Z?5QZrzS>yne8%y!jj##BhkWzFrX zy|lI9AarH6&kM=1{OlV60(TB=8~l*P3IqL*#uR+Rd2mezm3Mk_bY6;|b@lIbN{Jz~ zRgI@CmxJ+iI+6)&vq|mh>72IZ#?gqUgsMoLmnD(x{iTaVZd4Z+o9RyKfHX3E%gJfn;8}eZ9jcH!@l)( ziKurcJ6?+CH!@Dsi!Qa*xSjo!dfr&{^!eQzvEC2gOqk`Y^SV3h>>?Qv?;z-kSMmjt zFkZ+!X}!s8$jlO7zi7mc7Ts`BGdZY6hOp47O##>G2*Y+W6^Fz zyls8+7B7439-YP7^yz}YCTo+ryYXNkpUjUGWPk2X--*o{%Yfu!(^z0PLwysTXWzzA)H9X;KSkECWD!xo|PioVMNs8Yy50lOu+kt{FDC^n`f!7)a zGl^<)_ZUQEaz7vzonc3@ZQ&YS^79V!XH)A0u8!)nfY_|k5tQDLF){HJn?+>|p0`1S zST`7sWyXiZ6!`sBiW&Fn^fELRC9e-2ehlSDlTmL0IV^@L0#lb`of)f&t1amj&3lTO zIn&EpV`UY}!M|baw+L1hcv=cdi*|OC0a79}Xpl}yXr?0?pcf>8_4N+;gk>yYz5TxN ziVo9owk0pZ?&xy+TJ+B=2-6s;j4JX4>PGh5USi=PKof1;l1%*eIda;%6w3#aaypdD z1uA>;Gd;uf%!+?$$!pq6p0ltv*WW)-xlqt)`>l>66JNk=#AzA!xBE{u*Ga8i3TG`9 zQXV+?nTff`-FMr;`1b@*U#J9tggLZtAz|1@|0OJB&@PdLrg=+l60i;9E5K=8YbdEA zMGQf-I;|xLW=ST^EE$`pZY&;jDFR%X|0Cyraq*M|(`I-vx`$cGnd>yVDjyqIVV^W} zF2`h9=eo6`)=Ah~80z3q02yNsfCEy!U!e4m$!I;syROPj(Uf6^&5)5X|Do|_|D%v~ zZr!LdnFCaVQaP00Gq(y#^)JT}oBT0Y1d)i!A83d3F&)n>Sa6~>a1=6v)2R%27!uop z-ZK=YInOO$up95k^-|9Eu&bCt!SQxAe`iGXQckkRx8XNjJJY-)a;=_o|x1$egq zF-E$uD5>-82D;ioY43B((j@0I#HF1nYjcSvHGsQEmdp|AFw8TgfqWR&A{~&vuJ4Of z_hrX?q!DCvF<7asaJA#Yov@T$uYhr9j`6e{&Mi$6TZS|- zq^a7HcKdBflJ&=|vSnFu)c{GctQpJV&)5jeq_EW2)uf#gK~@nSbwn0~iX+2Os2@`d zom!xpdfDq;QwG~}3>`Vy#S$`Kj_hZsn=8x9tU;~!6UbQ-t3Ji|V5B5&>)XfYdIo+M ztt0}|IfYw|*PA|-A^p^jw;D3Ej@uLd%rP@)cBDH<*z9-0tgfymwk8P?@1Fu?g;h{? z2#EM1xD)df&nMYB07A|xq|MW*uIoowXF{vG>&EjY;sLWu&8C5i(!}MStcBuLJZd}p zCQ;0Hh66K3NSBW8#2ZuTcMuSn7W$1@wA;fTCzv=f2$O|Rwbf}yOO{mY^U)=?091SR z{VcnB^jEMsfqkn-DY6FmBzmGGIxDB)#nenff`r<3ic#U1h(%x!>__kfM1J=!!{K?# z+|kGk*KU%`6G2ZCP1V+1Zi$r!Wu1{bhkgPCjq)52UZ-Wqyc2NUNKNu(GF3?(cBMpM zxMRT`@Zksi=J}R4$KK~pF>zxf%S+87+UqI)N8Rk!51#)t66yc%k;q8*o5uKWAXMF$ z<1v`+Pc^k=h0%OWZ*7Jc0vZ=KfbHw&nhAq_Vw|9yV??1wCzlUxTqxrkP3{<6Ou zG{insKCW)dq1{L@reIn4|4{K^JS%}>#8OYQ|2-tsEZ{uvx3Z!5u!eRcXqgAV@x+Gq zc7L0XGS<)5b_!sLl|nhQJ#`~yz;nulh#zx|JU+hVY-aRp}gzS~d&!+$MZ)MHr>F6WWWA0@?~ zb`S=B-^tHnqm_;#-TBw=l{`1a2J9dt2MrGmPY{jJWBY_B&s-43h0HLZ?U%3`qNycY zIbi*|^umO!`enG*4c#d#oTGDqs}p@}B9j%Sq_&hHQN%=qjktsG#MZwjG6Tb6bwbZ) z6Di^j5d$ z)L7Ske)J-v?<)9F3a^M8B6VK{ugt8pt?siScqr%^SRAdApqlvL4(HcoKEURM}^ak^8F7;ttRhlzOJ zV7$0U=}|-lJaSL^Kk6#Geb&!4D#@I#)42dS~8m4FuY9C>r6r;Dpv)nVR1E*3KEap^M24OcC z0alG#s0M!OkbN?%X(!Od_KIw&r!tJd(vBTL{op}4E<7XkDF*mqq6XH&Eq_loNkW{M zsU@?x%?M;&tP$&r3=n2iZNL{z95@<>5WqJPCCg{4dLR(G<>i9y zkBd_a9;KsyecH>{;aicJdgv7L;gfsAT_`ydkUFz8lyz({R+4Ix4jIrans0WsVr!e; z|7LGC)Y7`o8A_t;#3SJw3xzAJ^>L%SeZu@n2TpATqJ~B}d zaLcr0u&uD!7x2WR>JeZk8MMdGR@~`GTTVg;a(f7U)mgPV$G52ZYp^g2; zX*`z0_|rTkaAMZ6^9=n%Dez_!^Vu!R7`mli6na0vUxwD8XPCjF6gyJs&Xk$w7~H;O zpkFB-G%%oe=?1+L_v1`k%1ntxyCvn>$^YPx6ut)_Oh*2^7Q*V zcA0a`tviG@zp=f^RBE3xbXV)yq|&*VC|9r}hq&SmZRBfTt+7K_&)$t@!_``KY0{ut z7RX3>Q>b!SQdG$g$~$~36h#?6t&YfjdY#l?13DX0+?m(Apli?O^xYXN2_ZiV)ZnFN zZ_7)%T-6VtQh_lJ>9qL5Qp&bg9(C}MCoPX9>`6r!P9ql8>u(wtM2gczRaG=FqG>gX zK?xHf^1B1|R_-q1{5pMiu-AN>hS1M{cM`gX;PAqYb^fkqTm*S-Nv*BVsg-jv zg4wDsM4mx)DCLt-=C0hKM{;u3$I+*bdl04)=(G%@8T%9T;@cO$QdvT-I0j26)1x7< zaw#?UX4_9C22?MNXbx9^gd$7nR$gS86w#2rOCopD^*FHGH0~KQ*X>{jM-qO)hwg8n{akj^cy4sAVZN`}16vkCQolK9W zM^w>oTAIVKcq7&8^&<<{11{DS<@Atgqp@<7ipQ2!NmI|1Sf_g)2BWs}ADbWfw%|64 zG-vAVo{40iQ^^lWy)LlBidGG4E_M5=60@c?gJkwij^5n7IloK_h5xbC&=)MFj~WdW zQ{t0D%cRO!-3@KsF2%7}F<6>++d=#`&ylJ}f6JOJ(bh}A3_Ru=Eb9L|E*!a}T=K5e zOd%Vtel|_I@r+c!vd`8M+BPR9>I;8X-=JFQkS6(-Od3nb-4? z9`z8EW`4;Uw*FEywsC$`Uw-YdcB;ea{gGdl*HlAJ zxKThKF0zSEZt4w*(D|vLxk*qm1C^56`Xadg(KT zG^M)U8enI&EonR0mE4r3Jp z;f+sy&;C{L`qUJ+bvIF6T}^v2d!&|Rw)l45qj|*F)*dm-YOVHt+^O!7ZE8(s`wPLH zg;NM9nF01}jPXl_npuErF2kp=0GmEEt(u#TNJUF5&2YQy2}Fk4TC3eHOZ0ork_m}n z%zRGMn1(&YBKqRNM8i1@t=DCOxAz+5XCg>}BogTw0VZLr)q6Y$TIv>Li)U-qA=6PQC2j!sz#|+l4OnZy*$0XURL&i zt(`?NXi1zl%!x=mgnyXxVSF9N#hMmu%LSIrIA@;AfVhFudGKaTqR&L~K26Rn-fP4= zS~SA1z4u8fq$-OF?&)PbFr}}GPMO`r2i(o$XPvuz+xQ_^KSk0%t5|E$A~dA#g9-y9 zpNjQ@-5X1L>?E=gI2WNq8F#!KSQ&$FCprJvp$LYU6R^n^cvf@X#b5iT>Oa>VTEbTZ zZ8o4TUTC6=SBAb^^ZTxur=_8if16N23&ww@1BUMlCtEq4ZZk|h zo&OK6F#sGIve?vZ3+crR#8-FmPw?33`6eF36I8Oe-EW+w6K-xPtC6gT^`(aKGFAz?_bkSoo5G<|Bw+L9Kr zBHLWLid^bVF?}&@O~041wtILJNHnoT*;9E?EY%lGm97)^JD|YjAAo2E8>atsk6`={ zE>t!)hX3jwF|9dn!^n!z^FjXjmp4=r8MO~ik6guX3*q&DIzkc@VG>_>rR;Y-lCce8 z8mOETtKKgRt*!1RaZ!EV-j1K|?qfp(BK1*%<5OdIX#;5N-YMC<%kK<=^fbaJM{`qs zdmLz(yKNr-&LkJ4=KoN4A3lX5q};$ch2~KTX!)YSJw`YDuG6}4?zGb{VSTB+PHQhO zVd1doX7_YkFMD}>-1o)RX0o1t-dpb$KSn2gbtBFc=$CE^`04V8k9U20ULo<~%nxZM z5?buuE_qXTb$zf+t^MnZxDPc5UHbk^+x#nNHk{Cn==%c@Aa+{>CFT)tKz6o0^us@D zS$62$!5kxhhdh#AMhB=-@%eTcJNa+gmKRmK_(*DxDEf807vvQTVWurt&>*Y%BgBL_ z`#NDpL8F8@s*)`Ah$K7iQK%NxrLrcU3_i{7Fz8jrst+jVu1YL#{wE_eoRl%oIKnD* zdJp3aT*r;5tdr*he2?i`na zud#s<;?DrgoH^dnd>A3F$|bVnaztMwA57#1JZ4$O2S=`(IUTn$(&j=i#nrhoWzRfa zlgQmzy~y(TO>UQe3|LL1eZ=>gWrkTZS?MZDmH;upG^d%oW ztld=e*GmG}7#NV81ldVLO{fxxpKjk{7Uh0*OxCbY_jScr0U+Sh+uq6@og)0 zj$})Fr29=f{gn?3-kh2Ufnbi zrhshgU;GSH-=V!xTq5@|K#!{_h|7DE3Y9rsi(nElX{v@0a%xE?ivn3RT9j%u_b%gM zHX2QOBXQ7bvUWp}3i$@WHtP<0h#nEx#+j4{bS$x6OJXfyzV)Rb6CpN_J)O}>-`HA3bL;I4btMCYr-74VF0Lmmxdb~Ajt2zF!Fwnk&n`e zAdva5=f|3a@Cpih5*%e4a#B@s22Q&QV~OH|81z=NY>sWaOclj-_{kS5(Nga1+J`frh@y9M3vP;4OU#dd@W{_W3}#oJQmm+mpsYHggf;@Q4_rY2G( zCVMl?Oxw%O)(Wtv5hrNEp?G7?FNssZ5b5ud1h#>`@ScM|k6=eOt&g12exwOm*FcdA4-9fc-5ZVe^z1QZ;V4 z)r9m-GPVpN4{xxJU_vA!R)Xxep{~D><_zuL39`mGt~AUYD8AI6O}vFS?AG!iPuH;( z5AnQ*@h+_(;0IHaRu7yNw#0;oFj)lS0||Pk6X-6!k$IMC&8~rApd1nB&^wyvGVDB( z4`64d8N#JpUe|P%8W%S?a(0%eCN8}!xchnO7k+Q{$*|hF4q!p9WhbAR+N$#8Cm7|Uq&pDEfPB8ls{?`{jGs5dGAU|<)*aDE&mEzlv?gl=bS;%cwrYiUhy&X zbef*;>sDzamXdj_k$?9BN|<4YON{eBSz|{*vSbqN5pvAJV7u!fv_?hpzDOC70ru*y zrQVzDu1o@ERRQk`PmeVUk{Aj{6Y~es!sTlj=Nry_Ji-;pA?>Y85nno#>SuVVP~La1iFH`=eQ<>u_rhruAK|jOJen~5gJKVsV4j7e!7W(GD@O6rUO8l-wO*ob^R;YU zS~NbX`2p+#ZjBunxiu$T5d3GypiQxe==seR)OV2mz=P^&|IA9wJ^!prw%OC-6j=Oy zVrPkRy~2HKiB`_qKSOZKB2}Msh#I+}@F!zp(`#4rFi_%zQ>A0f;VSP!X+Z;(|SgZuKYxHl;IG5f;Oy^Yb`KQgZU8Lotjkas{ zX8C1uW6Lpf#ikg@p1Ed`nD^I$ceV z0<8SB47z$ES^jiM>l+`%>U%qnHE<;7_-=KoAB^K8Jk74=MDeTnXxfgUx%mP;-Npql zpixI6dIXmvA#?4j_}T&oi<$#y_trjz^Eo`;8_>HfI+r( zIuTp1@Ion)2coY*{nFy?@gsDKR-KA&wEna-) ze7Lc4AqyY<#m@{ld!;MOm2%H3qP;ng3 zhW*`5M)Qs_9Nm}k6fXSIBLh>|5l)Z+D-*4zxRb+xA6;auVUiOPxxc9bj!HWjrOr+v z77{P*Txwax^_a)X3`71$o4kreqK-WA9+;BlFGG?38{)(G0!Yk@@L~sJ&x3>$WF<^4 zUm9ay3bID?IaV4x*3mcrimevAAIjJk0rZLq@W_HS;}}CCudQ&g%*{vV{S^eLv(Yv0 zID8;x-n*A8t{GU#q#W;t+dCGGGiQtESzPqO(>V!@MIGB{CqbgVFEi%j1h_cY?v?)eM?|A+)mf4a-7x^H~}Yo z(>)s9XOV@SiDu}*4WWKfl17T`mOd=yJH?5vB>gsz@wDIx#PP=2o4>(L0u8-s z*9|pP`1^i4XTIA=VTz7wBJ{FX@|T}D8!oc&IFTWCd-mVim0JX=oP#welB|h9x^jd- zi(@X2O-={)Dwcr7pkXO7ak`TQl9N7-e1#bLqcuC!ai1O$O~$pu+6N`|9i+^AG0D)ojLI-BI1mT~jz+jt-vS6N4Is zTi>aGD-u7QKpyJB6g-!_-XEI)*qzBayRVD<*Ud(e?W{wQs5B8+!Ga4dC-sE5Kux`@YI%B|koDByeIQ?;&73H`_Ytk*DKUAkIbI!!{gGUv+!&@{ z3p+>CRd5-t0)THqU2X;%O9v%(u{MGgqH1k&wGo^O6IWz|UGSk06}TuxSvkI!;3{@? zpl|7dUa5Y>*U8x_dxzMmJviOu@4YOvIvCI43u)uF2of(iyM$ZkR6k|{XMb{@iZ|rX z4SE5xZ1QE@7kbQShc(Wp#!LGrZf|jEe*mXi8zBCJ9%p4_|33!b{|AVL`G130SblS4 z|IN~WSyS6qlNG`Hr53M_c02T+L&)I1ojj6RrgSS`1atz@n)VDumnT^wHz_2#u$0v7`YgY%w9bUDO;Lv z8GC3+b{yZ7H{1^DVz+`4Ao9R#0rHZ87I=}jin&^7HU*mL)dPgT#Q_p%iGj><-@sK8 z5Y6yv9Ku@Jwf{n2_3M;^;0PrTZZH*cV^Re^>b)yuAVu~>-aCe{fQnTvgWI@S8!LIY%tl3aDIWnAK;x&|D*t~5R;DhwF}Tx6`G7r!^k z@N>IT6##g$z;dpBfP$9^ssnjQAhQIrnA+ zJ#24i=()tpRSQ2WFXl!$Zx186M%q6 zW(`1N8oHkr7jHh~lM8^-yo}4~y6O}%cHumSQZ^}AjGOf7Sw@8fpQ($`>5%g#&=eAVQG1@q(e;; zbxQ|d8W-OloqYCX)Zzc;z|NMUHoBgME=C6Dz8B_}h>j-Sn%ur1@^IA3O#|%kj%MOO zD&Rg{pPyIB5`8_e?p|HLu>JLb7ex`0A>=3QCyW;r$YN7#*eJ!(>GEWLk(G^=^@SaD zZG0#^cQ+-+hWbJC!Rpy99S%KR9DM5$i~ehfFb{?q+$$7}S7a7+j03d`GWBins{ic3 z!Udy?ERXmzT27zUyZpRr`_GgTM+}I|jVnwAzFHy@+7pqhMr+lLZY>JJCxG9L9=Uw; zp)bWC#4<)oj3R#jy_Ft-kv5K)Z zjRAvS4krOw_&lX#Sd@Z@Lp101^XB`!*!>ZNgLBw)c)vb8+#3N*wsL_1@<0KcX2Tc{ z+4bnb!i?vXGdrQ5shh5Y*pz^9w)teC8F;&Wd3nIsn<9U()Bt(^2k8X6;t>QV`EY*-Ym&dVA^P_G-kni=WHu$JCYGlZUS}|C*<)E@@pMed(;EKCgP7$jCpQ zo@X*8PeiOJCL~_C6W_tcE+>lvIquIQFN@ZE77UdN^3l|hlLYm-a4!WncF1@FP8wbc zp%&p5&&H(blAn=4hr=6nSe{m)W2GsLQ!c0E%Ax^)>?}xSziE2AQK&PH6R_XM2v21p z6|9)r1#L<(48$@y?Un=>x%Vw33tGF({X^^cEOO!R0UN!7O z`)`*GX){iRT{8#Qu1}GVFEK#HwrE*VO57fQTiu|r158GR4?JB(4=_oIzFrJ7>VgSv zmFqWx&~f{tj%xxUmZI++QQe0oC%ohjX4c>C&bmG_&^R(zbV2-rK(r3@X4S&tOk!An zN2^P%Phmn>hP&QaH4XUy@-=6vp)5jrO(%F zGr-^Df1)#3sciD3V;_$$%%5LPtERF72kyU8z8!qLSbTpbH^K!RC`2x z^pOHMX%jn@wZ?`?iG`g4D|Q@hlgpmrJkOg5D~3d@48X9vilaNJ75mro0jGPzJ0)(f zmA>Bo0Zna34XkBHpdxQspq`qe#BLRe5(woKoH)%-FLFfYg?Afu!r`Xs>~EIX#~=Sy zR~zjB=A|Bx7Txu6+m^?Q=f#!T*o~8H+_(1q1wR{`*7Y^J#`>7prGKqGU*jhG$4t&34>H5scASYcn!?U z1KAw_HtLlcke5Ipq($EelpNR)c45@?kYilUTmAYzC~wNxGBaeDTu}R9GGMK6Btj|9oR~vhltp|#w!Z5xHvxkIY@u9m^A(o z!R+LjE)HTv<@u=+E+t`1Ifp`7#w;f2)Z zL&~e(kE;Ol&Ylu?W0PT~-EYd{Nt`Dukz-~(bxg+r>P6UeNO z5AuV$+x|3%=Z4@-m7jxfT=$57jNpTITAHpwf9QVFx7FcJ^gd7Df6`AId4&FJgnZaf zHW>iXPGBM{uu%SwKdoqo5+fpy{*CRhi}U9La_GeucQ4-i9g2_dlId*)>WBh6W(A!2 z72GD^`Aa7{;~}I|@A#1igK-ph?q=~>*NPKU%Pgd|=d#m%XMNP#urbR4W9A*korYLp zbch}PDP64>6Ht~u0p9QRQpW^$q5lU;kuI~|YZ7+O-h5TI9Y1QU@S6sOqbe=Hn#V%Q z!8_OlCY?#!($k#>0f_g_6*S6@;8H=^-U8g<0B?(@Z25R~z}B2cA$U|p?+mDf(csZ5 z|LNmteA2)$#H-h_n;XyP2a_w{rSje1=2W)(i38eZS4nh-60^CDb$k2C808;BT?rMA z;{+FYU7!>RjBs7ybW`a}{|^9#knq-jC~-MhS^l3A_kUxl|4U}*w&r*&F+0pJmiipL z`VUewU>IO4_b)RP<{j-2#l-1=wEur`sW3OY8l#>MX=RPO%e1;XdK+2eQW z(;<}nKHCb+DOx0{!*YaN%}TN|Z))1^DAdwSauauD9R$ z`RvOT`(Qt1Y{}PA6fQ*RbxPiC)F{`xn9P8)Xn(MYC5jG9Nus;~tL1nMg7)vr%3d$N zZld8l+tT)9y&Frg`Q=ptcM4lwH-4PT?A2tsE)iT7tbMFtig3TcW`v+q6CkauK8*xY z{w4&WiycB1M?Bu5ZjW8vw;(s$rSu9?(XVHkP7?}2=IyVo5lbUE9j3ysdmM0w`Y}a@^Kr`13BB2_6**X_2?bVF2%AIl-amBLF;oCZC4Ak+V>cz z1b3#A0?qgzr!DL2jOs_1sz^++hiY^+{y0bKg&#o4xVwq1UapYu+7Na#bj^5bFl2?Su_sS2$N8guy zq5wcUUe=BEAK_6ep;>Tmm+DJ}m!M%(XPq7bR%>@J4J)xXF^TC7g{(=bT0udvd=aT` zfJnEpQPYYO2+_gG&3p!u^10f8!gWh#6ha9ZFA>AdKQn9)EanDR)C3l88`rSy9Gtds z03yeFNB~b_n=#j7X3=NzEFBVul>3N>RV@ zI4J6<6DrB#JJm{YP?OvdfXSQW=_zpDkB#l_84RDfZ4Pl~04l_nnVu z6;}lt(o5FpIU;&BTPU=zj*tr<>t6Ha{(i$t|r zNBn^GmAe>cT;cnm^rhi3%l$@_U$p`ZMr=;3t%_l)bdL%`WZyE**eM_kx<1hWT&tdF z_Z7GiDqJZLGe$>iVV>5^-0VNtuGJg~l@WR694ygv$iXDtlDjv`XpAQBoX^8khum4* z@^tx!awhb_?+b=)Q2Zq&&&f>d3%yK(B!eM66xo|X&ST&bBTIw^+}19 zElq(pM6W+n01B&umLP58xraoQfy=(>v<^HTtVO%JKK)}T6F;f%R_VX#K6==;ig#w) zwpwYEN%u-%Rbb+xBlqCpyAimy0AId2?3F8uKU>t5;l)2*rvO!a6KQ|f-cn84I^46M zb(Wi@c&VO3Ycd)czZtU$3{ndE6wJ6f408V`Ep#gFenPQv^H6p%PFFBIuB)Z1pM05^ znQWPbPTC2OSzv{;@8{#~@SDb`J=FbF$$S5m8V#ld_cE>&s#{-81RBj^o|^NJhBkjI zDfphG2zQPl|HavW_1mWoUq+ru7=HzUX>-zWY=}Q6FTuTd^&lFyHfiW!?3lUz%F;OF zua6s6{ZEPK*RuBiyFAUv!TH~5Ca1Ne?Qz&)dOp;r@au>oi}3>L1G*!CA6Eui3(E?} zDZ`I{@TGXo#Wr%*n^)xk<5p8y_CJUzYjS(!z23cE9-Us!FfE-Xm^qlceX<0|nm)m3 zgHy@D^JxYi?~UId1g(vaJQKs4#F9tHclG$*9OCv&LC2utF#`s>iQ^F;O}7;UG_qU6y@6zP+#MX#2KDKCx6cMH%gkrBv$e#fo@=t9pff|HQ*$IZ#EAWkzxkC+ zDV&9JH2H+}8Pl2FpiRZ&G;L%JR_P8(#v@%WkIo@(D-}YetbRKKVJS?&i-02kVUC+o|N|b zZw*5NsjY;LW1t3<=KaX*Ui;m+(}tb#C#jQaTUuwRw=k(OevBhgO{>_tX51gHDkE+j zwwp96L?d3gO|jiKdM;YehI?0KJ>?@rROLd|pVMflXN7k?DXl)p8090J>@y@}@}XTN zjcxjUee$^y`}^2}37C-nTdD%#8#PA-xPsLj|MP_nF$^6!$gYVm@A=zHWd5hWEu?+q zYw?d>a1U=~WdArXrlHn=0lU7dO#LDWOYOEU86M zVTfaH$E9!Q!;NT%+95c#D9>RzPqicR2eysebR@( zgn&F3(VHbgjY3T?3kDyX0WUd0!yeW(hN!@pfFdWq9-t6KXQ5;8yB#KfQaA*xt0j5Hls+;8s2r9FT0$^-r!Bt_U)yzM9fIOM;<*IGDfIn(tLoAGl z69DEU@4?t#1y(4>iH&bQ%YMlR&QEcfGl}fU6!h_q(DDM)R2en=rbR#spiNKIx z7i!NV1`6TIXAG^bQa~lO`L9$Y1w#$E4Ef6GiB3?s-}8I^@QA&oG5Tfzy?7Owl@+je z^cXW@gyN@fpK8EJlF~YCci++BLMJFQPFamAy}*R3?M5Kz>P-q%OWDfrr@{uJSP>e? z7u2gm*9|>pU+qKOn59rTXlc4bgKj@isQb{l3gOiZ?=hW}Wl(E@z~n20d2M%pt%b}< zvlaQBczh3KW@fSGx;ld-!9!;vCuit%okW_c3er%QS7#U>*f|LI+p*_mJ*7x4Y*n_| zxl!9;QDijq-H%w?*msaw-fn9{qp}6ne@8tS) z;O|!z9#C!m>GKn(5(u`Juy1UT%ynAI$&m(~X3$AZo5%CnD^C+K%9@)8ptkj=)(||^ zhViJtcd(TkGKnCaT&P~jvgUDnti3zthv?CLEOCnL+nzkuPoic!;peINVRqjbvB1`TaD!TWOy@b`qRNUXbQotZ8gz~tAi zY)JtrYMO%rMbbbP+o7TF-iFP}a-YH5S1x5M~Mk-F|K)9sspUmcFotsQbxBugx>tCZaTw#Rh| z^%z3tU8Oj0Ir&dd4(8j4@1qk?<7O4-l**rU@zu{IBVphc^aG0S zM*7zOO>6I4DClLT#tv{l^92Y_N$;=!wpzeJgl$VGbeV-i6H6w0f_cRUHng3o8v!_ zrCAyOJ9o`#?MXXhcBJk9aWOK}Fu4Q80NQX{5^zKIU{7Br7^jLF|Di8^CA;8rA)P#< zSxWTujC%SzNTi+n%`v|CQnngbmPdyrFXsU)m&51B56Bz;NH2labbJU9vh48w`tW#z zPMK0NOYN&5RdaT5+FEAs?6+Xt*nVh#H8Xpsi4`?_^@b@} zSb<`}xA(@6-^(*TP>s?*l6M#N^Yk#f_>+ruAq8zbIL<+=(6Q+M;}Z#w5M4(XZ$eT1 zSk~*u{q_AwFV{jh(vwumQz0y29h1RQQq3@uR}CvPDz2$4wh&IjOahtM5)T$%Ebi~u z!ZcxL<7Xw48*z5?sv=rr+k@XMdcYM|)@qBHW?HQvy71R?S}p2k$o|2(B@B|~Ez$o# zdxfRqV(I5s%!G{n_T;VHkSb`PApt9bxRbFxhNd(oA)F!OibYsitle9x?L?Vr_C_^t z4TG{RGVMFLJ0e4EuPIZ6Ji{%gsuzidWGrTehTOY2Rt{PeBGP;qXSoN~jYX|e2mZLR zQ%BLo0*x0r8?Bf6S^lZ(`bRW;UcN3ifv-lUij`g*ib}i+gP!G1U9Df2irpKPgPaCH zA9P2(>%1+cPa7~2*;GsmLP{=ZM z?q8}Qc8FFz9K%dRUA_xhMb(OHPPbPV( zL>_}XwgDJ7 z>_*VD=lG=4M995rFOVxX}x{|=N7^|DfQ`8IST@`g&he>|E?19^oE;VS0 zlGbvQNnWm~VQ!dcbB{k7$*h;QDvWZ~)-q3p1_2FicZ0U--MwCH0=fPLz?=Kh8LD_& z_PIw}O`P0Ew7I5i3`^}~NzC$03f zxb$%{z0PgA2xwttg@&Y;f2f(v!_*;VpN~GXE~p{5w?b8uy+hnJDs=`9^c<}gLJwqs z(PkJUzdZj+FOyWP_+HKCQ*8i1tI>!V1&6e^PU8vyZDW5|1i)}9>~9tM%$dKC`SMNR zEzUEoSrB6}FmB~)+R&O5f|MTL1H>azTBb2+XiAyl0K+tGX4Hf<7sh9&vx2r%y-3H# zNaNxn;Wv|OF3Mzi#ZgJ}9#6;8JAvUo@$5qpnb?<2>MPG+idmt4S?7}RgZ|{cZmc8! z6+aqV$|1JleM2f?RO+(ywESOfb94lSw`WADnI`l(*%&tK=ZyywQcLLyG#%jTi7>wF zy!RQeiDo-Mutr@fh-qf8=vP+ANc7|~TIgc4j@n)-7Yo*YJ2ntWHlW?-kW?bsrx9c} z%yl!v3U3ym?gJE}rC3ZRGpc}V(i-V|G}U_juOL*XaqZQ3?8d&5)+uXOBP1G=*sNf~ zG;6yw&(c2Am7bIRq0RU#Yg`ZmN4y%_*;^)-RIk134k}Q<1>zBvL3z90Judp}knl(s zOdO7kGZ^8OE@G^N^FT&B)gjTH(_BTKeWsB(?IC&9WKU~H790Q5n$*iF&b~?4mjyA4 z)lG$Gx0g)HE$b*P6It0n2fPcx+VG?L2?DM!JZxumCR2!}FTk0{gF;oo%U~7Tj?HFH z#J0_PbXHTR^CHudk@KNNMcrmh-zsI_bi%;%^^gT?EDKel?yGRG8HEE@Zwc{~dhDTH zyZDTOZ8S(=y79Z*rQ)!jG<&M`)<{$kQV!$R&boZiX8!TDV-nS2H9XU*B|;6~hE-CE zIU#Rh?I5@;n=~5GzgOLmc6Cl%wKd3gYiDo@BtgkdIrGkOhL2V-!PalA$T`@Vn)M65 zwlO%`;B4-WMfp5Qcbg@evdZsl^@hvXKEdsFT{QX4XcA_|X`snSfVaP`YH_UcH@<#5 zc-4z|4GgILmWCUCY}!#^8`c$e-le)(T5GXW#F|=pmg1Bi{Wb0dHAtJm=YAQ)mR7u1Z2q=})vCbg zs&F;8hCg!#sgj&8q()aWwjCWuBkdN}At{3x9}Qi$;+6hl*vC%Yo0}2WVjq|zM(yM6 z8PKj>W%H|TnvJO|dA``POW1T}!ks;L&S_&UbDTWtP2n|G zEUr8DD2F$exowNu!*VgjosL2Zjt;d-PyAem>q>qMO6`U``UT-~B3gTn*sh^OaXyaE zrtij9WV*Ypa?g^P@4opYTsXYK!#i%*06sN0tVW=Cmp$`NlO=QAL^!?ns57-WKtn*15^FfztZ*jCaLoZN*Tr|P+1&DTV5vZBTojrhj9WY%YUa}{~tKS=Ktk#IUPT|55@x1 zmeUs4E<4xSpAD9j?Uerc^NVk%sBF@(>g;qL>(3HFwf3y`64i3sv#?4e4>V+g1rO6H&k||<*3Jzeneqx^=7ZNU+!uW*o z@S7u63(e-qEn#9tCmB14{A$vC)HpC5$Hhnx@AxhmZ1~!=3Kifo49lWo1YH}*&w34oP*#~9pW8Mz|irQQ2Oa}TH5hu-C zUI)S(7clBncIT)PY9iAZmMA?Zc^X(7Z<_U=G_C!H<3ILeKP^=RN%7foy|a7NDB z;L+)xPz}H?IPuw_wTuG`6@@H6f)#2>c&;3mgi%6V9CEqZ{2<4{;yyQ{AeKxxHR1_3 zuDD{t$|)7p@OKSmo1?M#qz3bI`^RcEv^kCxdj!*TzCCWkGx>>Z;Zh`1Q$S0IA8x(q zZwn89s;f@-ZuN;X4(qSGJ;kc{LbGS_xzb6vSh%vacf&(P^sOhF%Q6}>R+YI+7fa@P z81Ac{oECIh=@@^F(WC^`luEaU%CrD%V)5)->yWCCYP1HiL~mp*5iKEVgKE5^zJ-82 zG-LA6N@9-iHGL7xgwU-N4zd@?SgBc779N}>4+Db+D78qwxcb1&(ygMd$rZI+qF zlsS<`3Hd*nX=d*jhV9On)1fuAz+8=SoI;c34Lgw`u&mV)Lb0}gmjooih!peFR>jPL z7~9{UJUMSHN&o!F6D`;6n+QKz7>+7JujL|+RQnT}16gt@8bPWcl*?2>mWv7Oo+{v= z{`r1eZ(;#TvkFWySSLfA{TCllCXLQ8yNse~%9~fuLD<8!PI$WhID-CXF36D z86wEnpLsTX35CO6g8?HT+hbYj+s-tBzDVAp=1n)vdmmZX5^}uy^3=z54k{c|wT-`; z5Rjf>gcjNT*7UNo=yAgL#fAi{2MJ)n^*km3A??~qP!x@E{|;=m?u3|Cuk=^1B6+$z zfdx5o2+_UrfPJ`Q0!!MCD{y$7RvTA?dW~c$wK9Rt8g~W<>f#ubQ{21KYeVEv(l9tg z2ig3ldTF?4Ex%H<#pxCDd(sb?N;;1osYb>3^=gf~uh<(}A|%Ih%9JzkN~O_!DcmR6ZVoJ9MzP0qI^BfAk{4Uy zCsgHPKAu{We`o6A_Lngydc@kjGB4q5i2Rv#cX>71p4Akz$Bi8Z&F-4ZM|qPOa_YD& z`8c{e!RB-=eNq@^ZZ${hba!P6MgY2xkmcpB|WFpv25Vb4| zeA@y=1@fV+`OlXsdE5Jtk~$)fx;2N^R@{vclXXMVj&n3XG$cyd0@iMJx$7Zp-SI`| z6Vd;KWidLVpsqsj(wR!3Xr7-=ta_pGIHGA#105l=MbTlSQEtDtt2t4PTO(%gCx#Vu zijp-Sc*L%>G1v8ze+tBHn%f&V0)zovph**?(~=@wLPb5$Mor$=`O|%Ir5UjV_avT8 zjA^9@l1zCQ#-h^h!Qwk7Qg4(u8^NxZXM+xBh2xgYN~fT86Mr>U z!Y13mpUr6jG2oYGRf~ti_EFEPOUEL94w>;cx@g9$&&Ym~&h9;|S8LGH%$JaOdH0hr z8HM7y;;(Qqt7!RgqyjaOLvk$@tYQ4aTd$C+>HMN|-8rEM2{O9vd_d$L2|>QfQ)mUKhNo0{=G#mS+6Cv; z4=sOT$8*=sOpySF8z6h1I!8^J)!t~9U-2W2R_GC`z`m-Nu+oxZR{8k@OeR}&@gI6X zoQ(f}?CtO5=D!0#{W@9yFPqU9^;7UnVYI3?09at#S&x7%rc>>B<@j++xQrkE;kuxpPjB(! z!acg~8G7V^Oc1nKtAz|*C$$MpZc0Iyq{ zx*>g zot<)(S(6>fWnkNZbC^a<5)*8Ws+dQ))$fc+fh15SjEL7R)}zyB+rx-_GVFD14rLWo z+I($ud%AePHVv69shgGt_4#uLq7aaxj|`Dks{Wnq4!)G_YFDl!UGbXf&u=YY6t=g= z5I6yA631UoZLOPDSX|!Pm`s(}Ezt7&OV$tnmgUKVkK`Q}Hiw&sD*1vQ%Xby&4ewp2 zVF4((ZJL0bW-j4O{I&a-s^9`8m-P5Mh0-RInpk7;0yj_;Ic4QJO|H$4k@K?{vkn4^o_b;P+xvu z)0F&D{tvp>1-)X#SDcYk2{JZfx#q;$JaH%dr+!YF?DFK1PN{Qd^kPXaKr*fXok2x_ z8OcoQ^<7lzPMQ3v0q2E4R5NPt5bFph$y&$0Qk4I$u~zZ1axzeRvZxE4-2#^Hu?Gy_4VoCzym;l2glO{<_fc(;m- z=Jp+yL%bmj;cxJ+6)_D@{`qM;+Kd@rAl7enV@2{p0po(ZhZ)6dQP62+>H=BFMNEn! zzz~G)7pNKQD*<986Ueg{GhZ6%jPPnebAnnmGj!ajbmsWZYEJ%rY*EAHn8WWS3;fOeEVIwyghlOokUD=(b>dvC5WGJvBTvj=H6z>6 zn$bCPv7zI6NL|@ewX6C(WU7BKu2Qp9ur%B(iZ~54so54y>vTkU6XDQ?8dbtRrJ$9u zX=yC6w$#D0IcLrR2wSP2=Y;V{SI1bZ$J8uc0)oaxK0Pi8RExRukZO8xrB!_CuxG2w z&6p|U^IFR^Bh68TU6ZI1$dnC%myTdz4j}Bzw=HCoP?r6WOI}W#tw|f52>B==LC5Nb zyZ$gr(s&@rwNDzFl1A`u#}75=YuRwNx$_gM|4h@}oRR|&Nbhq`Zxe!i@EGFr1rsYBYH#%dCybJ*8UMf$HPmF$`I2l=C9lz*AqI?KYJ3dtmQ`nX~-$O>7 zy<1-tV1SIpwhFnNd{B&-n`aGEvofR^+0+?vRYG?d0ce`ekDf`lQdw(K(%LR2Q$Ad{ z5g+GyZT)TMSYZ96^S<+1gUJA65h43&P=D0h$I1TUGVSO=o<41hK-)-xzorr`q}QcN z_uV(yP-*yPsFFv#&2mYV6{=3&S3nwHXsV3@BLJ#eDV;q+c!`E(Uwy zQAvX%ZPzrLCOBI^K1PMB2@Fhi*D#BK=B`ipJMH29AG^)KA7?4O$nq?#Gtl`Me}xt~ zq$-&euO^U*9H*STlm|R1xbSgm@(QDwX*{xtu@`xHyY9N< zjYU^<03DIt= z)ym0hbJ)0-!dBV}N>MYMk)pI;kci>Z!rUmDMI)A*SF3MLrB3X%vZ8rt2xL1*;+o_Sh#p}E>n0`eDCs}^B;$vLHKAY< zYhZZ7M9OY>l4m{87S^soKu>)~YK}D<#TFy2a-Kp4@)5ZDG`1$Gxu<@v<$fZFGaCdf zBTWsn^iih_JL>Fw7^5Gz%wY^-qBf06eKJ$U*CKJ`fkF%=NMh)`z;MBrGH<%nA{Y3-Kxw#U#dZm(gdo)xhf z_`YI4W{tRyK=ph=$UxC%DnOo7*#D-EXg1~M&FC(0V2B2{?$2cCFCcZObempne0(_% z5E~Ix@ZU5Pt}4INo{nHOTKI<-5(UPRCg@a`8^nXmjnbf78`o%#0k5g(JG8n4hPq_D z7g_ZSHS`UTDeq`|IWjNTRpXk2AIdpr#P>8{eYEBqMS?0*sbvmSvSzF#{`K3YH{BVh z-+a*Xx<~5H6w|r8+}g}MC6YA3(a9Raf}=Jncs{Lti26(ho%*6M{{)(;+>`xT;VyMH zQd!want@atdJsQ)7_m-Pcd-4)o*2QXyxhShu%SZ-looGoQvMQc#}7`a_gB0ow>1K( zsfn1J*WFayaUe^TYv+pE;fjFDF2Fws!?9v`Hy)~;E_jeM4c3^bJ`S4lVhtj#eSyGZ zS51k}4lo1fvEyGynJ>x4meJr}6FIarpKp#$180nY56=|ss<{T%W^^y35Ty2gb10w~ zA0LE0oBG$o`G*!nklApm#%Y1G{Q#{V%mjRM#>UVj!yEQXd)mXX-@}m0vDk-)i3}XR zgj^{~uq+xx&wg`RT=7D&P;kBAp}lcYgzjQ{6EL9Mdo5h;1%)&T2Z(d%Uazo%5{kY( z4cz=^&CE6mkN z4H-a2iucVFJpNMuFy*PHxS_c+bhvX|cLKPyx)70~JLg}$OhNTHMjvr?@sTvenzi;m zUD!;Cy&(zl`e^QZ!LQMl4acAhYO3IH;E6Yi7jjis?cI79%d?F6&9{6ibs;d)z=@@! z+1W-1!8YJ+%MrZGwdU0xmaW3=FCN!xF z3bXgV?29`z6oGx?Ba*b`w;`t9NXKtmv?80V&fDJA3nr^yZio_sAsXhel0RpU3@e`i z{(&d+FezezE$^Z12QDC5EN(iYd{Axj{@3hK@-L0~Cm~+G`>Ll~dfiSwjr#BzsadbR zrDV~=ZpWGxeO*?Des<#vTcbI#nrsKuCoHnhM-&D+&W60U{~`<(R8I$zef*f#jkDO) zKk!Qej2lEY!~VOcAFg>uzjabD8C9ek^&#fZCVScr^FUmkJyL}}6z1;b@LNU9on^}H zX@q++f+9p6tGfimjS29pVrS*%KA~$n9@1vniBkEXQ%6nyoUBw$A#=T=S~o!GCmZSAo~5x=kX9R+%e@w-|d8XCDp5eVpAvHApI zHvu=W!~`T&3RMtcBjL9Ecg<6OzfDzbwzEDEtHJv}?5*7F+|0Ag-jfS!VLZuXEC}on zuYzI-kuaA?LbyY`bjt;Y2+3fJbBcIYu(&DxjiLF#rk3yoDS_o~wAd0(>Q%s~QI;r+ zEER-r0(Oix-usj88jAnH}FAFg{XJ!ypf(F+U|ouMkO z@jAk@CJ5=MNPNaIo;5H;wAZZILsC=LcXQc{;8O}#1>|fL&ZqqjM|}22f+e%i{N>dr zzwUJ!8!mGTU;DpKk$=?*o~k@BY!4a5Jz7STN8n5A@{OeCZ?y(RQV$webdg#@+ONNu zv7=e9ZBZAzcG%K~oLDjJj2Oj}G+4I&X+Tjgke+JlgTk0L&tCAXZTM^W`k=6N!lkU{ zr4&eAxvwe6el)6z2*z-B!7fvdj+t7Zz#|*ZugHg(+UR)Um`Gqi!3WQh(A??}4hwT{ zMT|jxK)j^>VHvH}sK;`C1<-%tWRRjECed-dDSF*osvUs2alA<1f{lWS0I$`J198l( z-$C#mlj@BvpGtiL6oFSXCYd4p3rr%?X4DOXU>p+WQ?TX4Lz{viy@f`Z((Q)WQGgT7 zC~^)3gDpV}fJ2P*M43%&j}^)}CQB68>`Ft%D8A=qLScPHG-7%IC$2;g=skl`YB2i` zqZm{q#_=uyA&c+z^WpBzUvGMpo}Lb^>Tdm_NcHpi^>TlA@O9b9lS#j4tQ_*~=(Y8( z^X>w@>HFyH)8i>f1=(qYhOm3xx^gVl3X<~H>C>riZg#{TeHQ(IebBrF5lu@ZzB$y1 z@%;h)75Tyc0cd%M@p|zN|K}6E5ayrg;PA!6Lz=E3Mz3Bred?^&*#CyhtI!JYqQR6A!%LS8N<0gQ@@(dc)2<5*2S;gqnjsJ|1Y$h&*RtUq0RI1 zzO1`mv6t)X;kZo%cR}bWM9uZ%q^s)HBEQExv^9?qeYHA}e2`3#oKOZxR>;NXCdq4x z!ad1jg8sGX9d!xCpT&FaqU4m875yol5(X(kp@5j-T3`cpY^l^_U~DPL=n2I?$W&vg zu&4-%)X-UgP*(F+-i?CVvWU7#uu%Sc39U8)T2M;yAfn)u{ivAr{KQmcL0pqsbr=Ep zBa%mO*lnP5qU(P_DgJ&m6?jb05@Z=b?=4sn?b1OQ0GCLN0|*Iq+X_%@=OIo|jsa&G zp&E!39E!F^2jHV500AMEGJHC!tL*U7M*avaHsQpE4|0}axwa7iDQ2cv8+pF%ttdz9 z>&5wXacS%H<>Kf1q5trGcs6^vzNI;Sp4mJ-Tok!t znV*>UGKE)AF%k|3KP}dmtojHwq^t zNifG>!HmHToQ(_KjWG*!+F};KnxZxV{+O#d6K_)TQY;{5yF@~r?VK3-zpY@%T#+17gYk7lKXwFmswPSjk1Hm2$fUtpT7|$5~k5l$T|gR`lZ8PL^TE zgh2Rag@i^@l>Sy+arUJoi`9N!)*4@ky=rGpHjAS~HhY0g&Jwvyr}1F>m1yHOqy+@l zpXiYyr_zXlW|3$ZZC`t71nh^kI(B% z7#hCND>zcrS?Cy7X91e{Ox3;0A1Lwss1!g<#DcR6syts>#qCgJ`s)U@RLf?Q!XaD@Q7#O_tCcK~1GRH@iX;_E>slTaRBK%*kPJTvDA!&g zUyil+f8qnebwj*-kxwY=8F8aYc-{jZ8;YQ$oTghMj914xc7+llsgGKrFe%Z#8^T#nKg7*nUWXcCVCX!7Ex0JB2fzb(u01^i$ zqzm%z!TUAc6<_xwg}YBFiU1Dd2OFMN z;_{h{JX=*IQZ-)GHQw1|M9$GefOr3yh~ZDdm@U=ZBVW!x+8XLlJ743Q?Z||V%O|`{ z#Qo$aWzcsI^9SzyxHQ8X_{W}aU)V=J!4`RXR39q<-`^kt=1Ty~8w+UN4%8zRpIi;p zt*3*iLa9}j7Iar>t>T7J4(ML8lK6X>;U-N5lNim$W@+5`dYf5?mZhNgqHqY19swII z4$ImLr$tgxNZ2?ue4_zhVW2MqL>KwIZnZPIa>zvig1Ul`rL6F$3FPtXRFH5e{RHeT zRIBo8ujQJv2=HL*xgVIC7#B00oN_b)CPo(7fe8}+*Ip3q5Muly-{4lj{ryyMUQ&LO zKoC~#wSO3-K#AdvmL%30-`;kD9n~)L9;kQHm!+zhqyE-TR}Dr@UJI<59)$X^XqDlh;jgJOJmHq+N&zaP84BZieN_y4t`=K)UQxbp zp*BzNbgFq{(ZieRs}ZRDRN6&Mt`Z)fn8!8nK4}YQ-(z97>&1y^{5OEZZQp(1iTTb6 zY(S|W($zaG04XYW+Z;{g9LvVtPzcf=`|fq8h19XleokRx`Q`5)I~+npN5x6o9Z|P9 z-1to`_2kHTxgtUqkH+6%N{Tbw# z{Rpx8|1(o?LE0jH!p%J4-J~QC^d!)O0_KCKGqASUZpJnXADHxycpv!@)cX{MJ}x^s z-oJaG?zCm=ufjs|tc%0XF320d1jE(aPsd7Cq6W}MTywx{_QNoLW35$09qGI{O0}M& zb{Q*)aGeTQ);Al2ggnIcHUopnVUJPaTEfF=N`q$SLtRNQV<7Hf+qWPPUOI8CBbL!V zJK-tsL7eFqON1q#o}?UDOP$6&#+FCdo+((14BxdX%y_nTm*D7UwGsBBgs(*5&InNy zz_$C|()S$QKg*WDhW_|29MIKpu&brt6kwWnkN;);fsR(Z^7;?8Eho$W3&Zk%@2Ik{ z{+FvlzdNe`TU1gPsj34o7_eyxp1ujMF1X#ruOEW&fo6=B(pMf`C)%=SjVW1G{P)wU|`DS zc2D_uFzuOwkHN*W1B8={6Ht$&`I2Lv@L;=pMBXfD`PjqDgJiZT#eeO=`}cm=FN$i^ z1jWQTp8t4zZhy66i;5Smh4nWm=NrDBY|{1oPg@BCK@|Y2#~-uj`unm%P4A0Fe*%vI zn4%{9<}P@B;>1XX9!+^e>o|jPp3010!#df~j-@m`qIrcx%z%-qV2X(%*_;t%m~f=j zIX5HA-H5~O&eN=X0`&+&wlB8|O%5hBb4KOy?bgJVCqC6~|Nmg@9fLEA+V0QT=-9Sx zCmq|#9ox2T+g8W6)6pF}9oy>I$@KfLshO#Ho)7P-+Eu6OeBXOrXRq~JXlIhIa@tHi z=&&ibimc+olaVc!dlwZWaFV0p%@C7%i6RMc!()jzlV zAla3Do!`xO8pi`K1tk2;JbzPe>={4aS479k0)NUua)4hH=H?fNF%2*($u7+RJK!TcH%hd1v0JYM)=QEzRtdcE zpv`a4ao=ZTGMFd@Dy3CT&1%lX`-1>yl6a zftK`-N(#@20u}*TQamWdaS*D-dRi|0hjC)%+bmBFpB>hPrl{szvQTBk`bISrH-va{ z?=`TEv^Ha3Astc2A*CF*c_zl8?r0Eo4=5`|B_u1IsVMYXotG?`kgw8^?8$4BA2xWt zN0BqiJ`BId>;wa8(MH*)J5VlA5!sIqr8uqP)Y^gppOtPJ)u&26{Y@n$38_cQGkJeM z+>kyNmrEmSoO$8PzX52J%0iTTAJP4Ce4=;=M%*sXSNIy>^^pjkvNe+%`vUM%im3?1 zWh$JELUPzosE&-g2=y`y9A=dAcjj;O{Op>=>QxUEC~7wsnjTU$_3Z&Lxp`2L zOKpZF#N<bq9xCKo}x8LNRjWi-J= zh*X5;GM`em$g#l?BnWh*MQ0RjC)pOE4L;BC@5ZCFI*L8RF3Xw3fY$2)@_Paym|#0C za$yXo6mdpbQ<)95spbE9KE+v=4NLPT%;3q@I=(0_au!yVaC?U-gC2B=`t8Q;Uq-XehLXbUj zHM)GLgO;ao`DJ^%f|;-J1Xpuheko_k=a3VO;2{>|e~$r$usJwGqh%__LQlQ^)FAzSuAK^KU-3`5w9`iL=%kY0Ng(K zQgL!;Y|D6{E;m*dy1B-LX>l)hgBDykqBB(3wT_%*^7aP&cRqBTW@wCSI1RGj9K@I2 znj1B@>a}k)_u@06Q8Of+V`%jlEKJPKh^LmUqSq`NT#ITR!|nKscPkx!WN0^Se>Y!f z8vM82pOfW3?k-rF*|`2!oULBKr2P>m!qy4h2Y3kzg$gophj6kq)M;JFWprJ1TQ%eQ zw?S$Xg-*Gx-p(q0F5YCa6k*anik-lR!0F!m;>F40DsoJSX3#*+-hDmjOVDwDVdwn( zE@)~qv+oz%$5TzKlW*@`7(iz-uj+xP9+N@Gh)oDnI$2MqBy(Kmk? zG)!r3LI?{j7}EDA&&T6Kb#Ci8YCoA$(7e(*PceqlC`~alw?*1xA4nLJZ==z0c;O!1 z-ALh{WFPfTbK^^0tGQCAwCedqMdJ$#XknuGbimiU&kqKnzS%ZBI}9zR)*y#7z#vb8 z6nv~g{4U1QN-1QQE_BEyDjtEMP9N+9&t`J}sIfDlZ_ZyCyEiyrej3+fRNr9r`QHM! zQ3_r$(6>e+wBb=>F1>sTQ_8ERQafKeQ|ZQ}pRTM{DZ{p~N8D0xs_V=p0W)3X?;l}L zB#;=v4wrnp+U5P60y-83`&WPd_G#O0{ar>yiN>=vv}ipHJ}|&)%`&#V2PWKfb7GyL z_cn!_pN*u5>GN@wc(}chY(vpNW%=i7AC_#o%9@lCF`LQL;Y1X)9lZ*^`m*@AdjpI>_qeS)d z*(Gl?QLG)-vXxRbG@U|C1T}7-c*p(*fg3dp3+ts% ziLG)Zb?(xmyQ{=+IY)6wf+yze6`evmYLw-kbcsU05tiYgYY0oN z6&p(fW?MK+!XO5sv9IrZv^s(vYjw@{>lFb>3*#%WaW*N^bG#QyP z463AVG2hEt48Wl{1&vb*?jpruQoGMpaPBiGSP`7Xnh74626=slg$>Gtk`nKY zmT&9zrS2+!g|c|vzJ!x28NoET74`YIY_f8Z`r+2IZ-icWZVTT_6 zOu!@#%}#3xQhvvrCEvY+Lu~&P^OxQ$VN0 zH%7J#h4)j_Pr#tfxYTMyM>T1@1qsGO zFyCq2_OQQcoWp~=UngcND3#=qIuE*ooO^MMUTz(!P(>N_BC?Q)T0dd%!I$kcm8#}`h>4L010YQuZphoWNE?s*wzVjm-(vt_YhfahbcCm_AN&vW?n%hU+Ik{%Z-Y?qAF3-yS2FxYzJkrnrv-F&x`V@T2zLb0ub%KlSXE82sakeV0qa$9UUK&V@kAQ8%=Pe$KLx<12 zI^Qy)RD=G7EYqQVif-uo***kUs78*=)@NSW96cK0 zk?$Ug{$2qr>v(OI8@D4%(0iu7UO`XL~zV6G70 zVp%000}rV%;wI1W@ZI+2SA`{P#F?vZw6|vzHH?R;HWQ-Yhl2P5rS0~5gjCmDOLdaKwt~w(8S5Ds_-e*lw#Zhs?6Q{(nzy%2ou*M; zAz_KjC|$c6Gi~G9FVHwDQ((mW7@hMNuzgxasL!AskWHX9H^C|xhb8-@BM;6#n`vW&am{jNvra4-N>koypVSpCx@U`B39x5NHQmuF@q2UUJQ=u7c|PF+{wzU4myZ@wI9{5P zq=yhz*jyR>M>-PplnDIs%U??Dhc4|8m~T8|mY=pY6el7hhx1~g*AE*3eg3bLCjo(l zP~UM3)czFQBrkhD{w)fHaVT$G{*-G2P+Wm9q2M$i!LH3!oHdXI5on0yEyWFv^q-ir z7(9x>l~(vA=Jm>P;Oye!;Y%ho32B=O^J%rR$B%|Ituw(Mvq604wgYf)iL3Li1G;&fg4kC zXOOJGq&v+pr?R-gJOG<0n7H1>G3MKf^aQaj-oY4?>&$STgMaUW@Ze)rNACu{O5taj zM{$gSNys1M?>}vvvX>-sRjC;BM9Y+|u2*LbY>%oYv%oj|*E1yRVRGkKPw?l4xbHxv zaJ5dQ$JW4N+hlS|r(ll270G6mQ=k!lEXjSOXF+^#rlxN*S9WIk7s}BnSFGr0CFFW$ z#PLEq+u+ztyzhD0EKx}MgWNddJT`Hw_JmUT4ty4kd-o`-Z%A9t{TQ{U zRJu*!P-2X#$U%XY6?Ab`f){jo2wb!J;`?NRq$%Dnuc4-Bj6zAy6zdt`BGOqMADmM~ zLyU7>_s*mP?r?e)AFWw9lwW0LxXyGiXN1Nia<&wiJ|buEX8f!}+U2J7a!A{bwOYHdM?k%D_6^4DJ#A*xnn zh)3*&B7~RG&CY(T%ROTUuKCIFq>dLfyeE0(t7tx_gqFITiuCO^{itMhCTU z`puTS)5DYUHN4N?%0S$Gy}vAB{%eDue$2sMnu>ZNtzr4qxMJ&j2s5br>ahCqK==L{ z9)S&Nntsg~m4_O=GV3ccr4Ued+Bc|~vleYXO4gHv#)SAX&w>&|b&+|f6A&nsi3 zX-c`r_RB(xTiC@{*gb97_SwJnD|CRt$BvdWRyCCgR-w;-E^)2_J z(3%lJZ`3?dSht3$1E_yeFHS>h?5lyHgWIR<50MB1QwJ&U>eJ716>^^oqzaArRvBYj zsxn3gE}9-3V2^rXE6Di>+)EKKTh+Ysn2 zKWa4CsIGErx5SdFrfvg2Mx8*BD<0Y%X9U5e+?drk`?N#yvT=Hsq{!dOIwceYkF>8_TFEF#!eZ_2zskzcc-4`+&eWOS%wm)r>> zm>}~ocEZ35V*9dH^km2KCzQ&IhV~nCY>TP6gnmg>XiCnuq(K3(yoD%8IN~$Z+xb2G zuVqh6V8I3pT8rvQKXyR`{%BnX_R((5-*swRZKNnmZ~L?Bz-qf2?mXR(5C7?^;dBF8 z7uvHKx)vvXvpy?y5aQEEUBiNbUc zWssq}Syo1gr{*V#Clg%s8Pg-TN{Ryc89fs&JfAzKz@dD#B}%(K0{WicR;ngK9ojcy zBsjRmWJ0b~lLhqD$zVw)SC}>R6;M`3Y)ApsnBvgq$tjA4Z}epyX?LcVa;o;|JJLF5 zwEok+-n6rVM{M%Ze>+6%#CU`Gcnq!y{faLni-_STD6pJv5F@$l44EY@9k zzWf@rfv5t9N>8=@8YU|D-RqOXE%Da=IKh!{*Mye^ zZ#PnN*XJTlbNvfv7!@2d0JK~K*8AZJq)pdmp`7ZZ6Dj5XRL_g{g-4M7t~G)(+TmpT zV|yDkZ;8;1M+V>91G+U1G(n|ZyBxzhN7ByT$@$ag^r99eoiaNZ(v?hPB~RT7Tl@Vb z6}>mkk1*AaI5H$wbGjQvOP?IuOlBq(p!LuvHrz6&vmMZ#a+KrSX)cw z8@FcT>A4ypw7L$@7c_i60BvHqa=KNn)_>nRjMcDa4E-YV+Kj0grUD5E-xD)sS|%6hq0ui z#xss~;&0wue>&=dcR>Bc3tXH>b%gEGy_s62*qYCe-_xUqznMOhB9_KN)FsMS2nhI^ z6gi&p_ZD25p+R4N8Kh>2w0wEH|2sB-A%xucBm(!Kfc#Bh+z3(zL{`BDv3a>p`VJTB z+>Zzd_G0wJ%--bG`iCGAmqp}eH62+Lh4ABgVKxEQlD3fp6F#VU=ig~Vyw)s3_Dh6)+t7`hh1v| zb{*W*3pM}ozaO5@SSmyXdC1Q}r2q816r!Sb~|u%-;_c z&W&w#qMkJz7+j7M6TFt<*&BaQSzq}I>&rTaBVvqAg7;Q(O0*GJG)ab9c=c#Zn9jDt z6$rb1HKgggP^0=lat6*&jh~a_!3vhkzSdA?x>fn_=$h6f`g8s@b@v{Z?=IzXw_*R8 zFZalTe67NpTT?bRZ&Gx|S-Uc+sRMRlwszVaISU8ZX+s~VUwIh2RaQ#JIJ3kNw6AS52=$^CRwO=B z)->|$T~5W^_J;e%jnsUezi>xfA~~$N@|Y@PtvM@*vKVoWx>yAD<)U=Fo235q>vDTDZ}8V zD)8o@t^lDNWuXi?$7^Q*ouoUdE30zVnZsyj`u8yQhYszLkSj-Z4M6I>Ff;P=F-eBt zF<_}vjn4qkuxEF9nUoHqrh`)zCaTXkTo6Sd_K>=0md0Wd)g}qBi~y)qpKx4l2uY(K ztA?m9yiv{1QD+^A8f2SrSD`qddZ>QgN_SP4Y{J+h0a#;7^~OHyU<^D&^_#KeyXUTi zkYZE$N-4*O{Iw`Uea#p8ZW3EY_BQ@eS8}+UxGFH$-Yf6*tDltBC9gRIK9u zjHmMnkI|;m2cML5cMs0MYdk$vd?(k=FTz5H zG9C66i$1PdHO7FO>%z&>ph1;y(yp3EIA?va43Fd(wEV^jf*n5PqlQO|#O)~B=0>fX z4s-7$dDT3r6bFl-A8pR~PXcSkL6`mr9=*d`^bN+Jp#hu27QM!s{YJz=!=5KTu$wHd zQ53X|53W>Uh!4Zbul>ahdIfc*4S7p+%73hCUHpvipxzI!7!vW~P~r!7y$}0v!cwV7 zI#mhaaA@eCtLDK{sr6jqHl+9cc;=i*GnHs@ONpJ{cdhMb|aj)7|18U%fS$?6f`Q z2hGP)cbUt93<9vy`?%sH=#VteTkW)$Ao`+uhXpVhIM3f2%$4zwDlM-1$)DZQ8Hj(c zVN7?ZyD5gNm4nu7A>bf08HcOA8L2?muVaE%?B7+`aG=(Vh5!1qHS!A#eJ{3WaoLpV zvW;|V6ljRAog#7o1B`88i3y+h^qAT2s4#rbzc%$(OJ@^&Q~~Xk=_YR9D07?>YM+~N z_YP#vmVJyZnF+9|=i{7)L0~J*^3ZLxl9+&vk*#ZJhIcD{X@zThw=_Gy_ZQ(0QFHg| za9i_`L6_42pB0TOlAG`F5^|&8;9Xi`!FXagN#=8>5_#_J92$?_gFZ>FtiSl|iC|?r zOM_>)Rx&4YS8}2hS9OHxW$QL=Uy5#0lF=Bo8k&&xP1)` z*r8M(!rtR}LiM00nSAx%i8!Jtb*Apg)85PQM+A`?;;~j7OMi6;djeSse?zdVfL3gU zYSXQ0sPrzkeAZ^TWt}wIS;QBw?$m4E+2~wyy<*me+3>z@|E>EQ>)EB&Yo(=o{}zKS}Garb2toM(ql<1!6nT}`M=At5) z9DZz^pkDnZwMO~-!Ao2w^P5}i@-SSTvqh{~~lb(A6&^QWYLdGRknw%qi=)g}u~> z-Cwfloj{jVwo4ZG@-jUFIVbHnZh^sB*e8t2aj>Zu67L66JTCtQ-s&2r7}r;s(@h6Q zbyDBbNE=Ja>gAtkDH7JloQ%@$8b$gbQ|9KuGC9f?%D;ZN)jr^%x+jwNaC!W2M?x?O zz%W={%!8abzl&0N`!c;loXGCCE_!q7NlfwJ&+>Zt25DtNn*C3K%E`>~pM+#q4%YuI zYw;hNp9iV;MDqn&hAg@iv(S+EiVZVI-y)M@lm7>kd^ToK5#YbPuJx*W zCm9jF?wrmT>~}xV_qCre{j)#C6JPCl zf2}4M?6{(6R2v>7+*W^IZ6vgR_aPSJsoDMp{xd-BJ>2wf@5BEOz&M4479{WMYxXRm zedkU2LU+ppYyuuvMrV>AbV6(7QgNkN^n_N4KE^mPfj%699_}v5!gS(>F`y+7=+u~s zRV@`x@b&&atNMKSd~?7nP|9#_9&WI20k$T>E z3Kx-XsqR|wp^P$U@ua-*VKgM~dc(L&sv#gwln(XU~F-Uy}9f&@x_IEE# zn6%K@)*Xzdyu7823A$;b*A%Tfzc@SRb|Q+Gvx%H+ZXRZsk2oE%ST>hKu&7>JKVD)F zlu7NdAG4GAdHmDlVu_WUCPrlDkOeB0<#gF;9T{l}R_vtomyhuh5uFkBEsc$_~2`7R}(&p`af2+YZ#PHcBrq5{wn z#q?PQFXouHC&d5~CX70J%ydsGJAIl*P+GvL%K)xOARGqm}myr4H(6-<%egCkC+mf3m~rqJ>BB>pEwpe4L4KsY|_bMT`FhB9TFKaCR;NM}BDx@CBtk z$n!k2bd--1Hu^;?v%)gn*@UVrjLvxBAw$EM+4oX0M;pkl@S<2?6`)hX)m?OCD9BKU z2Ff;X8>I|U`z}?tYSTIMjhotQ15MAKL9)oHQa7LQx>97XHG8*ulC>ePhox&!0UFv5 zXT0+n7#iA%0E;wPewAI-?YRa?jt9KvpLB?Xg=rc!09B#i|EeDF@v%=Omu@_~fivA} zGWXt7+oAE~Ye#F?J_t%rJnKpkZ1UuPq~$53?~`MCkmj|1HY7h0h@rPi*WQruu4cTM z#%&&N>l|`E_RHE=+%K5Aay=bgFq5`!TN)Xhr&z0Z=_wkEIq~bZu_Pi0_u2tBjz`o_X8Ay+_@rK1>aeJ&}r{L z8rRPBVGmpUVn?A#`1&sA-T=B3a&J8TE3VYb_AqdA_uHPOn|bP9M>~&TzqWL0L)%}B zX(r!W^3koH!G)KsYHlRtA#!n=l-c|hsBzzGTa6X@o1?G5s2)H@W0(tkhM4vcZ9`h(Kx^Gb-cj|9bAtS2;iO8;tZ*LuobPnaHqbfs+Ff0vc28{Bisb?f&TlS6j9K<2y|x& zw&JH7+50h_3)F-hJXSt`G*YadQa&cGqLDMwAuP+trgmPa1bN4?!-}zDSH|FiqnKQi zz*s@6UHb*?VK861EG%vN`U0r0IiSa%aZvSDqIYdhxrquF^scdheYvr_MH6u;#b}k?_%<@+Oz!3fnrQl-o>21qBz>f*`o3lNiedw?Vf7C&p?x@bFg%?- z+piFh&o(dRK0-&Y_)Tpx*tu;p9J=!XMW*WRBgc+pe07qydp*|4^0NEII=7*#joVI& zTSx!$@JFqZf}FTyS3}O{tCt?-B5d>f^Xp%yVUmKx6h9O9$ceE5Cr9sKY!+ht>a#mroIhkV{ZK^5z&i7Q^pw zN%^@#f#BTLSD*$C&I-o(Rf>zPq!eiKcuyiH%W*Of(5ka_OSWAaI#>2xJ#bt8RfK79 z_WEuK7h&HAbsO+CFme9+5~CU3tVe)gqv4EubI(tx2P(zt;?V)K`jG^px#M&dPk#D z)y-84G9N?aza{XEfq5y(A87@vaJVu z$nI&g5q%@S$q~La+&vGDf~fumMXxZo`)^9|pD6tQcWJOP|1a?lSO0gH#!Y>ukfAzy zC6*z5qMpycE{%czPnSloIr;SBHaD;+;ugS$8~yRquk=^a?+g(nBE^i1MF+0ZLAZ*+ zs=cFokPqQIgGArO(?Kwp5au3Vf-m1x6`Vds-=x$?U+u4*+j>DEV(x3uP4E}kf!9IQ zzXYzGJ8AVgZ{j}wFthu;e>Zc9V93u%2O()r`t|*VfHgJf+o1u!6?eS-c|Lt`)itSG zZbRlZ0z>z1>MQ;R3d5Ux7N-6c{@orBK3gH=U1?Tx%>{OZjYtwV-vugzQ`CwVD-yJV zS@@8WIxJy1ow5J@xKR`GO_+v4gzA{hSok~$vqZG)|-Ed4hp0J|SNZ%0S zH|1eyt5<;&`$^pjO!d%xg1$4cx%R`!%Swkc%U;uvJ+6CLX|jW>onvmU)%zF;PJ+X= zJK5IBCw$o9h)Gn!&eVP&(3rx-g%I>~=OQl6Fux}5Y_9eqHAa)ze<|b_c&aT_Un=$- zV3@joSu)cLVR~IE*CB(Ikv%*0VWAD9n!j$!mfOcV((9+(e*v*ew0^GdRjsgl8vnal{yp#DM_r}4D*z)4y0C$ZE;Jq(*_pM* z&`_fm<$zV-`_|EAEOAwXb-LVPEZ1uNFwV_zVsD`V@S!vnx_?T7C2gYJBW$c!jSPH> zNP^}%Dcn76%22>Rr=6X=JV^h`kiRmSDIt~5^D2%1S=ktl+s)ZBt?c3^0q39l8^i(& zQb>CQeiTLhn3XRf*=aOd)4~Q+rJT2}d81Ql(336%TxpX{^^lQx12iP0;V5t(_hFBd zxBt!}E`hIbPz8HiF}d~UUd^kBG^-7*aJ73J5hROgS5mirPEimWn3~Xwhr(Q-#r&_V zs8dSSa|jovy(6!`y)~KtU=&5l&L<5dF^pGq!H$C-oM${8o)fuZZ4oi^yNr7*9R1r# zq{-rYTdC-$Y|0AACDAl%^6Zdq=;i-MMkb_90p#-)F>=i1#=bW;w0?mh`y z);uuRYK&F3A!CBV=b)7|KvH33g2R`c{21xG{MT0##uU-h9Nj0_-Hn1R&1=qZdU8UH zbv-R;WoYNh^hp5Df6J+0{TU7NZC!Un&<+wJuo@iIeJEciFi;yx9qEtM+Gf&^*4!4d zDPB|ii$Py}LYnCaLcg8)=m2;!?ab*Ba@`?!@^w@Cl1z!`{D- zZOwgQC&`xOvK+=hq|NUs!RQ&{%fjs2!~7$@$Yd8l=C3rG02jLa1#R~6E7y>a=ep4W zSv;4vf#`{h5u${~Q{=AfDQ;JGFktENk@rw(`2u9}z=taLcb~^p+oReeO;REEpgwvB z9T@d&rk1B4#N6a#j7cnlUD`ljR-C-KiC4~(P53G?*wrY|LzKWzk4cM^ljeA(N2ZWAky z3Rvu*J?Nah8g9lL$1rYg0WGE3J7;tBkH&N+1p<>Vs~sib%XvE8k(ehm8^RqNnzx6} z4@XsLN#}|jav9G*&swokYMlwI=-NAvD#$sE^R>w+>+4SE@^{q!sOqp?7Z~>!r?g1) zyRcYFi}%tSs-A(l>Kz-Tsg)UEsL303PI0T|gxM?IReu+Jeztm&^Pz-Ti((5pOo@vCnMUMOQ~;cU@04~*0S4>B}1FikS0 z_ii^AXAXeWgL3%VHzHjEW9#daz8l=rPdIwLt4?cmljlWP+}kl4K6N;Y_6g}68?LA` zZ9!PVTnoL@HKd^CV&~k@T>{XV3Qolo&L=G*^|_?zOarJ`$i+bbScuHCE3R7cX=%n8 zbDO)XQzn02jNBv29NyQzmC@O+Lx5Ug3Sfs~MUF-D3LNWF0-RZzO?w*6-6p)i)!vXM zf7hWltK_(ecPuIp4*anK(I-Bx=Mmyke<|Z?eh!AN(uc;D_nequ3yqF>w} zX@V}?4a&vWpKxx3T=_)Id-ww-t0(=Wk4yvdd>51K(NDI<<3uJtgVzF(#{k`7;L{$8JddE=4-Qv7Zac-a{YSrK(zDwP~pF+2=@OBTCi}j zbN{bglKbPP_(D8c zT)O^xo@Bk|cVqf&_WaTIepTpt63VsP;Pbu$x|R5VMUDtq zetddYz%(g?;rzl={5XHKd%mg5ikHF0a=#6SBCCNXD26HQF8FrcaSw2; zRLA105cY}=Ph7!egGC1z#opAYi}GlKmjPkrMOcNQkDIrV58e{%r{VK}+R`S;VAW#o z087-JuaA%I#-w@!sDKdi>1-Vkrdvaj(grD#5(IYbbJNh$$&`bN{a8eM~RXH~Bz6`Tt@FtDh#h!H-?56f2i zkU5eTpsgehSF51?Z`WiBdhJ1Gf*P0!!m$T7=1tFJlUs0>T|Ught&pz&%FYDgDH3xny9^9wGnu zTbmhyoSCQmlIWbIivpA#;99F|T1yU|t)bT1vFdzmMB-eqmno=lbZ`Q!>ve%75z;ZZ z=T*zkOED>Joolh#e=1_sD^=F>c>D9Cd(8(r7uYqL0nR_F*|m0@i6se@7}fH^%pTJ( z-N2nG+W1AG0~h3ICkRMaZNOrZfBm07I4s2?0Vy zu^e73R8;vGx%$6(m|5%AfCUBY6)(`KVTgKSN*&w)@U)o zW0o#P@=Z2h=iHB9jgEP!es02NS)g7swTq1KW*-q4YWF*XM+v0geB@(^*`z{54YdRaBJ_w+0i_;&^)@Tc+fQv!eKTfO;B(y@z+{aaG$^QF4@{ z0ESB$Ror3@+=s1q#SMB;9pT31gjO%Es{7io^b?|4Yvs!R%>T%`6ECCt%ji&{)wmg=3{Ld(~gi&m(W$Y9!y{+btbinRDq8RfiSwF zJZ0)nak989>pzLkMHT*sAL&Fy)WfbTcz(XZfL3{~KidgXa&85KWaUhoK@!aH@y#&h zpLIK~_q@*>4uYkRR}r`H6LGHBuFm$wSgA?}UQ%4fSWcra+Lb#=x|T~2eEg=X$?)>` zI*^o?l=eZ`z=ZEZ%zp0nU9YZG9sJMNiH1ADdr3+YcHTjun&BnLEbxCpI}wFG@P4ju z!#A#7BDvq;AK<~HEp0k?$i&3arq+00pp5qGp$R0!a<4cDp}kJfa6@+7Ga?;d-CsY9 z0wW<|Ubsb*Gp;LK+~7&(S@2q%jR9@O_Yc~+(WDra(+dRU2<@4vw_aL2$hV#Xpz(A8m@F75T{l)d%s^`7yChljBq&*sY17A zvhez(cocEih#o}Fk#?Bp$7-pM$I^C6|9FrZ+kAtDq~0C>=LyO2Kg7iUXUaxWwuj#pmc^NoxA$l={b;OR-R$hDzo?9eUg7=F^pqkJd8cY;b>a$+T>!eU!P zbEb&|)k?H=idGPNr|rbOM+&@*v=*a{H*R5KYa6x*8CQ;yU}Ph zs?ik&x3*rXL?8TsWOs%lkK^Evv88L`p20-~+rfwU7C@?WWi;1^N*3X{m5e zVbM99>PA^t@^GS!qj>Qd@(|4vB(eLD{8KA8(3DRsF4^U`s_^myRM{@J1T}=Pig1Yp zm8kXX-&$jF*wnmC@4vCr5`T!b;Kd>XlNYD1HZIi)xr9foMp%XSX`|+eof}xzY1%;P zCstHk8%iX=B{Ez#v_aK3AUPrO*kQV8iDJ8`O`RBDbfv0A+RF2z*B6f zhSv^xBVys!~p+^*?!LNR9;b?kfWN&-Bz>u{%f!JM$^6;!^j-&XZuR#Bw zxu!l|fszro??Rtw`Xpto>|kW9KOpn_ue(2c0XKl(lcP5`WSEYP%U)`W&NEOn2L6wz z#)geUy^laneox*Ma@Q)8f!hrw(XlMl&gYFam`uOIz`&8OGf#ipi^>L)1Lf*s&KmI0 z8^!r@UNL3yzT~Ey2nkFO)6#&J$oLb1ZW_MTsJEjhw=M1m9^PwS2qt0N6((VZ@MX{v zcqcUdTOW_E(;xTC?QQ(otHrO^qX50)vcl7aRehy+e6lFZ{BWN`boI@3b8=sO(eJiZe{%oK zHTGrt=JUKUeWTf3ks{Pp5Py90?Zxqp!kd#fX!+rQwRJo4(80%d(Cq2#9le-qo&^C5 zL+d&r2?ObxnlKwrWpT^y;vv9y=AU0+kUKj|wYs%z>+S8r`fcX@H2G-iA9wZDRAA-N z4`bSJ-}r;DI!dc|;KG?L53P}Mk!o@u{#jCLwbj(H-9;} zb8#ZkUQA>}As0%~z0g=eb~=pp37JkoVmgxW%^8`pnr4-2HU&ljVu3=B!@~cIv2%(Q zC0e)ivTfV8ZQEXZ*|u%lwr$(C?Y(UEzMW3`;hu++%%@5vl~k%yqsBkx_`J2W=kj(5J@&DQ-y{z_wljsK$`?3GXS{tPLjL^X3=za{K1ovW%r zhQ$N8fRv?$FHysD_mp^9b*Lfoq2`I@dpYNKeO82S1@r`~&Wmhz6PMZ%R3Fku!G9o3 zM~dyMP2F|p^qbQ7T7Rvyqxz-rk^fXyAK6_L*(~6dOA83WKjj4d|K*_b!9n*uyLe0U zJ&P6UhE5U06VcLlNV$~^aj^3tzuap6)OJO2TCGWib%2HJIX_Po9E%Xn@8 zjP=}MGaA@6<%kWP65%5&xRBax;F4gdvO{Gh>&{DmjsS-LgDdCz`m`}YAFL}L;kukp zQgH?^(k%kQVNXl8Iosw1)f;w8l-05qp}ZL8$}qM-%?C)k{93r0nv4iaTJ}Mb%pe?v zfP-ag8t?>e+MNTPQV4~$u6-OtTIP8w@=r>b)icWcH9{s%%R5bVN^d;LpYU7=6R!xq zvOmDe3_*KHKGW}Td%+m%KcFHI%{@%jXD0DA*s}COz%c{#8H0cMWDGSB|4_9pSowL2 zZDm+ug#ci{l4%W=LCI7`1r~#nJ&H9JkQXcUR>*d0&r@Z=$yW=`|o45HBf}X9^G_DYAqB3?LjUEGR`q zR#TwjH$JzAw&HXyKO{W`H(=7joNz!vwVcsLwTy|YQ`mwoR1K;0c`x^Q*Z3T4ehINS z5iAM>+9|2WiwF=rp5zJD0EHHtOCIcZ2tfEUG*Y1p^o$f&6m?WcPLMI#9|uUlGeA&;hX$eev=v_9B@6)XdzXP0iuuh;@e86H(S?OPg zCtH-=x_F-0PrO7i#TBEJM}+=G`*)2tpc91S2>@2Qs4&;Xh^THND)tXi9q4M+2_@MB z&l+Be}e%IXOmiVeO)W1n8S6KnpcCXA@7{9iXrx( zwO#6t&n1DSe~wSm!riDE_-c^yc4a-5*tHF=wk#;;o8SnoEZ7-=Dirp*yo^}8(IN5z zWsP*Dv)b92W91$3nyo8O$^&fG^8ze zTcvd|=?dbFbz8VGc|z`q(X$K)f;D)Qf_`}gXh}X>1yU6WYILA)&|<*|Lqp0yOXMp+ zs}7vttZg=EF{FI&Xi*r^#%;>2?I)JT4MU5}L^Jky{{0n=yh!@r%9V|Q^?!RiOsuT` zrMIKa8AsCrJA0=7gpZ+FD1j?b6u|y%ie`U0VjN05)U^P%`-`7WgM=VCU*UV?65Bd7)V&3|9=EeO@oq~mFW9+KuY-<`p29>4 z50Kun^Ow50zP@o5P0DV_-%#n_oA1YyK6;bOe;f}#M&ppg%ZFQjy+L3VlIUl2fCE&$ zpRc)-wlu$|B2&E`7obT-EFmo6WdKkygpMdiEpsbog>fK)pkNvpCIjQe--BK8ZX`*{ zcgzopasj-?ulL7SX}7aAeN)UDRI!TOst-IqSnH5M%z}J!15rs>LHM(>{TzEacx8pC zYeCC`=9@h@*I<+bLTti``jFdAa*9W%@LPaA@?LpM-_TcWhKdW+UfL!JX(&C`Pit-i zPzqgxLhL__mn<>%C0oXK0q7Y9KQEb2m5t2%ys|Shg)@JW+r0hE3L#SuCUZnTDRqEB z5Ok?9P%kjSWf)|=r+9{xTf1C*qx#vI@%HmP$cQl%QuO?(^D~DBSN1^jf2 zu8!iCii=d?-2A>tyUxp19)vu18uTB>C1Y=wnk|L(nlR!C1v+i-u0aD855ttqnP%@+ z+#wYMN6596NDwBd3l>)Y$kdx5GY>7xi_0+)#LM7wrXcEN-Hdw>C^dEuTD~1hY&h)1 zCF2eN6PfUXu2@7QqzO&_i{yvTMbX>2f#etC7`5VBC7e@}oLS0_*Sm z2HBRu*X80UqBuenAtRQ|AuSZmORe-KD#9ay^<~UUY8r@@nvbg!5*YhZnZ|f%4#ZiQ z&`0)=Dmk5JZhIivtyCc28SiU3gocC>9U-Hiz8(FyE(0 zBMD{;I_nrP!*ZdBqiQD`c6TNG+hs_?R9g;GX$F{ZV4EI%8T)qwDR#n!2i9_zESqb#*ALC4|E6Q;Hu5tg8GYa+^plIy zrzHsps`nJ7Hqu%Mc_qb}_rJJ9{mGj_+!U+Am}pfo0VXPD2^WUbpMixKjpcXZi#}J` zOTbboZs*Jj*^5R+A0XV@dDvy42?o-=0s#i51yx42rPE_?L+f_ekbZF~^fY8EhUm8D z9+9ev#HbY;-&wVcYAVrsW1saJm!^rdK`YjP7BTah56qB;7F=5HA`RkILf+aY$TC_S z)dZqT<3ti|18pXogDDz~%z-~z-fZ_2Y-Xr+gY&WW!0o9kZY}PMI&WC#;vDI5)w5Af z@VGQ(xGpCAvPo#+BRSGH6AH=|QL-QHlPQ}#DSLGPF1Z(Z_@`lc&n0A%G!0`p-AvF( zs_BwrR-T(Q$G{bt`7Tv?94|)mAEu&0#ZVpF$KfnLfuT;LgwKYA7F+e?8yHpLJOttL zYWvkZftH!YL{du_0#>~+o1twmb^Jc{ahc1t+{*1$&yW9cCRj zXS^zxy*6)uQ;v(8+gdd66{y~M2?fsLqcViJA!FS)n0Jm8LG4+Dqe<5U-L)^?b8_rD zP?q6DgXdTtVTP`oY|kiKFLoDJwM#$oVYsGESP|_mk8&9iN($vwn75(uH9l`*L+ZSH zw+qp=kb?4{`l1O>DQ-4X2|&$+f@5GN`%}R??6b z?opc)ou!4)`(yj;2>t3N?3{@^1P<#UYy*7bm54!8&{E*FN;*6TqPm;FTL>gJ1{!Qn zP3)Z+LZ3NIun}n zUv2XZgvSvbShX%Iv)T}Z__8%e3XZ#9LtI&}qX)aZ@s%@I;W`z|{7OkZ=Sw|J{ zA!OqI+ZX9JAkcXq_2NEY7rpLSkE&LE%WHb^)OqK%a|~&6a;V;Cj>ZjMsI}+cfA8Zw zW6!B}-+Y&xYv42tF3eAS7q2PnGG+F<2G`roa+KB|rGZk|QY6H+)Y z@$KoA*-PLw;9m$B5bclWgR4$E49vj33=DFXE3S}h|MUbeG`Il2aOL%4K^+q+A3ql74*U}iGe29+IJ|*TX(vEU_$q6dhsNamhR*7w2Ct> zz4|Pi4pm~bc`1r*5KOO(kv{^~ zC;-4zUmEm=#ve&A;1|x`K4vE}SEa!I>nCU>lIE-q5-6Ot3IP_uPoSqT%K8<~W7R7! zS&B=0B!@0Fo&Ey$N1!WE!c2qRftE-5$ur&T0XPwISSSbgaY-Qh4Kby({zvaw>529D zEE~Kc14V(t(FhMKd^qS8k-(GTCeI}ALh-NVH0eU_Uc!BkrU&$Fv7*UY8)FTuNa`yj zZDjAjh+B7<87KIsBoCObyT_HX=K`RzRO*hMu%~u7r044wYM#-aIgN6yi10mMXqQ60K}WQng6n}y!5S1fU%QSkvC?ba*H_L% z_Q(zoIjZmtno24pg(nmrH8N@XpM)KB$;ss43{693utdX^OYo0S|6_0$|ovCVBx9OK?-^g z-1)WF)3vd)DL;L!jG)D7iH@(UHS}Kq5GI@LLJQQiy`P@1hX>`T<_gfa&Ui?uQ>{QmS$R0Uq2lr&04H<-woN0?Rxo1ghK@>mu1HOo za6=%9b}DwysQ*b&sh6JyQ8Ho3Uvc+kxLh=Q%68A)5D=CM+>zF!L zMyTv-_0Dm==yJ0oG3o87utdurDae}f217fyBm^4^P6}mNg|YMHrjGLM zqq0N3?+vZVLlS$HKVc*ppB;#*xcRCa^|g$vN&Yd>?FGS-X%13e)qCG^vY@1hriLpA zg?)W$Gps382mVerQq3JyV#Rn~qnJ(xQ|S3P3Z=|R0JUPCv;2`F8`Lw4H&Rus?z1o@ zJ5_5_fjnOeDx8>-IgRQEElq1XKzAjw!_;>w`|NUY%P?`IKQ@Iq%{Oh{ZadBuk^@;hE%v?1#`W-Di@Imbz_sOjmm(9(B&l0bpB_Ah*1*HtmdXiXdW*-|mKO@sYCFgB`;`r44pX2lrV zePyB1wzJ@94)S&7>2b>iCWRadv+C4LFxz2$O{#!j*UMy?F^y9ZKj%NA5n)=W`p#?^ zrc7~+FtXt9>PhQqi;azu0SmZsSqlQTb+cKxei-BhBPf(SC4dx7)C-gpd7c@MHmJ{o zfBdw0_EygXdi(4yjOJd+mXLT)CUf$rPmz(w$;sN3xfCJELUvh&dD!=_d9>_CbHm(# z7bjx2a?Nq)AcYFCVxR<=lGl+MERx|iMO9QVtI!@ieqOVAtkkr8wR51!F67XumORq0 zQ=^)^(1g9r8O9CqUObGTSyDnJ{rqW5&LVn56%Di-mNg5SS6>!z&x`c@JL73cZ7keF4L(1amEc){ZhH^_v74Hw|^(eL&pWW{Zs!MP-BE&l%zrXM4_teYz=DxBM zvC7dNCNl6@m}=Zyd~@HvJz9mfNpGK&mX|}y7X&u*Dz!Dm>p2NO4k%L@t80fo7-Uqr zk9?X{aWB*{7lpCbY}IW78mT+C5bg3069!sbrnOca*f4ash55E7iXM#UTIL6FH`G0E zK31hV%$p8a;V$y(`i*+8Sw5E*CR!(T7qSd(1m@@m-&G?ADO`>ip(3 zvr?uri`E$xN0ifsgKh4Yp&7>pbP}Cd?L|8-x(yMQDJ>nW6{5lZJ~b*gf^w@jr*rvDhV7%I(PHi z@1khizH9(Mm(N^@n674qJUm&)mon8b$%?Pg8SfSS|EfRLpwmsQFlvCyq$XLCY=ARZ4_PA+^kTvw=0JD<|XK!wargSk7T7UaOR!fi;s+TqWpF}xh#wr-XL zn*ACXb^=SG&D)eeXi%Tvzh$+6@5p~7GfB-n&gmCh0sQ{r7oXh5&87VU!sMqT{3p4` z_P=qzOpN~+!2i`;`(G@KgdM5piuwUugn4`)3<9*gQWbXE2CEa+8*AO^!SLf39P zf2eP_SS7WVS(l<@)tU2SZ>fy4$MUWj$Q*PY*MF%>IA6b+{)*07_p!{iY|Wki8|`*$ zi8@e3nR4E4U#`#h=SURI^vdi=0o1Suw^~^6i7L#3+?jg|js>VE>*g($UiR!yw**`F zsl3s-TfV#~dh#Cqi64Kh;(>9zIi~(!MBJmv&1ScZBC4Q!A+RkDs86PPT+vW-bP`_~ zPX33~W6C`j4$fCK_c|*TJu|+>oa*gU)D!@t&57I3?nYeIJ?w7tkKy<=k-AFH*pFc% zqeju?ww+UT%>sa}i!&eJjac9>DiEL11^Pn%bXh-+TDy25&Ykv->&H1)oCS7My(C+5 zUuBPf^gtqHC~N};z>w8Shj3am>xmIJ+=MHG>rCJVYV&}XAe2p!E{Q~u$^-KIPVciZ zx5?UF8dLR>kOsqiBanBw6bjKAs_gW{n6E}TDPJ}WktyTi!3E1R98s~e+e(Stzp5XG z({Skzrn9Rvmut#0i;{@X}0;rx7$Np}Yr1iKj4t8p-Yec8NypX6mzR0%k0@g)V6 zv@rI`{xeh=eHr#cf>KM{SjE;jCs?@n8f0`ZnOd1^%an@6wKji9%&vXk867Z-f}h4K zP8cqwX*n5e(h@?MGAv)EU2Xa(I!f#zGV=-t4-VTam7)Bqc*!azzK&O}>P%Y8W;3c(Ny}m_r0@#P;7grKS7K@rw0_o`YQ^O=s^|&1$}i8K-Kbq7 z`qaWIus8Mo>rQ%4_`KfhQQ58Avp)~AXRldaj##~PgiTtM;~yc{peX>4(rBojuYIdWar z!JGL>uX??5(fR_^Nj=9hLX;}UltIm$cDlLDJpx9$o+(k#%t6hISJE&{$6dr}9NP-6 zYuq%^D0iM->jfu4R8pDDe0{P1pDRdJ}L)ru^Omb_-#t57k?OrNzRv!S$ATc)VzjK+1Tu%){#c|UR6h+f*! z?mNUppFg)`c6mgv4BhJUSZXAT55+t44xXI zz=E1oFA7zo_31dt<&{U0SkY}!Qjs)Ya>Gje?agmNXTg=1W;(cxG_2YR$2b47%%XE@ z$iuz~$~w8QwCbj0fd}05g``gE2Tu%^QdoQ=|F!OVS#mdb=rUYinvKyiy7s*}OM$PI zCC+A3X_h5gr3?Vge~9$ypv}8iW6>uHh;}`)+|cad+vN4*O4+)G{1rZt{GGprXynsr z#l%c*XThk(i9_tl&VAaGmCLvS{AWwq9_De^B#h#=4G%V;PMD$jk%$M#z+CvqT_5jP zo&ZJ#*-*!j_&ZOsQu3e@C&w)TzJ}R;YwDYSkT02WP->4Kd23`CC8kr+vmZ=Y&>peBCW3X z`290OM^S}vRxZ$lqjOde+FO<(#VfvqgNB!3pfZG?Uj=KS~)5LZ~3MBo$w^Y3@1R8dy*!0&Gzqql8v!JZYV3d2E z^0kykJO#*KnVB?)XV6SCH2UGkX|d!?a%?(=ApW#0gJvn-6ULcl9IEXO>iRrdpena0 zfR*QP8SEJ`A={%>`8dtyyvXoZZ|*OoPm0-V8PDYgZ;RQ$9IGK?OtpJpw0rzvl^d_& zNl*ALaw9lTtgL#v2iYPShpx7q3FWqK`u;2`rS7o8fiFypnw;xllHl?w-#2Ake))=t zXC(YUxzw}II9ar(r|K?Fh(gO% z0<2D``_Ysbej8La_&fyQi4GF?5Uzm6f`WCmNpqMhBq5Y}-9pYd&O$RH?Ev6r|K@ z7C$@z6C=O^Fu#9!^Hlo}9s@x1T~9m!Rs2!A6SR7<;E5|JM;d>{RH>Yvnsz;{$1Okq zozJ!l*^ZG}C%J-d)-ei{aMS1QHyrRcvf&7jkqqVKQ2t1!*>4`O*b`u-f2E|m$c*OW6iVz-dv!fdxM+kYNxkI=Pnj`!vc-FTcb zOwb^OyxjK*qreGg^j|X1BjuJp?2^tFtbEukBA=Eg?9U#NUSN)n9#7=UuW#V~lO*Bz z-_uM+4#xj3YImb08@Kf@ss5>c4o@TO7^>et*uSYsKd&9sgUX94E62(5`#XQoCL-0S zvbBZdIPXcTbUb}Doh3f${l<28aAWVu@7)Oi7ph4bjkDVa7l_62jhbz1$%;Xk4#xOz zhv$#`sg7l*oHOAWfHUUD-eMUSUqJn`umZdwtq@Kg3{)pD+cWo)OGKVQtb8x+_T$aR zTX0~}B(a7c?yvXnO@C5DHs{UnGyYB6+UpR1*q=_2(q`;tCK-FiujlW5Yz2za80=zW zx&6DN+k>lvSJ!18^+!zq#$d1`EoxRkDa+Di+-5MaQRDpNBb*6H5;GLeIuhN;-lU;R zC+j1SVlGi~%tiZ?xi~vvr?V;T=eco8*!B^ zMFW|F$~g3yg%hR>H_9SN3$%@ZH1DDgHZB^#bVruct==BmZ1mi;B*J^i*GrUWHj$b) zfbB5`$s_wR!VE%5Rh~HpYzR<{5Ke!IAxkpu1%nr-9{__FiQc7(kTeK3Zcq6nMK+}P;cwnPY- z$M_Je1u4TAz_0mrQgpd8!DN=}_P-go)A5-(UF=*{H16Y5(p7; zg<`#E0lOa>>!ty$P2YE&7W*8KIm=;XbGt%W&xmLs)P?-3344d>dO>aI?qQ@SYW?@Qw z6H$t`lIj{Aj_Nl#Fim(;08xgeiC@ z)gM?#O>>dnY&+Wq+Ydk$nGTo1;IvUD6h}d zgg+1HYRgUdP^JU>P81r(yvr?5K*hI5mR*Y|m5vv61xIffhhz~p@j^$5FcQaV$UMafQ;udI}@qm?EL($yqiH z6f|M9tIKK;o0A#fMkWI~kRzZIc;ca~`o1&}Lv&KbK~!rG0Fv`37lz@%I(9!a&x?Q;qyc{{nA;f!{c2CG{*x49SM zjM!lCOGsxAqs1389e*cG;bg|!)1O*z&c-Y7)dDzO|J{?Ma?MbY9`s}c^}<0ykt#Z^ zR)a>CIhv#HQP!!n=EHt(wa{RI{i%;?!D#Pr>Jj^2IoroXSy^1`&XpNJ5=4jefQMS8v?MIjx6J0^ZPXa%gFc{KnH-#0S zWbzku#nr^_fBMjJ{)c~mCXW9uHZ-Fx9k<1S)caa@hi?v7r7;3N&k+B281SW4a1YH( z>w4M(j{Enwex!^BqtvlI4 z$TLYy?8vn7O zeHe}!Jjz#&g7cs0G)l(`4fGwtp@tuvW`i~NC^?7*Eiz7to38@?dsdg zRdFW0U<`|apJ#yW*VGsd7ddF4+72^mY3Gmry>58O6~^AXLl?Ag*cSv*Kf7C>IK37Z z+Y#>`xmAplc{rUMjnt>zgJw1(h27B(meo4>IbS+sR+tvy3I)nnMl-G8I4U-4tm4l* zK;=!Mf@7{sLQW*AN<(=}L9HzEf>$(pas-=Y9dYnCE@$~~QK)Ew*@9K27}O+E z^-PquP>Bj#e>a-m0>H5)pbS!pjLNOOlfQ0}$gLQbvlfvR^Y@s}6<97!h~3^gL@s;VJz=~4nT=FG#zU`4{^eB7<%*yr z%)@06E48ITLzbo`B*E~~&dR_*P2l+$!s2V~kc=aP5ERffQN{PKMjh!$n~`ix)JIu} zn6HwwFb!*VyPZY0vRqhL8w-qJXB#B}pK%B)@^R{EC8}1|5=heFsGPT=*GapF5ek`7 z(V@ekY}=|<{r~XQ9;BRD>X?v1zOmhwz3$l1di8>zJ>dnj=NGU(OQ@J?|M@SpdrN7m zB}xeNiK%6&DGY80@DwVEDI_bgm$^bV3IrR~UPp8xLQ=XtFxXf#m$zW}migB-7!+{> zB_CSw{L(<$t_YmnnrtY_0lgMK)+vZmxFfpQ#|-DY?PFkxSv36wL#eQlBdJCFmcbrw z(0i*bHyT<=t)cT2I*~cODCKN%RhtOiDc)!=iQhLIGa~+%UK4mROAsgpR~-cC9S%}O zFS*zqmw72vh3V#Z3u78$QG6&3`l;n$VOBm>C^ zS{3cw`Y8rQxx~5Tb$h0K_=Kd%>N>c^`ZFm)3CiW+UwBi{QvIE#5K(1OG98Aslgfi3 z!ZzOMV-5*!Q}{f8^Z?`794fw;;(V45OT?gq|2B6jZMI$uZAyggB1=pTQJ3C5THqk4 zHCL?n_gnRJY@n#MOs!|W!DG}7M-93?p(t;7RVfMRjCcXb64U@l{< z^?6Jo0b!qjSk@_+Psu1?|8#ttF??=TubGIGlz5~+ImC(nVceA%SUtBi&pacdk4ayH zcWm~fqGKJ99)Ne-S32tc)7Zzw)YDq*Wr90Ganq1>B|n%=0ecU@S(CDSXFqH)4k_P_ z>F_r-Q5M4@T2(CzoH#f35^#8_=N@2qX{tWTy>oyc{~iM+kI0kY@PYzQfM*9AUVx_u z<}8)SFTZBhzB=KUW|vgZHzc~H`k3YH+CKDkZ}=}yBS`P#~hvV zcXD*0>7d@a!xdZbssyt%cMNt1#eE@V`;uZ<4h;I#_U)4~XQlz7SmlBysf!r^xNQwhYA#4o%gzwGv7gi)|D=n=&3`=^Ej{N!;M%F#5C5CY} z=5o!8y1d*trfbFIxfe*LQT=#ZXqH71H#Ld+kQ=0HOni@diHk z0E*NIqP6z??hyNA6V(QY7NB)jXLRXwa&n6*uTCHRfQv8|+(H)u<<#I3^fv$(H)j@C z0dq&Qe+rX;`R6sGA)$5@-54D}$6>%&)GdW%BWuKZcOl;ey)GDIb5TmaA#1Q4GGT{P1xOhG*l#lqD|8;j{B0P zO}Vpv7+?Z5P!8bkJ_GkNcLlQtWPu@e`AN37@7aO0>=}riP)q6yP^IKJo7+J$3GNs zYYC5_4dw&w7{&OMC2aZ^Ur9$4jnpHdi(CTEvWv1ol-u(_=?(4E8KRngUoD>>PuL}!Kt~FmqcMQz{t2Og?KzCO z753DCMey!~Oa6hD5$OAFU%~ZccYZqHDAD*u3MrXldbHOt9HsFgGO+ApJBI4{m2;3# zr4HKPk4Iav)!y$sifoyjHk2m!|4Mo4UBXl;5(>B#(sU;BE4MuCLm@fq2~Oi)vni|2 zVs8s1)QT4zpRBZw&O8)aOtdyC3qeyvTteh?_~QaDZw5VQqMe_XG5a}%ua2X^v5=5f zY(Xmu-#a)TlXMsZmM16|O+{oF2L3ja3a2JA0|HCkbxNKnX@-WfVW zOxElVmkdl2GL8Mq zXo`}oXt8xmuY-C}n6aAaS1i&HmcgvJu8APf>dz~y#)05fhXiVdT|=WO!%ia+cQVd5 z(;*7argz^TJQ8j#r`WP7sP{?-pdDlFw>nX8a2tVdmuvi8ryV}?Z9(hDoi=-f+k`0e z7i!{hx4KX#2R+-EoW62)pz{<{mkQv<7uxp|7q(shU1=3_iBy6Bgia5p-%Mr!RRn$k~-exl@ ziTTx<51>~;@JvG=64bDK%>AoVZMHC4To1Wlj@n9bi?OYW01E|ek@bdq>;*Hc!$wGu z1Jx2%7hP2lG)c?JPG@uI#EhA&5a(%GfV7(5;X(Y$2s3@5Q}S#A*;$SSc;pfe*^-=_ zRrypcR!L6wV<288c~S-(A)ymz$b=@b4qTzbh#4_Y%bYeANMi}%K?GVrtFU|A}>`9opC3}8EfD;cE~lm)0DdrXPT%jJ`wCn2}RhFog~ zF!Kejb{5Y$-NuJ;bS#KrzlrL501eOT`k#`GWtHOEbfe9;Zp7;IH<@RD#c_{)ZdgXn^bdUt7SY@S8b}lmGT{>RD>&uGVZxhz8SuY z=^$Z9`5uQSDCNe+Lzhyy>iZdxa6(TKmRcEBLV%A_yS5%80jN)~0FUEXh`vX(T2zHLir zH^nFbCwU%H54_}pMRvjaHWjy-Z@^X9%e3c;aozWl?Ly#-#5z1s+%+w#jCcapwI*fo z5NXKubeiM)@GO7cF<3gWNO7%73gt4<7%I;#0w~((GksA!RW_N{1#4eQj(%XB z8QlCsl?sGxfDx9bvZ+(~XR7MUk>BG_4!?1cRyH{Vs{W)45nD@GqgQiNns2kW zT|)q!|I3HJ7V(+*KBcnQ*tJ@3vgdHk3NhWT)mZ9e}Y>DN_y z?yS%1!dMn{u%<6I)**!gi7vaZ{+sA(pzVU=4=PrVZw*6c>${55?+N zbye$!le7@}TU$AKc70x`4h&ON44vFvdI5NjZ|Hy1lokwtQcxOs{M6f94slsO@{go! zXhFZwAG-_nojs`fC$M>J0eOJGb}=BG#MYj-GJbLQ>gk`_zckyAbI;#3AatsF0e=TB ze!|M^Y~7JsB|-x!Z_sQ=id-U%NfLnQLkg%R)s+@-wWJa4N)~(Ub4+06C4fX9q_qET zN|0Zux8DBgeV9Y3_C7Z12`qLy;dDU1r*rnV3pqfA~=22ghRQ8uMO)?H8X=(%66=n?T(}@uQtHEtSS3+Vz z2J-}@R49ZT|2vpiC}dG}q0Sw<05e36telLXmQJ3T0T9Fk*`|>5uDT5cEBa4UUBF80Vsqj!cTQS)q=Y{>5=eD!5RhIQ@yQrJDNoj&UL&|I`n`wsWYy5n^ zCp@IAqsVdZ)R=NS^&u}2a60Q|m5(IEK&e^>pinxLWoTXm80uZbB!~D|*pKOD)HY}= zZY7N>7VV&81Ea&>ioDHQJBrF=`>9fMmqRW~@cqyXg@5>}wk8FXk*LXAOb{U#XTbtS z9*~N;Q-zy6tXdyj(bZ8-(ggRZ8kt{;VPE8{aLAY;S?AxBI^wUzR#S>hV-vY8a46%) z#}e2)9*u}i-Hd9|mdG)KL+U6Fn?X+cM6-`#X0;C940eCl3KdQ^B}uKBa^*~#7gr<- zC&)HWeae!{M5ww5rQ&KO}LWFY+@k978&oFFVz8@q6;Z-&KMh=_w}q9gryqrw504HdEu z0bXafkgo10JIrtz7HU|vuKQqBPP&n}T*hb?tjfz+K}h?p;0QkIXZ-vWF9hI(q=oe5 zYKv5n-dwwKyQW`OiVlS_HcQqwx1nI-2;|B9&=Ch(((KY$@?kU^{vnCrDW2y6C-rAc z+6!IbON9#dP&Z}T$RnUX*j?=krRmz9tSKD!EIF5X9K=RKb}7nRcPAe(;2`x=i_J7t zObTX2NtK@vA(xs2zzpm|WVBV6S>zl3941aA3a0+$RKp_s3>U}C=P2IIq=33!k% z6Mmd2;g~<5_~Ndj!*sIz4v*>y_ve-W?u6X)Ee8J~TlWWD?^{5ZpY=QR=kxXifBA2i zm@hc{Lt#tz?HLu+<#z)yCykJhC!(&|Z=L>L;A+^2L{bPzYcu#r_#ch=B0Y(Am|c#N zE+l$?yA`34>Q8{O9!>3C)y2MH+c0tA1ChCt#hqAGNhL$MEi80flYExx@|f5Pz?&Wc z)-2EXMTcBvb;|nNxgp$)29g_GcW=n=PD;D;O7_>HqawdTaJbN}ZYCHHReveB;T_9x z^XdmYlt*JsIZ3d!ak@t?lPhZ3*#W>t$H^=xMq+rqj^pHFjrWegd3sbKr16Ml?v}sr zNkkGKJ6v>Jrwd7z*VN^f@GBJ@gwepW5SNT9X`UTS9tBQ1IZ5CrTstQg!mP~4ozERP z6yIRAjaSB)GA5OnNMbIniGFQdmLuaiEnHzE3joN;8L%_mJW9&)^Ovsc*RTx7Y@oFN z4iplbl%pf1YQ3<$z)lgDy?PrE6eTiM#Yz;#Tt^jlI)T|yRyNf}S$5Ys?C?MaSt57f*@Va7a+}9-B7P5l(Lg!CKnb{b9J2lzv z{_x{p82%r|-YGbDadM#kO;@arU{`f1UcPR;{a5 zwQk<3cg#7*d`1K=W9m@bwvi?QEaqK)3jIa4nmzV~=?Fq>1O*1Br?I5w2t$&1c|C7b1b>Qyz>TkY9 zMN;@-vW9j^S7=o~_2=<{Zl%5R<(Du|0GSEZAE|{PbuE0GCyDIb#VygXuWW*W*y*0? za%(4cD2a@qIueeYAkb)1W6=&U`@*w3%P$Q#TINp&clBwgm*QCYm`EztBfz6je`? z`;qG*7GAVT?A3+7x@1<;R@Dc@x+p;|5hBcv6!`56SVh5jmQop$HLSdRK#JDy>is~q zdQcVz>6Fqea~SU(veH6PohbVa(+DvkR=tkM>~35kgjB3q9CDOt8{& zPVh4V7)S6x&C7VFi+@^pHAWAq9B5+1SOYkNptBpy%@4S690)`T&18`4j2pth*r>xF zf9?(L>X9lqs%%xAnfAh4lrR16X_4Dx_-6Qw zr+$;ZYs^TzUP@CvkYyzb5B)~^}VPou9ma!6~fVD@|^X!0t@Yy={LW)DePUj3^q^c`PA6JBxc z|J~P2;{MC}k~mGs>izCs+xbs}=2Vt_E>KnKW87ll7oOom1>=9xra$nk|AX85e;3VI z*jWEN=dsp=El4Ze*6|OJOhF{V^H)Fsd--o?x5x|Hjt=wAvx3iW5sGMLcuQ`~4F{*j zv_V`cWQkjc(YccWJP4nc)6<9Bhk>=({!0D+gS~@ikQ?}n@4rWx)41IJj^J>3ez;%n z1uUFBvflB_!#99er`_+T7i;_*$lX7Ey+GKxJim4r@}s;C&bdF>zFx9?C!Xi8uU@3{ z##Eub;kRRYeLp^mem4@CnJ2m2?s8LSfUB?l6K)R4VFE$LWr@E_}chb4>=g z0Mt^(fxq1%6nER&4aO@3o_9H^jd_CA1Nf{g7j;TpG+L)%%QACXK>rmvI?}qUSUPd)OvVUJ6|)F_Sh|p9QDj zuum2csvkC5^b%Atu`GekG4U1o9imixxIkK%@TtsPsj;Qyhl5R3n=1w6NFGxS^el-!RU?aJD!!T4J?wy+%X16iKpyU68jllm`{>UT9)YLEK@;1Dd)+9 zDUXU#=*)nrM%2-;zun>?%$BOZ8uEMQgy$%NMBLE<4V7J1C^~OxUt@NBzTBTn?g7!d z4zuhZ*E6LLAip3;@!;b==5fBhE^po!{D_x06vu$gkE?W`caxf}@7KvoOUWDCp}Y<1 zeW`P|kX0Va%hDeV-V&EO+wLb|l7$uFuxNLAbSl}wJ&5gvQJCJI+@l#xH-=&;6Bf9# zt3Q%@b*Q=sw)Kr_5Vq@l8rQM*JUjv^_;qIjiBOts-2ERPb(GhKO+PF8DvCACnQdDz z*gd@V*}TGXZ3fwo)Ekp)2&>bdhun2}Mi?B^4Yuy%Ze5N2TIf-_b-7CtFq3pGtpBi_>F_yd%j8V`ZpW55cvfL|xmGFcn@l=p~%Qxw@A2&g88W+5HBweSN!^fC7& z_3({$GZ1vq#J%c9BEvjmIB+2^sgHrU0!BmmxmcY>@GlrQc7`vNF({09KNsExa!@X&#G?Lk{R7>)r(C&sQ_E`BGi64(74C6TAg+7O|ZA!L8+NgJQ8F3+oiNe0x zgsZMDr@DTw>3HEfFj~JGU2aP{s*sa~pE@7S)sldZ_3Q|u-Coi>T)v>e;l#LDiH~uf zHlQO_ZB%HUxj+2&dnmegC|U=ZZMjylEx)Z_KZz`X@j+hUkRL~osGZt2CE5X%nX&K*ndSx z@h_je@?CE-*5r(LYWofgq1+hR;)`!^ZkB0^Fn1DeKp73G>~MrV3MYWxv^;-Vs8nVE zTH$&2l)kh;DXbFNR>n6m{-sR_a_GpN7LxJ+=^e7Dd zoF0Ye-+BZUKc^>*^5^uF88W93#T+o?AL(!R9lRWZ^I~K$YO5X|M9(riwjd#=z<2VU z-?qrEyE#^SU#PrOETx8Sp$slO6)F#=9hB!;a)r)Csp(@)0k+cLkSC#fCLP(N+qtg+ zm0?>BcQA}KelIbnfnir7PjGEGFC8G8B@naa5M+RB?hDiEV%vblW`0N!D>Z+u>-NpM zb5-|WeYP4$q&=0q16GhNixVjmQ5#i9h|;r4DLbzbiH`!)7cZ!3WpM{hY0V&zWZeHKYBXkC<)u5;q$?=z zP358)qSgEOG52Q zlgW`=2%{NS`HU;ZB|pc;%~$siSiH74L`+rvmj+U-CqJSf_^Y0l9!>hHf-Vi2_wku! z>q&DPV!@7{78G2IR3$*)!~OV5QtHdh?`L}YXT)B2a!^j&PR=WQM^xOv^LcD6 z*UPQ5o#X3C!V89k1Ipd~=>YutZ~R-|WVTZYh(2fc;pzA^cc)5(E;rJ9Rg>@)^p$IT zDLWUcfcwYWHp&KceB6gmgnaI#_Syxf27P?|p@T88^M211XtH7|?vZleyY1`Kpt7pK zNPOVU`PwIXghArPBNRt9VNHuXo~v7^wG>?-@Zbqf_;aXQ5;W%Gj58tiOF2We)q8)ffYJ*kMCbq~A3Xvu<;5 z%sTduQqFDIa4F4)#44xQo?RQTgP&Z5*Q*SDi-~&P#vFCrjNi0#1TKbw4Pk;dZWP~$jmlzLk}yt2ZPG4$bG6AZ&WDqm)decra}P8vDzvo)XLz$>@M zY`><7MfSDZuBXx4&T43hWVEO(GNIm#<=r015<4u4O_8B9foTF8*y5@YUZA71V>)4a zYZ?&1%bNM(s#Zn+{0rW>-*gF)uQDOxJ3zg}B=~a`82CVNF^Q`lEC~kDqN1RBit3VaW9u8%hHZ4jjiT1N9>!sBRi_3dY z+cp@Es}0T{qP!TczDUP7(G$#) z9!aGLKxBAT4{i^6!;=Qf9%bZLvj;Ewla-5P#p>4ZYH)v&sBFEl^?u&<$Yh!UVLh}# zs#!x>4xV~En#n`S_Gy%dhXo#A7ZWV$M^eoTKwUeJto&!)DThjNYEi z2u)&kGW2jfn9_da2F}XW(Yh zb)-(C4L{;AJNXG3O#mEYE6{1~inLGdD>tckew zJ83!PTp+Ee>5DRs7?oAw@?r}kA+2c5=ow#pzkwx|4?Q6X83JEI!P`Wfv&K7+xccLm zKw_c}RwCn@T62Y!ouMWB*dl(Ma1$q|YIVd1Cim~H2Tcl7Qc|n-dC~kv(u?kL-FZnO z)u4V_VG3a&T5%znnss!tbj6Xq#WC_&rhoRAm|P7vMo7$hxAi>?VR>XF_Xtw;T7^DusORCdWbrA|Cfb#^G35C}8s`(M*%Z zl3WAC_00TWnj?yZz(CBU=+GUl+OMx&g*ObScBVQf{lhW0E4t|eHMAk~m}4qd4ps~) zv)+&dBG9xKEoVN3lfsf^>1#}sHz7r3K8Pzme2)KQ^>h^5`D!`|eh}ZwZ&$i~n(scv z!1%naa(>sFjxa#H?#o*LUmKyEWaS>FhfTle-ZbQ7B2+ z3YwN^%_K)J46aC>V_wI?V&;8VC-XtA7}_q^!VvWz=1axK6kKSmp=o&lol5D-FBGOB zkaxq=5tw{GV?Ak9n1#YO!-j-zAYXgEsv`DTG^&X2(4MwOUf;R!t;J$aJL2Ol{g~wy zODFFFB{+f28odNJP5>mSBwz9C`P7D&YcF~q``6%ARmN`qMq|VZ+Ip@^0^Vkxit_V% zzK%`-P{^zlm5KSD>S1Vhhw@p`g}c+5p6A7sj?NJk>(z{S!O zW=5$GVvP_PV}7>D4s?v4vC$b4 zd1uQ}g5JkW{&KSWW6t*VH|ef=E54#`{Pf>@VTZ=*IFouJ?p4*3RsJ`;j0pdt^dVR! zpMnkoGvOx?(giXIw>iFVRAbdD-xA3l+}dDSe06r#V3sM_re< zJxsL5`=>|YseSS7Fjqr+n84zq(yj!e+4GoaZyntAoby(=0OsNfkG)~tv9@`5t; znT2XjJ2+0x(jli4Cgx=gYZzP8GfLD@6(PkvUauIEd-cTaN{+OAg1{`#bBh1lRsXodWV>@SKv-NOjdNp}aNUOcQ6QuDV7YRSoNzC{orO)hw8@x^op&I?#VXOt2z zc6xHcPX9qr(KECBf9<;eA38qs|DoeEv;TL!JirefUwZ`hf6(#s=uQKVVK@%8Bl!K1 z)GUA?Sgaw;sUSmWE7i-ZP*lYN?yuh+TxYJvEBR9kQ9H@?t=h%12tq>-#ipYa5nTI= z@#lv2#nZHFp2lMMOA&5qF!K8yEQ0)5Hqs7*68@}}w`fFA5p)B=hlC}6! zXjfzS&=T3SByBK3}O=7*9K7thdA@yRNnNyGYEm{BY-L_(v& zA}-=!b5ROKx!!CIbpV0FSlN=P@&Hr15>Xol5x=l3l9*M`6fNEQ6Qd--`rbsH(1``w zyLojLrm$|+n}aL7_!fmslC-rhG3x?jF-|*j41r7pQx6O*#Ta~nU;R(;Nm5(1e{%Uc zC4o2*n@pvWgpII$M!CXa6Y0B+Nv1#k08Ibf@H(iX4Gs#mMuw`o{&dTD#86VZb{I8% zrwmX<%d7r{WdU0IYz8)*TAXV2l}m7=3N2|-qmhfY;9_(~03 z(PB1+l0Gq-H;E~Xo=+VYfaWh@jS8-3Nko{FJnLMOmt-w$U+fW-UemxFp&h*@+Sgv0 zQ4J|t#gXaj9^L#(D-z|e?^TjlacWrqXWhzw#NXJKGtI6MBT=1ye+bL&{*#oO^_a~L zA01D%kQL)2hFB~S%&x>5PD-6A%7PBa!T$vk6&SR4h+Kh)0mDfvN8MS}a^Rxe6e~o< zP{8mUF_P2^eyj`4v*=_02aUf10Xg9B@3-=Kko(QZ;uFAfyT19q!T8zQ7~0UsMDP<^ zGvqImVPWqaR(B3QqANap-D%U?dN|qA+RUyi-8^USV;A$cALn|#4}4wMv2WppuYsSZ zCh$=2M_Zd|9X>%e0q>I*?6FPlPfs1Kji+Pp5`MGYKHWP$Y2K%3Z$2-dmcSCd(s_L* zeC-#tG^fl^Tb*N%52mh+?K#KvUJnb04<9F;r>P)XiVgZ@-eI>)QBAuG!;fcoj-0vT zNBer%O+^-#twrtl5r0CZSk~*VKBpY)cDA$hzBXKTWXwtvHIUHYI(uFCTzBwhKPEcI zB>ea_y~|QuB0~8%;4Tt1f)YZduw84hOZ;{|=|AZ&bvx~Lhd4|RbFt%<*vpe%j=Q^A zjF@SzP+?M?nITP|paV1mThZm8Pz1oRUZ|a4_Ln(3)F#&C-tJFHkl$XnVxPV<<$U~H zK2vMn0bSqDP8V_|xt)4;yn5Z-*&oZF&WnC;?<(I!x|0_$IeUKHCoyy-BU@`2xkHHy z3ssNG_n;cx_6173iYA=%2aN|~8r&*ZHD+X6GoP@fjM9Xq>RH!}7KoGHubx7d5pdf>FjQ%2(H3caAUSc7$os6Jf6CPSvvnE7&EIcH6 zNY%iak1;nsK?j2uLfVno0YoBOvLo#oGJJCHV~^9UiY=-O9v;YDfc3kBme5cvVmv5ITGzOY3L2spp1|1ZSj zjc}4;FMW$>gLEZDa8|w`rlZ5TMjro0RJ}XfqVfif;Ulu-dJ#1XO8EczOz@xZ!xY=% zN^WV37BfD$@CsJ;XCkdlh%EHUB<7t4uDdmLor4VHdC4psafd69VrZ7hd@dG4pO{g>^IujR_A$BA5rMKq^}33 zi+Dm4VYbYPZfR9lJdn3qs({jF*_wOgt$!wM@{eMkCU3Kbk7h4uI3}aK4Xc8zw|dn1 zE78*2)tU3KB4mU1%G!_$aVeENRl|h(&&&g|R9P?L0@QM4>ZpJ>uU#DZ1=Vr`{0^~s z0%))pMpy@d1qKv$5a`y$|AlgN^x5@ z72hxG$Hv0@36<@FV<6i6T_hF#V9(v;h|8RaKs67U%(h_A6yjYoYKBxql-+L_0R)Vb za()?a%j{4>NoQFY0IN{EO>f#Qog$2)KjVS_??`$MDY?F`oG`ZmBu(-nhy1w4)`1y= zPZCT?o8vn_u8eFv96f1OgBuj@m3Pehjy2&@E%gsE?UsPzOb9tQdr>Yq;LYtB36{4} z7cI961xerNFV}}x(1+3vVLz@s8+O~{zrP7#g>l0ia5(ek#OAf?RLL*@%8@abmd9Aj zl(*RAleFYlg_)qK>e;l?a6>eSB&kB};e~hWV4>I1WJHgXwva>zu#h$h+MDf4jUC7r zhmC3EOOnL?bDN-|0<8cn)^Bu^*OXUTQc<2Mg>Uq@4k#vUK*YHY9e(-Vu&($6FU9EM z^^NgsS9}1;CVjiw-yr-%82cR2KBR@Uz$WdHJ*LGk%bU(Atm9;H^h^B(|2x8#5XJlV zVq8dcDU20$O9|v#c@%SE>MS`}S!h}QqC;i&$eyT0N7=jCCf8txBtEsHczeP^#BlxJ!7yt6y;)X=pb@|x}Mv4j#Y7Q`; zf1*gd%J;^zi0W(ohFlb_mG5t3zKzd+V0=jwk?$7om$dtRc(+-o&JA1=ujagHgttTDC+l6lNJn%#Gh5)r8J@_SNqcfuu92+)Dg6~J5x^uSf zlnsA}r`)3$@|EMYk+xA+$b&}!W~z4jO_MY6-UVAwVu0IE$Z<=$e^#ZzFG+1&qWYcS z{SJru<$YlHn99EqBHW-V0!ZkEFgx!l%hH?yuycsbR|#y!Ts$;HnZ!r?%{44x3YXOS zp_B4+RKxU)Yv!AgW!^d=qX~e#fBp$QDKGX#!GCy`u4)?Am)a%dq4IZ?;#xgv=!~T*pE`>u2&bZb z5ZZoDMEU~)r(iPgKL|tyR@VPdApY-pE(0?g(|N2ch}(Hzjk~8IE7$@71H#^G4#bIlw(7u$eSrVC+Z4ukj(cdw?9m#*qQNLyX|N zjXq!F0N9V2+CPQ7Q?7=NUBCPC){;>EVt0LiJ|1UZCHrt=^%j@AR2gqol#4TyhgMCC z!o~meOwE1@?4dz7>x4V^CsQXEqa?r?1cN-&F^c+!fC3_5XO0x)lPTW3;2~}&R`Gzx z{{l^^iQ~GEYu}_B1#jagvT!(RM^4JtZ+@dE>X)HB0l(4vp0!ccmQn;EdW>Mq+K06! zTqZQDC~b~zhF50}%vZwFy(~L2OX0h^%c*pn)QXk!N3Q zO`b7O%9LBL506r#HknsF;X{S-d{d0BSf&}t=t{<0KEK1FJuZH5e2N-A6H{!~aQCT_ zm&BAEVc0R`Y(2D_f|KkzJA!0x8oAmM?Vi<2gU+E)RZv({_?cSt^ID{-c9?TvBJ&@O zRW=z^6Q*aw_*;79q`_eP3<|JkoR$))fMEtD|BO7jM{KyA&v!D;{iS1FloB%dKXy`m z8}I;r0qLC6R5X0hLlli2-{gx7e}Z4zF^O-8}EfWb{P$ zQN+ZUsq$yFm-3ttev;ePukoN<b?fmn*(M4!2ilP)gCk7j2@+H=M`HeYk<4Y)e*DJ1(Hpi17iX&TPzG%@OKgpuX z5g_)K3>;Bhp)WdfrHVuOG{UD>9*gk`;o8l&O=L>e8MAL)T4No{TrFZDxI062Gcqq_ zY0aPbQIf`8C5ktj8GJ4@IZTGWMn*HZ$w=&qshEf zQyo}eMUsr|L@Gr!)Yv6FtyG0Mb>Drh^W@+er*ln;&Jh9Qw#}T;LvzKgQGc+{qx7sI zGY1*g&|cSoymf7(nZ%)UWuQ(DDwygTGPJmAaE9zj=Fz%B1vSC*k~K?J|48XJkr{O- zH^O2z+C<8+UQ{{|mQus|BcE{Q)8vQm+BTcm$Y15>c9ccqe3;FVS$5e-? zhbJH*@LQ&Dd^{Kiff2A5t`6ctM1cB*F~Eip*QOa?cpdB?%tn zlufcf2%^B4my+A;#J!OQ@{a!+b@b7>+L-cB*scGL&m`1vqW4 zLkP)ZZA$=`ZGu!&MmLw^^SCLZm+W(%E;X8I7_84?Ot~ql4nA=0jw?xj4})_(P7+!1 zC?kTdS2MrOdi?B;gm97!yh_vIO*mqo(_S-@=_b9aai4Qv`vM)0-g93uxwiGJ*WuV> zaaN-L661sYvM8Ly;bN$(BHv_$2F42Z=MyA*db*v32u8)i+p6RO5rFTUIh*EB!TTn= zE<`HH#@qy*UVA`-MYxLssxWM*k+u)d@aug907=30d(A*@0i? zq+3yIAJr6Y|N9YhH#H&_L@wvg{i^}k-Wvu~u)l1EXTpVY2R$a%!=?z};^$3VH<&Dx z5E<*&_4TH&vPxGvdQAKn5Oq_X5CNGYESZumK`ctvTfcd%gW)XWYL;@XoI|E(4kU7S zi{X(YJ3?*$wI=SdmMWG#%Wg-&Jboc-vbAL9<5A12mxH50TZF*aed4n{9?QCVkBFF- zl(+DCdf3P&*kZ@Yh#R4j-7DB~*yJ&8f=*{Z#^|rj#-NpOyJ_~a-TPGJNW+wlb>|?hpEBqY7icP-dmD2Uk4MJR7BTZ!eoMPl zim8$qX9(zi(%U!&gvqod05|ME;7DR|OGQ|xLZr^-jcfzEIYvpA{AtN7i4Q{e#BdBB zOoJ;1ZP~wfF_=h>wl^shwOOXz=CVS&BmW~?Ia)U7pE&(d@L*Q_dn#v{*=|NNf0&Sr z5vo*rI>otJpQTo@-p+!uKX(Cqc$tsydg1qPR!BxvD|+^|qWI z@Ldf^D5mG^q)gqG{NsW)UR>WU?C@2m*^ZiY-5fORM3NN91Ua?TeqeED`>@7>R&I^m zcAW6LN{RzNCU*PCn4gbIH5F_pne(S9uP4FtbahTlOVVy+?^D{-ZpA*?ZD(TcKNYh_ zkFL<*_trAqlJtseT5J1+?{Z&VPpB{j#YI{;NXMc)JV&-Ac4Q0-erD3ctC%GM!pP?W z!+E|x!M!LTlwCD`-6lCf`TdtMm$t%#T}&RUrn;5_RK7O&#qE}gROm1x#)Te+?YfDQ zjutb*J^o(n2u*SVTUP9FfZ0p@kyqNMEatvL^G%Wmu8(=&j88GGCgz=yqiF$k@m&xi=xu z9Ji)ppKb~m)TmsoyiF&n&U37+%~|eGZ#4mt*s12kBuw~n;DBbwxS!3qU?%gz9y+HL zq$Di~9Q2KKf{?8kM8IR2)no@K{=*6I5=iwyNb#|!>%#FmFk!z;ZmBp?f=YInHFirI z#+kj%T9tvLB+=^0XE@ z7IRMpTJPzkiLw>{vj(tY)kO{UwXW(jrFAC>V{O>`tnvCg`Z}-nrrT73IAV!uZG_JO z6ohNSqM9F_7q86_kV_nDZD;P6sf5N{1|(Mk-5di(*~Pk%VYB0G=p$Gekwocscs10V zx3oD*?H*-qd;96&2_NaTHwK>!^cctlsTB6V=+YKWX8&?*jg%h4bwzdi@Is{urlS}- z<_1YgFfi@%5nAltn7)jMPnV-z!nl)okYTIZZ9))xkU0nIQWg|jWEI~}Y^6=<{tfEgMIaaHKA z*pX>nY{a%)wgP*Leyd1o0m89p;HAd#~_7n-mGXgKj32w^TD5HJ+I*BgMEr}T{aJaxMK)oc`C(=O-*Cml_{(f z#GdJ8;~b+He&-S=C025&z&$eOBlG3UH`hpa{+oWNy?*i|wbnKpHOL;(U7X#QgCh7u zhwaXrgo)-jEZ%T#A?o^qPYue{9dokN_7aIA($NDvXC02_Q9tnxYZS|F zIEqgiYFn7w!AmAEHI6JgX+9oY_J4i3lMRa4bpu~t^a4Ka@Sv6O&;L_(#?JhIS7#jm zZLEW4d(2ODHg)_{ouwQpbO8zcFb8OMCx`z>K-jrC$n`e_ZNgBe)<_wfeO`Qq%(6~x z#NiDfH<(UuhutT4XUDhQvK4ZuseYOIdIvSYj{OT|lhN$Ku+2E)pz?YG4`RA_4}1FM z*L3s0*r6S`-pAWS;7}&eX$1R^`%g7O+cak&*XXw8lz?Dq?X^PrJAP!DJl#`waK$?n zjD9UrruacTKEm-^s9yIxn)s}lfAiPBd2%VSMw(hhs~hSgG%72bjG^X}bIIm>UiEzx`En zi&!8cP<)d1<4jTR(J=l=`-uNRF&h;o>aGXKl%zeBa8%qdOpPyZl~i?tYB11>R}h;e z@cBj_vK5FCIjG=VQnM+bi5OxuqwcXWr_Wnv9HVX zwD225EEyjr0h%aD5lp(ejMta`?JjuJCm||Wg%e2zqZkkqL#0`!noBJ*9mB-&6h6m6 z^qO)iBb}mNj7UKNv$Tr_ig7Z_RD+?I7g5N!zV;Rg6NtNy7(<$LO*P!c;-EUhbHO z+|DD7J8f-iAY07sPfxNdTm`dD&ZU$dqR*N0N6NbjqbeLpJD=w#F?I&0i^r(vsn=(w z*N@dB*DTN1MRN$P?24ChS!f~7tA@qMdn=Sz(?D3a=<>~n!jf)Hgw=#W#2AdFribQz3T-LP(&L*WITB4| z+nv#BlS_L-Ixjrh0&ruM?M=87Et^BhhXr;O-{dE>h;y?k)|Dy1=&76*yoYRHcZEaO zvG_Tp+$#`}g=AT1^3+-IVn|Z~CH_arO-??BGDjppizXrXUtRn=)!>kArr=&9+b{Dg zvO;GG8m(QBk_>hq{9%9N4k~9gLThUW7E+&E{YodW;n_Co}a=sDWzIk4)5(>PJxzim7-2j4<=DR%H9?zMC|1mf{g|R za`H9Y0duR%9qt^D*|Te_yp^580YPJ$|!FfU1Rs!IrYRI#9R zcI!Or;X~gisx;)T*b;1VTZ4p^KRROPSN;uQJHQ_~(DC*#0AB!#sF z-|Enfu%Ns2Vl5riDqe@xZlDqVRJR!gQqF*7ocotMZ-KlQ8QD)uK5+xv^<%4HsExQz_nsG&SJu69<| zJ+V-m}LMV<0FV z>9JZDD6Kw`x>i|seE=4j%`0G$BkE&C_D@d0@A0Eh<2b>PgE17h$$m}E*iu9$A@coz zJ5v&dOrm<{=Oo)!%LL1{B+9K#@(fRqts+s6@m6maT%0HVZjCiZnG{X%&~?OzS;>ch z;c=t>fcP^|fSmkd3P!bP#9lA?-{C!8<(G~Ao!U)G|9|v##X3`L+O_NXr5&L-o)I&v z`Fdluc(Kkk>9&%((GN#=rq-b4;@YQcMYinRBMh9JYM_Y@lc_XHF<&)dgAI<=U^H7t z$(yTPW1X2uxav-M-ODdWUP2t!=GMISpEsnH2i?EU+x5L??PihX1ND z+pRhE1FHF{#3??2DVPg8fO-X zM|_BD!0~}|cyHnGy7p!(z^k$=qK3p?2kv7f_$40-2nGHGgDMY<%&QS{$9>H2dNC`ub>eBHH7VeaI&1Zs7%o&*g$XQ#*dcJ1bs~ zVGzL$(aH`n!JVA$pno5?f3Rw=xfCRnUv*u+8xB7PK|gdb)p*<*bl14nxUtA6BWIN_ zF=ed(JZHch0KC06pI@}UGYu$K?3h1Aq@Xhnw7G?Gk>Vm zFL%Od7q8y)vOY0e+q6DZcY^uCFbCty-zNiPPcppv?%@`#rItQfFgudp?QWuC4&P3P zUe|+pAc!8Q>_qHE9-@yD0!$ATl_#>?O)yF)B08*hWa4GL@*kq^XmmeDyXG+s8~y>a z+(SF%MLW&@d(DAl3Ak}ki2gG^DZ*o`*6i}{J`)Wvc_wp*$>o_%dB;k$b97oz2$!af zQvup1DtrWb{HHkTIaP>*f&on<8?|7to1+*_o!4f`pQwLCde8Ol`T|`|IusF9@`8fL z2#k1#gszIAS2;V}*^&mVu0vehwXFKg~ws zzH4dM;*o2P3>7<5lu3YHi*L8YL_s!N=~D-xUF_{6QtfGdWGo;qM@NpxvZ0b+P9Tog z$X9N^c;YeDHbafA2Hj`s3%FF|JW3JKwg?wgA4_tC!RFFYh@j$ZuFxjGnunp%l_P&) z9?5P95tO4JH^+oMLY?A06_?G~m}dV9Wc2G=wEz8_x)Z7Kl=Kj)5%JqIN3tp!;8SlU z80&1^hTTw%DV4!#Dk}Npa4AJ3Us(d2Sg4n@tXO(k#-Vj+bJR`E14!>Y(n!=q?x*B^ z*Qsxpacdk-@7!clmMI83^@qyl>!+JjvIgz#`4bRxi@5t6^A8RHg2)6fbgp35)UsrI z2T>)%0ZLKMp_nA2!EUDK&)1dho9G`!kV3Dw4n{4Jl5li=H;Pvn@{7=@A2K-2YAiXG z_H*@?u>U#6e9N{mR0!mj)lK-U@1w~w565!^Y(&scBCU>+;W}xZVBuBn@WQ3dnYHB2 zKmT6U9Y9u^7RDbbGod5*)J2U3`0mP93KejhP?OAGKqhsyO889YCPi+4ce0_pdi>VM z!Q%W(mWvW?8pD+H1C1KKgU{HO6mS|%;1gBVSpeu7GO=4kLz0r)i&2vdZ0P&PXMf4_4(i_DA(oi zPO+(&plr)biK(IHnZ(G{nxJx##h&db@$@}H+0mXd8zmg@@pqRdt}B$-`G9PC)kxHm z=!OX_vc;-9%w&Egx7MpT9YGavV$W5`6uGivQSzxEApo9hxA3g#UG#qS6tp`1Tt&WD zSw_B&@-#svks?iBZNTy)*RiN$)p+bdQ=kg4B1Nd>Xq8NkT?a2um3v^6y}7_GQ&I1b zkXl9JVr#w-M!rP64x|-~H%>7c(p1qx52G0p@`YMOi&kLTx<%LtS9~63olf$<^p?1p?Rc3>gr}&<58+-~X zXOoFdn$aZb-@ECCjvGbr;y^bUP){LW{$mlk5`{lnQx34W%8{W!aHPrQzgFTI3jqot z;0I+emOrh+Vq5qj$RZ=aUE7y*4lAs%C0K%+g8tfbVxzOSxT^8*>dlR8tg|T@6fDGj zOCBgews+64Th@3jungj^RMF!l?J8jJHZ(<#cFdZTTf;ud=Ic{o55|EkOPrr8z90q6 z(4fyy)o8)^voB~(x}4)P5y-99R7YuGlF~RmuQmIQJ!Gr_Zd((vP40>#MI>z@tn;Cv zmjjO_YO_#>>L5l7Mc`YlePIrfUWxi1iB(EcOA<4y)H!~+QJk2!8o3B1u?#I^7hRAw z+Y#Q0*D7DFI^r-?0@ELIwB9KVJi>Vjw}o3N<_KLfyC#f9fCy&G8at<*ra|zJw!mScd85QN)__u6KROha+@)P z{R@fy$Q-KkKAkf0EJB+LH$oS>vkgP73tHKw+vBZ;{Dptpo6vT0v7d}MT?Uw#0no)N zT88El`SME|-5lI{^;P0mj=(1SuuLNkdvI?jV!_7As zOQdQJXOo-Q0;yxF)Lik13r?02ul5t~EIyN5lkA8aRLXOxlz&ny0wMa1m9@dk*1(0Nu6!ph?4=hImcBP!Zu+~Vp9-Th0GQg4#p~P5-vt2+^Hk|x3ibTR< zBGZ>ax?&_b&x*H>5-bmcuXK{@C2)Dvpn0zbpHqo%o)UbA|PtX3Kl;m0z zNL^|bz$c|UjBG?eswY3*3A((iXSjQ_(c9zqzOd4p??k=xo!w&iAqquaCG4BBfvn{+ zIO3c19v186JX}O^pdYRo6xVm>NFzc&hM{v`)xhNk!bcSkG zYFQxUPiSkYSL+m?HvP4xJxY{2PcC3arXP+xMw0~&q@rW%#4fqnq-KizmcPBZVvpRkaPWAV8=3QH5R(-4a5yDAUQ)pUm9>(o!tVp&;1%s7u@NHw0*(_D@z#wu-;8kM~@Ig6El6Lhj^sv42;!B{f;+dSs%DAAWlD8^pZz+P`HsMa! zQy}s@SySy*S1d32Fam3B z?6c$t$vB?TVRNFBXpuftze&b^%b946eqRl%j^oqVTyQ%8X|}9t6^KtW9A-oG#FzxI z#r>Ysd;wZ?sB3%p-OAJ}dtHhjmbOq7_Yay)Q_k(jG_x?uJ3M0Vm9Cz+$UKPYVu6Fy_JI zNCx)qYG6&92xF7W;bnVHGTx#{UN5S$MF3v*=vMH+u*!zFJeMZOl!0^x6Cm(SB3vQx zcYz=eh+nSLZ8;8+wtFxv{Ef~2H}hS;pf{vyNp^x|;XsQ*(7W9y9d8a7{{`ObGyAL4 zmSEFpQ5F45-WZ_|WcXm3RT+zp*K@a)YvkUC>v}=8&HMV1{X7arbZtW<6^3vJgJ13* z?O!SWNvZL({XE`xZ#UvF-xXE<-19b=39eIzk+aBPCYv{lM~#_X<9l7=(#Ft-9PqJb z?=wO!;SC@PsWH!YniHn)nIeCHn%wAS z2H|AqaQWa4XUX-@HzRi={o5s8{8eoo+bgJQJ~wy)fiy=4D)d zs?9*e_GW2vVhKnd-f#>`b+shu`I3S1=)>#SSc-5A zD7ct#K5=XnUt3SR+lW*?ObHg=-c{(+2 zQ##P=; zyOpkz?^!V8(L$!OKs;>{JTds!Pb@u0zsu^meT{pUf>#vFDKHCQ%Zui$D{;g2;M2yp zR0Kl<(<5_}Vx3*h5`Be?z)Oq%Ania)>euTh`aGDFZgW$^rVdufv)gbzidf z+vHT~2h;eA`l3SJ;xeq`WzJh^r23_zXVx%D&HJ%(&#>9rhBfqpTyHTGi>*9KyW_PV zknKr$%6~{tX2$=Jo?ION8~v$EN9wOm8&da$MyCKF{0o>RWZa=TNSnv5PV7K$I1hvu zBMaBzO-ZB;-#wkRD-ZbL@&U;owIOYObSnNXd2dfH-ELgpHYz@@g@LMrP182E@>^+vPr9TN)^CK6Uu6BdDulmq2HVc0?1YfK{z?`HEXDnki8&jCq`=R zc}3bFOF}{-4!3VB1$C~Kw&e$qLx}_QQ=m81d4A%Qr>L%_mZpB>H%5()_|YT1CcQGS zU~cuuU!wa;DIYVZMo5P)jHS6DpmR1hp`1gyWA~VKGN;u66I)xu>s#^?6GPUxWfdKn z2+#FIv!>GQ6W!Ut@d_Tq2vo6Q6!{v9sju609}^okEZj3h6j7f#dqV9XxI9 zbbo`Z7O(smYV=CVVk3P%lJH?q5Kh~$`OM6W7Q5N^;}+9$@)OdY{Bz%$INkCPa6rG3SkZld(O+{b<5nR`(2=nK(WA}b28d!{sp+Zrul30g}f+zW<>r+yS={Z+GU+h zO3a$li#d;zK&|R3Sykh@+Toi;P?l)WMP;8?8yb(ZW6*ROUA}DBD9Z~~V zA1eeNn>10LM1Ck)B*&t5moBW!b%<4bfzAgQc+@Y`Sys}W!=>rS?&$@ffODOPJI1w> zh}-yJZuT<%ohqnRdajb|S{)+x4+yIqBK0Fad7$yNw z9pl=WxHaTo3@VpXT`toGOdE^K@iev<8s-DurcS@;fY`tdt=lVy+a2`8x5F*oJQ6|8E=7M_ARLxnN z`cQ}GueQ)UBHLruUc|R>jA%Q(9Jh~c`Q;pMIq~zy2YX8Z4gDT!U2)A?l1eLSW}^Qt zZn#N$iW=`Znu0zb6iaj`(_DBDY^R5#8g{JiCe!|tx`6t31mFJHrljt5EZ30s4|rjD)xRmtiq%a)L2bdkFLAK5-%I#G(?QR+Z7;%O+-cqfw2E<4(I zbMTAnrIp^f>V%myP>(LjMCP13EZxhe85|E3#i=`JeWb~yjf#x?>%3H`R6AkjqIQ=74q4ylM^ zQW#QSu_bP!6SOyv7=X$a7iK1L$_}TBwH^jTa}?0CSY} zXO7Uo<|BcH`d(RCCH8Q~!!&fLP&g_&0$URwU12Ut!v@rbKQBIzd_%b05JNT)zpFxm zb>&s+6Swle3%g7t5M3$t=zr~}(MjjpTFJdnvs!AA`_=p#IAjkKgHmmhk)#ZJRkoWv zZPFy@0W80s%=BKsZ;)5@Av^zsm~`gW@>GtQw+ESyB1{Nm zT_^J7ZID!CIbf7S2$RWFP7mvlwV2yZw-W7)Ik0wv$$z{sRm!EdqDcL$x7w|`GySfV~mF(-WY;9Q$U#fNLU z7A<;2@kq0GK2_=A+7~UpY009uz)f)J29^+2tQE7TWG(dkO(%!lri#Yl2^2c?)DVwt zcB!$|37#m-ac?mijUh3T$jutU02hvIXbDv)`+$S2X_?AcZos5eq;%*_?$Y2~Z{NJV z#o3=)VwCJ=j3(ZiDW$nTPS`T2OFxYE zK$IBjjK5`f?>`g@I@C_sXf(1Ost0fJ-6bFc(-N4Ae(E{iCXv574QAzu>f!0x5EZ81 zpTawL0SES6D}uC$J=f}8?czK5x&)oDZ6sOa)JCqroRARkEyJcqAimG@tGfkx0IUpt zkq_G3UBJ9O@AyfQ7hX|KG`)Mi6N$_~7*t9J?lE6kqw#92-EA9FmqHJ-02PqfW!{xkTBLYCD@7d$)1igSC=80gZkF}2NMAfrWmc!{I2C@ zzw5ata{Cm9IzPc&&q`uDHWlTY!DkPj2;I(i0*UZ1h5r)#Ow9i$na0fiKT_zraK`Lu zIPR}&W)XNpO&!5tLE>#8QgwiL0=eMgxsDj$eg;s-_NT9tX~`hk=-9O?eMp8Be)#Sd zW*AaxQgZl(vS^*PH9g+n4@hspMtTAda_1;$Kv@Xo4g9iwy^eITKXq>lI3arf4*lTq zKW!i&!dpOQ65UoIItWxE*G%D}eEWUm2});Mcz$N?e1ARFV8}~GV`5fdR?}dXK*U~o)#Dghayot327NGY`Qa5*k1rYHBt>z z0xgV{eiCv(s^?B=VK<4FNG##wU!X8{)~|}z)J1-L45ef?6W486rTKkVqEMo74+;WX zh}UNI8-ggP5wV{~*g5!s%?NRuN(S@w5ik6?lLb_JR}PUmUUJ?eP5w~AEe(9GY2S)I z%^4*h4+Q3L64aL{`5e+qnTP}nP~Qt}gNEcK7c6$kf2KF+o026AgZqeb*k7)P9pWe( zgrxxyQW*u;xR&3#*7=wu4*gZFHd4u}RrMRaN8CjA)w0FnQk;rBapn~?h)x-FQ-%y= zr-W`GK2*v`M-!}~5KN#jHmFXLDEv>Fcu|EeXnNai8kwL>ji|4CcZV1>$A7gjgp^+;%Y7-rd9P)xpJ)U&00=?o?m-|BLT~ zVnBrix2zg9Xw>$4zj#?7VCac5gd#hH+D*+Bh)dWStwHrI@Y@@<+|ok2-fQH>f}gzI zC(1`3RFL?g%Rn1Nju1&$(q}Hn4Ywf!x(^}y93xqPF)$`nBwfTkaI%e#Nl!4enjkd1 z%jPF)4t6K5ky=GO>5f?OZJ#7M59-Y~!pv5q3-c5k#um2R7PRj?S-EjeG!1!Vrg6P< z51J$UjBHWyP(9AAvG$y8$4m!eagH%VT5jTb*{7@>+c9rR5qI6rGnSg;^)>ZWHuVU1 z7-t%>8)?BEknO`i@9xr}ea()j2nnR!X`OaSG+i^zvL?==t{;z3*G5rZ&E*pUCQ4`P z4mTeR=7c2bgySx$xbX-U@JFxE9b=*=m66e9D%^^nZ=yG|*EBmRlH$~! zUXRKm!_=|my%0_F7itOe)uWqz(n|*iaNFd=oQWqO&gLK^#^GfGolJd8_Y-k>DXuMK zM(s5^c2sS{W0y9^SX~N#?Tb76Mr}lnJLu_0OCN<+@ij8q2+2lMP5t*MvNWWZd2&-B zX}El<1L+;#BH9o?>#Ww8=JM?C;cvJcDv|<4c+6y(q0j29fi70DY?|qIL9$3D>UbjS z{8k*TLW*%?t3w&aqoFboEcpf<6~RSADk2j$RIhey1Lznh%3S4CDhJz-DpXBW*2NL# zyV__Xg9~>Q-4v@{*@*0TNRJ$gck~;jFwo*Tl$)2gH8Sjay#z-zvear?JIKw*Mi=QY z?lglASHOf1ox<9q4`uO@j~vT+y0}Ddk9MdPx5#ZPFKejyzh=bgqZqC5L}E5p#(pKG zP(6;;Rg72?D%lt3@lEK6+_#7SbNGlv4{0RMbd0wXs(D^opjERdH(c!?`==w{TMWgJ5Hu~xfLDg+=U4xH^Hk~3^e@z$hRi(>QS z7>W06R5(eHa1Ne}NmZ!FXoYcdtA)AKSl#h>u-FPwi~u|kzay!j6rA8e8t1{*nPz7d zSIggQGzqXE5kB2$G>Rv1wY4r7OZP_GdX4FjkeB$EU6s0{*xED<=*6H=g? z-BL!TMXQ2VsK%zCrgZHamzvK!;X0kFz*h$FoP-POixWARoez>tZIF0-h_FcRrihaQ zV-}3Z&K9REZT%Hi?VURhjx#4kUp=85hD&eI-`2$q9^^8(-e^eH_|-BRo22$(>83nF zSsM+t*ShkF_xfk-guOPiHje$<;mL%Gcj5uIyX1H|bgm_+N(r(UKK*OS>Ro-x<9FkK zz6B4d&PYpt7tWR>bV+D&z$z2*R{E0qFor_0>@}=0=0Yyb$g7K6?MF`FTwP0ecRfx@ z_S`<1Cyk@xsp~m9Rkar5+HVK|%y5dj<;oT?ysqk6c_^3L^{@EV2R1VyQi}-}P{_<_ z54;?xjt3sXy#M?bdO5+SYdGv8XK3S?#q=gfN0%@ti|9g0w$Si$@XwIkPu5c62}${g zhGiskH4Y|y^W0G-hE2#(B!)#qkPbF-Ieo5z`CIASRk+c6dVi`Y^s zH;GUFcW_(%BSy63U(saUoUEs@?U;m%%WSPhi5f0>XE?gyhU#nl3t7nw_c*u%jZ)*T zold_b?dewb?imqba6^HfD`snMp+r><_kw`VUR2#_gw}kFq~Ts`=i|3DpvoReb|Ksb zKCQqsTQ~v$tM?F{_$vjLvvLr>o(XZR5_tJeIKV3z&?RA73bAg6ndGED8GQRF*pU6$RyJL#0684f(-}e*G*(@O#xTJ!QGf(BlWjLTN^=t@@T#GcuW1T$$b@OI_;g$%=jwD@hY#PTMRHKnyr z-C6}j=O{0Y0c{uXwKu{_9|eaIc-6?)>FqQ z`gkiNCIw@FCDrs}qDJ!^J~l;Q4>Oy0Nt2qlJ=l_2Ql=?KKCmB1jPh_I2)93Wi0~`GQH296n>RBhu2x9#9Y4SD!@{bF60woaX z{OeQm^XgVdU_0nHr^qgBfJ2CTXNxp1t26AEZ>I(!*$fMxZ#MqV``ZkF7wPHq&7QR1 z-^_68{%Bq~t%tfy&C z(&O#Opdc1j+Th!;WRIZL@Z`EX8-2oxLWpBCtg|RWQZ{EuD<^7?k~z;@3PWl?n%CX* zfE;9jrnux{PJAG*pr7Ses#Ik3kitDH{P<8u5#U7keYzD-lg2HFtnnxo=-**6T8Xrp z(9QKHyz`el2>-&}LOHRDPH(J(<-Pa_@`PA2W|8PNe(YS&)zj8zKDqzKn584Qdl zX`D}TE5vCge0G3?tjz1Fup?}%AJ>I#OX;LGUOM`t`)+lX-Q_^P4$>VEmx=ZPQX+9x zuP?TxVkJU8#+ypIN4m6UGEsVU9E*SEU5Qm35tf!aa#v|_)TMx2t}`k&avolREu9Tr zJ}&ZT+22>{Vrd^3FIHi^(SYK(%oS;ax>hRIM_no{v%An%IXgw!$Bnlow78bD*m8)*)9yJZ zA%swva`Dtt&g!232UJI8QEDXB87sbJok2Znjrh^g_|qRecXZJB-s+h`%5mBIAhTi|Y)I` z5!kay|D(+meYb{ozf%)SZsVEw(c8U18@uL4X^7fr+H=}T-|W8^@pwZ-4Xx)rOEO5O zB!n^h2KDtJ6ZyM0_(@`nxFLLdl(B>DZy!5szKYyLx1Q9ovuWTzp7cht3IBd0yux~9 zJPVXtEy<;)c^-f^3YX|+%v$};cSz@ulAup;U^u|z5KsCo{D&enGnV={#96#QKKCeF zx2~OY^-11iOkQ-VrI?{pmOfzx(cv=}vO-NU$mn>lP%_XtE?}XrC#4!|Tx?CuW2Q1$ zXI4UPq9W6z8R5sFTdANQ7Lmh26}F`?`*wny&NJpwv0Sy=_NI4UsdQPh(+VS^8vndl zEt=guRj!YL%vL0RWiU$;4)SvCfxh;l@f6h)w^VR3-z zJFG@(Zo_ZXI0Ic(*3iD)n=xG=oZrbfpyxvxz8XcyZ2IpLYah&#@Ab_y5;w*W&j${y zx07L|Xgs?GkFX|0Iwjw4i0N9niFucxik8VF`rE`5Cq#scX|NdctlAVh@t!6vkdwm# zdOs6cMIs?+90L z5|-6DhufCH$G1Q*;z0(!Ia^!)mhBUh3_erhrz6xULzn(d8S4!x!8TfJ>P7+U#y(P! zbExvp<`sF)vx>-^tzGch@+w)jermSgGO*{!Q$-3TN6N#AnPVxdQU zY|z>Fz_}CzQ<+N#8QsEFKyUX2?1+wI;R}Y8Zl=T2PUx3p_g;_DDzrU+Rq!%!KgL;) ze>0BNoH1qDS8$43XF24cjL&KLTB(Z}75Ee_LmX!6vG=bf@sR$89kmW%ncR_OjK(Hg zfCPx>%oc|DwEDpwIefU5A+7TCk- zj|~9m9UpqTs6)_`IurMjUNS+4f#V+slm~{oerYosI#+*JMTNAG(-%NFXT0yajO0zwkvChR}m(ZX};D+`aBFjQ5iqjxA03 z?x|xKmrp|1NAV;5`@W~ikluyeipRYwKmyNXZoh_y5_+nZAfgQ3(cxMq_qNl?tTTz} zFwumN6VJyv!7W4!Q-{^`f?##8xTfW66u46pQZ*8rR*NX4mG>mQztM842) z2t4dq1Q8?MDlP)90)tNqz~~=T{d|ba^usW91TV4OOQQ8P5nT>M6Rn&sovJy^aljX?B2Jn#)2RtBIRk#~nnPSTeiDr4RE--G=M9ZIf*h6o+8bP^zvE{-PlLP$! zJgwmCb@b(QygUxCXCBUmk_K(ze2C8eV^Qtg0FFfq~Lxbs#Pu!*}6CwlLW+3;HoDjCUgsxbtP% zj;gM&ducHzj6ELPkT+`N#f5$ghkgVe9*+gT&dMed z`fu<7=G6~IFf$(Ze_0Eb|7$InS^iO!{=dT@Ze{CY=ENXwYvf`kYG&eKYR1nG?d;-Y zW@HELzCNWr5ko_PxHY5khyWXq?=D3m!_w_mc-|bj zy7uus7el&?tqa%Z`OzM}M%yDj&oVUMA&I+_Th(C-7e|0VUkPNCnPv9E{q^f11!GKH z4Mq^gWWW>;T3dsbP%iv2hIB606lG_M=!~6OdvCu*^IPUXkR(*!;GVnD(e5j`a2KMc ztiZkS$2KmdQB!}bid9i#wQ`KINFaas#Tu{F)G-NNGsB2ak=2F0Zn|)&IDDA%%Z1(7 zbws)|3QaoQZ6s3drewK%-_b-Q3iG{X_+OW#p09j$;cAUMvJq)}PZScFUbFd3B;BZq zqoQIC^3h&XuS&kdv$)lJjKR*`k1>WozbZ-z0!u*XQiiQuGr<37axG!;$c=J!G z`4uq8j|OiOI|VCP7lfRZdRQ^9as{%^`f}jx)MikrzfJh~g@kC)TvX|RP5l#cd3}^m zDYH<7|1pp%mIWAHJBr5Fd8G!2+h`!UXP@qtjo1N;p(u7lZ2Iv4Qvt1Sb;%8rAAy1? zr-68Ufly;X5|RwIabgqQi8XHDTkwSPiqFbC3<0{bM8@9a&xSG0Up!}8WS(F6FlkKw z9jAYbCmCzQJ)>Ad_f`IQKbH+DQ>N1Ikc+akFTk|BpYjh#7n|zcHOeZ(?Cg&B*7$1-FIPp?O^|peWKZ=5Fb{Sr)&q!e%*QdsRjZQmxxPz`jP2P3=`o+Sy z?@rqS#rlshSBOS9VCe(OWr-`8E%EH1Nn8#arR)Iq*6auI)Vv`USq{lxX{R{&b*b9N z_t$n8zp>5VOTQ!LLk-s^Ls+eHeLP}vp(fzGHPE{WPQzvGQju5qr#PAv0k z+&ul>U=#e{q`=3+f7zACX*i(vKG{+qln;*ul2N*XPP3VMoVRYOJ%)WTFe7F7!$nm! z=e@Y%qu37V!BQkomIyGy3-7Q2C7kV_wt>a7P_E44ti4FuR!>tg0zv^*cOOG0?JKlF zaI%YAUw;+jFu67aPVWC4(L7gyEt0`WG{;so9{1wg{866>FI}`*>#6jI=81nM1x$kx zTpH%aF_E|Btpam`NOxiRGA5z$)y`44buK2U@n-9N;)NEGG5`}t zMc;S{b;C9#K-;NaLhWMV-mxU}Z1|yGr2acIfj$O^g_>WQA#{^+@6htaUUWv=*D#z3 z(#72&yklu%+N#xq20%?_$Ck37`&ErQNB9c^8<4lg{*qFC1MnCY4i!5nwo*)ysm$d-mTG_%2!5pH>fd(LFqq+KIE0$Y}GW2;I;(v?Y@Ky z6Fr8hmQ35Wr-{DGHoFK7s?lCIFxt<*SIenMj2R}jBxys@!c(E`xQGZlg?W@~FAZb>|EoF%o3Etdz$v)Ed^Yv0B1e42>sJ$3p=6rGFq&eG9~9n1%g zS{JHj9~R`n8E$i)>(=9OqUb~i@JytwYjsWleI-=nA0az-1$JPDc@zQon1RVo6l08 zVFOiGA}>$c(HbC6TmAOJRxUX$6T&Aw8M(kIOGN=_-bqr8j+|Tei<3bn$}Nu7l-`KM zVM&!Ami$o@N=r>C?mE}I-{k?u3C=eqC^Uezt#%xUq|@*2b54Tqx9V^we1-KL!r8IW zygOxzDN+W)X{;2eUlVJEh9DqKUl{O#8{FC2BPMQFt$4%G>9{og?y6;RzI;|vvJauj zC%Es^MvBsZRrJ+((C2*TC+NiZ^(TBVau{L3UI>@W)iab^a^p0+5f*rW*jJ}+p~Mwj z@jl#>;$#zWro#Ex6K;p*uP5EiXo3Dd%Y$X@Qy(w()hCk&>+7u{{?k1ERDu3_6E8Mz z8_Qo*q@Fi!wy)_*-eWcImHmuw(PDz<);Z}VB z77xuK)*C+)Uwn<+6kdykB#BYu>DnsQQu#{0$U_jw27tFtqekIJ?q-MO7EN%sKX=Nw zuc#=;4mfPXYQE%Efw=(ZEHV+v-!l=lOLgQJO^2Va2cZYMe4aS-QF)#FG|8d9WUai}fKJ)bB23_bi^KD=K}8t=wwAVx<=2Q7bkA#i`7V>sY+ zD-kCt9p7HR?*C#;7xm5H__Cfz?~UvO!Zcd>Y4&~x_aXu3Ks)+0Yj?&nk$d;>+mMkl zkQm$*RR4UwZlKJFszDbT8-5OHPW{%;`^97xtsxjr2&^8|!)m)N9wC_))J)%rQcgIvzX?h5Iz_ux}qk^ z%tCZg6$_u*z=#Zd{~Kzahg?vW#Us6n1#7gH?^7DuJPRu?JP>Cy-pA~tmk=iaS}|X@ zbOkW@mEM93spH`4IwRfD+2tsTHN^rVwxvleoFQBVOz{K;magT%Ea!k5x`qRs7hq)( zw&rMp(&W+L5HPJ518tK!&nVQ6hScOZ6+unj$K|mndoV(!m?986{dPTrH{NBc9f_2K zy+{&Xys1Bh1Sn#k{9~o2G~d7dH9C)8=Suyq{@h(&G6oRsLLqFuhhbhq($7L86IwP< z9Uq|nWHaiNYt{Q3qIej=s*Zw@=NZ|=!K}tXo}hlHu#09W@=fk>Aud4@visZpd*-`y6>9iy`4?R^>8t;Z1{lNA3(cm|T3Z=}+_yc? z0_B4v>Wk&hRZwlQl~hi{H!>R(`8V!Wh~p{sc*Af$j?c7au1L_|(6rli-Jw=ht(XK_ zF?wemHhB!H1qk`p{qV79%m$&gEx3?Ks*^M_`c@1LbAlcu%)il@aKly@EkY6t3JvQ_ z9jpc&eZM3C`tM{X4r_&ZeTh`!EQj<%DF{Byk*R8BMgx_{cR>@W*Xq98&|re6($43a zT@!40xLRhzY@wqJqFzG$Ca4;J|Dqz4G@W?Wh?Of};&8z)#cduiQV!6LLIB#&kwbMh z*X7a`Yz8C&k*Y6J67-Dt!37k=nYr`#DMoKP!!Uew*To^GGq^6zx-GVp7;}btrfoen z>(Wxim6%NCA{nx*PpEt6X3POI=@qrzEx0mA2Qq&b|a3V3&-^Q*-3TOL2@ zpI}hUkoP)T79sfv&cD{7kApa$DiR`Z9flTsSbp_0#xe@ijcb#<#okK#PLP&jXF*U| z$>%==;C8b57V6Q$kF(*0@2@^OO$R%YR7=R!s7^Za2}7L^&V^%PQL24?U&^#v$SbIR zMTDjFlR&->KA?o9%)2L4M5u4T$AMf^@dj4Lk^~!~u%?V*rfgN?wz9X>xzp7cCFWA&3J$?sv_Hn_q)6^NwKXX8%@rm{o4>FER`%Y z>L@s9I%NdE|2nEsdgE>jo5)N3a4IZ3n~5(S6~bE*r&`#iT@pW3N3{@N=C;MT^<3Cz zLnI-Uq)wS^nVi?DE3O|A_CiZCxL2JPI<(0>!;!UMJ}J%)?{@7GwBp!1scU_Atn5Z= zp&UM)e0}lR031gKPQ_Ip9Qp@p#3ap-iY>u9pVbmolm=58Wbw-iNM_qc#f(CkVMN!U zUB!i~x_aX2EuYEEcIvIjfX=VcW@$EUSzdngH66@X92^4w_EwJHoUAEn62b?Evb+K% zM8$#bPvpGbvK$-To#MiRGo1r22#RHM`9$dI7?VQIG(N$RfUVvKvj`5I-_#Ph9u{ri zMYk$XqjFyhmU?}I22%TF!*i08C6VZ}h?@etjfy0@;mMT2oP$`8WqXlXJjKl)O{?=c z{NRoC0tlMjgtEWB&+_LaHiN`FcwFTTzUxF%b!dtmn2LW_{|qgv3A;STMv#>u&o6}& z*GRMen%bFukod^l?YOk+EV{6siopI5mao=1WiQi^MEt`)h(iP~!uH zLb>UI$Fr$r#Sd>*uJM`XsE@i}e+UEhdmJ1~u4SS(yNsPoxMtr$`jBAhVEd@q7_DWG za$3yPB2e^iRCrtcTx@SengDK5BqtGQ-nQwc%a8%&2aOz;B`rWYd%jn^jRN0p84-!- zwp8n?tOP!KE~tYN8j$D34Xxu7xT$5|hvMc4U5ryyC5V42L%tc}8P3u=FB0qOJgFR>ORuYS?E$Emka6Czp z52SsB#WAu*vj^wQB37?R^mmIl00MhuAzgeSp)?Po>`DcbYL$|t0~Or$JSg~~jBp|) z3BTbvb;r9KJT@@_nHg07s1U z7B&-Apu482PZC`H5tS8Z8@F%Gm1||OSEOG2`BtI1oAR%xsrGmkr+PaYR>IW8<}EoQ z3VjcJ&$dAJHxHAZ_HKp+rduCPWCr{U{RJqT)}3lqE7K5 zj!QXSdkZAOVFWwICY7(1-#)$@z!%vDCY0((;xxX-u3>J}hbQJ+8)12XRVJh_EtRw0 zG2768GFS~|3TDkK7<^XtwSn{({yQZWNkWQF>ixs@aC_BC4)itJ*1Az(pBzJ zrL9aAlqmyK-tq(iser*#yNVvLO(tBXO{%ImB0(!UfG@pjOBgDOWdL|xu?HFMUibM|$!_8Ajy6~{ zQo%AQ;MeBDyg{Dd6dUCHWHfxCAX;Y-eq!pLk^uqZC|a#%1K@P_N{a=DQx{5&l;CX# z0G-523v>?wCpQa(z(4z69LsV1Mg(5ip?dpK5>g0$?x8DNQt;V2Z6rh|m2bgDaXNUy zO<3{hvNAlv>$}#cSj-(db4wUyghYYr0#gM-Xi+UWoC7DK}m5;hTXk&jYXVxA)e@@ea%+wqk>M@n51bj;|xC(BqdPq$&$O(5RlQf zl5dLXMzx|JA2)E8!}F;OM3Jb&H6@fxtKZ(C23_f_?3i-XQ(eC!OPY4?R`@>G-|gB; zU>saO?mr$6B&WJC>t?%h#&z(XuT^%R$eb)-+q3H6d;p(?&r;QUld=^AcC^qwvztKw z+~*s8gUt%!LLyG-Q)SZArI2@*bNV_cW7SKRARiN}>?|>GH@L_gY|rBimEFW*OJ zEqAI%-n#6DUhm*$uq2JviG8+yJ=CU?TouI58?cO{ml@DIf<*z8B}@V?c(iB*=C`2+ ztM0LTUmuaBLv~%|siI(9=L_h^Z%T_(hn=_nRp@E8o;K}}q4o27Y1=iTc^W*@B#R!7 zwpdHDv_m^X3wH@ZnQdH7z)LP4Vwt6r+;lkU*V$z?4f06fE|@q3O5^gYs@WdwR)}A_ z(;hB`0nSvBQMe+bx^Fvr<$T}v`ov-Refsrx=|}8^PxStBf7@68HF5TsG8t%4v4rc8 zn7)imXrR)4lGc0Klhhn#(~7n&%nQb?k=-7}YvX*1C0o$IVTiLJWBZvd>N9khf{kp#!gT1}@hTp3(5 zM5ECtVHgG zL04pkB_fkxs<1@6+9;t#)?H7mjHE>^Wq9WEkINk?X8~Y#7qLB5qX*~94*YCS%dX{a z@-c0&S}yqHCbAJ#4eREw#k~T>bIhz4&$rIRBw|q#4fyvDNRNJR_J7&3|3JGkadG}{ zbMP+hv6u}`#I6^OQ;2k;KSOYgu#H)qy_>~zEq$5bW0_8=pFc*C6|Iu>W;|S@^;G4W zm7Y!W-tU0@g_V?rk%^K&gJX;p!2xFnAEc*1B?^63iWOs!eT}FKBY)3oKu&VcxaUGL zWu#K_Zj!IhU#UZiuma5?J*fxpmU1~&og06Ay~UtBR* z$;7s8JDJ$FZSzScw)w=i%{yP+`_=vGzQ0@V`%hPOSEEk#-hKAjYxP?6nB69J`xOM1RyBBYX)J0VVD3TVjP)A0o0CiJpd#5$@pTpvZ~L$gn{ zWDu1Y#d!hLq@Dyx1(EKGfj>}RU@CF_>|F0o3eHImx_FAi3rTbpj?r30t?bG7mdqO+ zWaPa%J|COk9uD>n079;1y;p9pN5heR{=!T)>tuKc^B+g8CvW4qe5(UoW?7pCV}3KO zM4hJle4rz*2#(dsmVY%43W}SPCNfC4og0rC!{Miu9HgBK;H0sst&B0`6w*Zp$&~_} z63{*Q?C-*g2w-cH_Ec#_W< zOms=Qb5h|V%7>X(B@^Zqd||wB>V*3KP^&%uNp$6-0h}+FQRwX%E4aWptTFZF`x%L& zZ(R8DSD6|Tb->b174?y0m@0|7c4bAr?VWsbmFuAsZhYVtjWS@t;L>ly31Y*}))y|Bv!5(aex7wHt9 zDj)?Bl3%qTK%r5I;ie8~bIzf|7?DrlL2g+0r?wehP(Z^pffka=E-8IKCcp9H{LMiJ zfLmzx?XvQ4o1>L5O40(yjTB47M>JJ?JxyW08i(Cgf>%(Gq8WQB6?i6-!DrqVX-@h` zTO=HMX638oiI7QY293XHcjA$F~v(31l-yT#-5r#ghVYv}8o$UBS%LBWNYVJ`n#Ks~2&>-|BW9b*P0E%>26Z(v1=62ACp++a9`qchYmBi7T#jjiT3;h><&8j;=R=kBR6Fm19_Y+scd@vR=lgT!9mAXE$_yG@X7j| zjcC>NW}@(y9L+`IX#P^f*@V*w1r09yk=Miwn*4T0Rfz$StMZtgGGfSD_zG)`8~t8e z%fbn0+$liCp#)C2LtWK%iYg~%AvZer-kOn!(WIV#qb%*}l{Wy4-R7sI{;%Qt%3wYN z`eE`Y3L`vcF@t5A4OWK)Z<=n=OI>q~|+3Mi?=9Nvhd1Tb>0*kW11;4Cb|B zP?ktvS$s2O>0bF=&YYFR;Kdp)5|pGDui~E!U*%3z2_lC!^BLL%W}J*>7mAk(h z-1gx8{-<4+)o7FK%ZU-N=sZ;%OSxx?5*73=3VmPUfub&wsurg0kR5jEok_m&P+%Ja ztA=PyEn*%}Cy}Kdmf@^+$eHVb=9qORpE<*maxr)!i*}G9#b``|k>5bVR_nn}tFWl_ zd0GYG;wBMiYebe2XR3q5VP;bYi-gn<=zFfM=d@a+vPE~h$XNRNN`gM@h4@QtOa(Hje*m17twv zg~C)L@TFN3q9TKBbEJCO^BrLAX|YkUxV6aQoFa|-An0gErvi12>-a`F@U&<=!hML> zwg5BFKPm9 zaV1cEmep9}QqRFoPde^xzGK;+bK(jL!H$K`QRS+~-)tz2}3ya*X)UrD~88nSSBW93X(Mpg3YiF3)Hyo?+fR~quQ=f!f< zc~L2Oqq@~fPC2<4*dDr;nur}oYqTNSL2G5wDzTOtSo9Ect1?rezh1iz@fuHp=vc~Y z%7s61u^Yr2A;Lf&4#k^8%9OC$4c!$L^%*rd^=I@wGk%n?kEK~PaOIJ}tX>)fd}jxT zNHJ$_oz5QNBVuQw8#wbvB-rzx6w%hQ{YwTQqzYTN8N@EfNOE+QfK0k1d zT^qvWM=uu35d{cqDjZN*oeZ;{I(Vn&P&;Z|I69WLOuY`iO=G8pbx>J-H3vg&Vc*o< zI$RD+s;09;X(-!bq#wzqxH|xtlaPP=&9^bT_UozQBW#O}Ui>!84aB=}30ofSMsT<1 z_uS&kM)I4>jg{Cicsi@hJ^yOGdi`{~jjiF~x!Tepd`r9uyL>uBN_{KskKLFK`rKeh z{ZJ_Mb$@WRXTAsMIS*s*?Ok4I`O;FBmU1o4r-j+GiZW&25{Z`x@%no4defH1caAPf zJz4qrI&9`5QEnKoe7SO8GEHzmiM~N4eLn7w5`5aUKjU>JaqD@>_x$pFmNBEtPEGlI zN4Tw_e^hy@_4|TiI$)lgIey*UHKzv;IfrBBmAL&jtYhDCx%zDA?cxp-p1lHBfgeNBLreBA(qK_^4INe ze%0{Cps`~?L~-U1tS{!v;okHnV$hS4eQ0Dv!z#vtC_1DAhfHOGFN*l4LS?Yoik@jo z&)(iX-b~)UzHKF@_Se9ZjVt!R5;23)3gl+Qczf-tX8-Wm4+{QH-JNR(*G7F7)EAM zQZTp(<CIG6nt>l^r{TFFcAp$20uH%}&GWqK-4{&)V`AuWj z1>;!6Qv&^{fUhKhFjhS{BS+l;CN5iWqcN1IQ5L)e6Y=8>(C~ae)+VaYS#Uz)5?<#3 z)dd;d=*|lAT>)s1c#5mflfKp$2~(_=RFud^un|_vwZz>WN0e%VwamZxR*@`g79IiSuSMpQWRD{AO4h@ z@-RP`N(?>L+WppXPq%T!=*1HwAC0lPX`!C{?y6wb!G}da@22RCE5=C{-Gsgy4^}JQ zo-0>n-jZz0e#nyw6IS-i&7#IrdAClXYy z^Oj(8f8;chZjNu3;8;#A>^e59(#!?@}4 z@2O6FW|-H&(*j6_KgZJ$&H3vrG@p!V+p7ItwPA@pXE#T!qtCmA_3N(R3K;gE-kNXl z<3L!d*E(&D>|)@&<|i>aFACO?J;alAjBN&xVFQVDXe&&C6?Cp7XXI7F;1QA{Qnc}T zo$yQR)~za*8+9#r=C|n0a=#cEI`)MrhCg2RUW^^1f3f0x*8kOpP02GMZZj1Z0CcZY zRB;$6Y$Ci?G7W4AIn-A#Q7zq(oDNn+?jxQD&0Q^n^l&W|kXvao-eMyDNx{Z|GUx?m zviW176;Fn14~Arff5QMw?vTNVTcqpNG6B^Xd(CPcdu^;n9p6 z4g5$a5Dxwb@_hTX#4rEMd<&RlyJHFBK2UOx4Mo3-Z-{=HD6!jg3VOewjlw0l(Dy@? z5(B!Sno}a!Ye}~%C>wvg#DwA)k&(o3g$#t8T-uNqQ+q?~KA~JhQaO9fq=6mf4eNX_ zi1=0wYGXfA-b;G65%Y@G?W~K(R9{dTeQysQ`Ex@+KV@3D(wBIefoY-;)-(l+5P~_f zl1rm?Y}5fJeH1>deCoG``w4vINtPLuy3OI4tMIq7(3*`%pOz5Fwk5XVHBss^pFD{I z;zg7_e83Muf=L&Lw9+UHz#-K6`L9PLbB?gp#h#+HOUo5RoKuT8qPeh%r&^DFX*;u@ zcdSOGtz7*2lM?gZ(w)5xBXu+6j6^er@+0@y>KG-^OH5TtzQ5ran!(R2*bcZ|{4bLA z8e4suUbs*WC-eEWH)QmA_##`Cz1N}ns$c35lIJ8QaqSz(NtO^et?t>TKv%y&G}GYX z|Do#pt4RAV_&gg6=l?G3i2e;BGWi!z%sM0dg%7NbKANxS7$iJ6OX39B2}&E>Pl(m( zmXS>W^aDPyQG+N%HoahESmNilE?!&dP6J}DEuQv$p*~qFKTi{Q9YY|sini$e*zuCu zlMy6Qvr9cXNScipFqXoEiz&u5z%;-$qAkm?*TbmL0+0oUD%8jeOgK1tb@7LVeJ`@e z9Jsj}=YGfL7Bytx=1M;PKJ(#;KPM!3gF`8?PYHi{(dtFegWuhv4wVjrO>c!%LBb;} z**$XnYt<<#8X3c1e>A+9j-r3jcwQ*kd|Yz7#m;lSulPOkM|h?E5AA1trMIJtL44M& zTyBIU8nk<8c!APpqn0hAYx7ln$VT(Edu)1d0zHTD=u$TsVo%$X zRBWQ{VM@PEivq9sgz(fh7H*YR@vO(F#C>bAkT0Tr6J05G^^Hj&#bjXOw}h2A20q&~ zm|}W_o5Gm$h(tDx^1XG?0y2l{F!!;C^dqW6+~e^l1fLau=s(68+rPva69?me7H2B4 zldxb+@WEGaXda+epBYU=a5OdB?Ho51lv`hx6*~4viPY)0a*@|y!Dqq!3N~vD?I2QP zhqg00g7NyYH5nCw+~f&h7YI+_1tSv}H4$k}BS+a~PemlR?N+``z-`Ulf>T`El3!#& z4dg;vednO`pj86P+yj1@*?!ROFfB$7piBe+mT?YjXD-Vu#sm^~X)krJC4f&;qv?WE)_Fz8$DHxYBV|V4sI4 zO-IZ((|9@4?&71KGNi=0NV&xqkx@+)`!!bYa40RBrI2l%Fv1(^7@TIN^wBflHD{lh z5%kBXK{a5tdJg_2UDo7}^jgJgE|!h@zst^D#>_HxH-Z#8M5 z;Ii^Dl)_E;aaHAVAc0Cam_ktBaS8NQRC8T2L5v}5ct~j?va8zhGqL+y4X2LOs~P5P zn)uG^hN?avb_YAl(+FV|@3R_+J&V=_#50^wb>qikY21+Utg-N_xhhNW#|b17e9H*+PBj*9<1%68NJ~)1EB&4h+S9a%4B1K1Q72N6Uab!-dd; zEkFu`0>EbQQDxq!NJlf0a|V(5HBiIw76sIDHi;eoNTEKZMB5*~m%0+j6ePMR7%Ij? zDqL0rp0Kq%?QL?(m)Hx7unCJ}=8&xlX5w2zo^CtLoVH7$WR;MTv!20|Vt!5)PgZ&H zM+2Z~!x=XsWuZXAeS|fyO=iiak7BfDsolgTd|Ee5)~;UKdE!=0%nJiK_n0SNd@keo zj1Sy*=%%fiYe=N+C$H3kfs0l-CB{@q971%}Sh5 zeY&WJQ*nSZeMtlLAn&|MQ-JjBdpv(|x0bK}wsVEzj%DbLEfp7E+0CO-@)m~cCT-7O zck==yJP-^Pv@*VJdfYg&e#kDWNn*Ls`CrOetFKD!xZe^indDvceoF z*ZK)e?bh9Y6D+21kc{wp#^IpHa4g?Z)%@%T&yu6XpOYaOHk$DnOU&~qwB6NJSwl}k zx%D>>IrPw3%dH7!Ta&9;HCoHcdcMjG(|)KvJ~$5N@Un}n<1s4n>(uBHd*$NC`*zy8 z|93v%epj{?RW@~D2+Yj%;-u1djmSM`J_&tE>Qo^L1F+V1eodGKn_aCF1PKJ=hJDpP z;8fqz@Re7oy&qBSb-j4{%MW765REwyLmJL)vadXPd#2(R^foMxz@sd;^)zX%b23MM zScc)z{*W|ri-!i2SpC(g9@-2|pihMkj%zAiPhy$>H4@~_d z$&n3RFCToG2X;mA=SS>(_7V#(Gb-3Cbj}Ah%Z^fNeI|?-u7QzJ>A|cS_>&Wb@Iyd2 zqdbOY`i0>+n7CLKybBBWR3;B=FIp!nZ}V<0^cV`_smA zMq)p#UY)5H>elUJwgvOgCEt`)mSJ=bDV>pp)1^?b)zcLHH#ZSTo~v_Dq94PK^s1w4 z7v-#dBl%C{NvjcZrLH#U;eeG1ugfUjm|V25pQVwuQl$j-+RS!UN5qE2OS;!zP`xNv zQn3wApyWXE-G zq!g;&iL|;To$nXuBU-udKTZ_?qy6@OtlycLIR7)E_8J&Rhh??d7LJQ4tok;DKroF=eURax1v%)f*Ly{Jw1Hc zMp$!Go^GE^*{=LOy}~`Q*m>)y+bLPQtohI9KF~Ff!SHP$*rcZcdaMDeuXoGVpC!5p1Dm@*9<1^3OI^bV#F&A zmbKEo+d(VbX>D!VAr~QS(yo*(&z#Gbt`>F*n!?mko?3lG-jZ3DF3eA))8--p^*N0> zX3@yJa)ow7(q2}zbliGg2R?fJ+Y*cpaV1r@UGoDT%`^26{$_O9+`r^0*m&;=V_fRfjTpRpWJXQ$>@nF?NOR zDbEVoAmyBHoaYgb`Pl@I=1@d(RjO^U?p#UkW%Q$O2Nc;=wCT6}a7*kZ(Ine4C2&~U zJeJ@U>rf0(G57KQMwGff+Vm!l9jw!}a;mQ{+*52(4g=>vf@xi|JLky+dTq*5>bC%m0$I68Ux7uYoG0~Q6A;X8~y3WeZl z=F^AoncV*O&d*fPLuf?nJjLR}rzU^AvG0+)h-uK7jlb-d*w8nmHTaE1SyH}cz{sbF ze^@^9I7}sUc`V{$TI5-5<7=%B#v$w!szRzadZtJe#7doqXY-ythFd$(+VwWa+>y1h zO14~Fm=Sm#QMsuuyWh)Z{G7865tDQSnnxZTE7}L2Zn%dpRU%t`ErO1xCxST2YT-R`kQ;T4zKUp^lzb=4WTTrH^ z;Vo-S{|Eej;k8r~u9=c)4*3O!|A=)<`v~H;9I2|qgR>%M_No2rOe$ZUL*);U9?F1n zJ2xZdbT34s=2!qxn)D89E`619VwLV8=t@h^$9D353%WwBj#Ob43TmHnuv}HG;e@-6A)?<= zk|Pj``js#0#2)OFrj|v&jsPOkI`CM?@{X~oF6%Yz#P)M@Ci^;<7G(6;=}epCjXHN` z_ou`Y*{!e-x@rpQWwgUGrUKtwnm|I`6qi0qL{b}n^X@agzPcn`fXDN3Q7}$MN`6jJ z2`nV&B(;u*IgQbyD4^`Ot+@f$gov_q^p@tajAJa?Xx-4II_!Sqp@B!0%)G3}hao(e z2j1QtmDfK$*xsMdm*HWslI>-dDSji4!d&|?h^e4Z`mln)eY}Jlv^hCD-Hkb0c))=zmR^ERVObS+aF3b!oPK%XAY;;Tvd=MO z00y14)qdCUi;?vENX1n9ecx}>zR2pD34^)Fu9*JA3qzuS(W(xuDnE{4l)NDj%0aO& zD)&&zTkq0^I6843T@Hg=uW!yBz-R%Mk^I4gBu(xsjmdp?*243tUiKyQRnyr%OAB=e zx`e=2HD`();x}V;lXY_wOfZv2ty;?4;4ZV)n_$V)F|Wp!V7|pl{(Gi0vu4gtf^<*& z&f9^G&67#3n98{$-_8OT5+oC$NE&~_5#gnhs7uL)h*i#%W;SfM$YZm0cAsPsjKH{J zjp#N^&AA>2Srsl^%U>wLk-BFp43^JCqd{*Xl0Z5QIFVLelLCpga0`#9+Hr9nHGV|4 zodR1@?Pa@Kr%k?}<7fL(*-QQ{7g`NEu!$oMn&PT1f?_Y zKQ5x(DywfjH&^3USY1NH6JTcJcC7!Lh>a^zJ&P(=ompks8LVz}MOF-3@kH^B&ATew z?qRa=++o}FWz$y&@YY<$D_XuhW24vP;{gVN6!%*dlG~D#USC`HY9d z#}}#p)=JEpw6YzO=GYmghPtRI>U{<uvgsy^dzxwo;V zJ7RhHK-GEg+ZBW0wcUQyD{}61ntFPxJx}oxUvbu8{or5Ds&5iBp8s9l59&Bh`X?xi zKO>an$hlh31$e#ZO~pt5{jR}lNU_K1gs z!nT^(O?hqKKbiGvc-)QL6;$g$0r-qg{-gIK_|E)~CC$H@CNlk}4oDjsqqcwjlDp6T z`Xz_<7q@|if=C%bjL`er3CRnY$~#GZe#Mb!7-M$+?K2rbi6b@@+uA-@dZ{GL$4bcq zvT7JgYu&&TG5ct0OH;2B|6rng(S##qXLtSlgU#0cp5^P8@RJ8m4UedpiIdkC@p&r; zfQ4=!`UiV#SMi8}08J0|_>LupCkD61$pmT7-lvJ^3=tFW=D!xjlv1h5BpvrmA6mX% zzFZ$Zn!5N=7~dD}kEWG9LB(NE?~D52PA2cC_2!@E?Z$1mm_Y|I=eVqRjFUv$^c{b| zChDRa7s>3s4@!OfG6qXp-c>%E|Dqf33PYD38r{+9eeMWLu=#NM_;#W3XKJm1L2wmQ z*fUcRvh1#^ppn5Q_BZ%!sFzNB?&jQj3(bY=#bzlBJOc0X>5J2*jY}AvO@~g#&PlN6 zUPN%ohV6xMw(W{Mn~PcufniW%lgVE^E7e2S)2`+YghhOv6O#aV zn1pB$hedt9--NC@7{LfXi+v^@PAQd#}3WnoZVd}r#VDpat`<(gd zF)3;ltovf2QPrR)@v2w1b2ap3&0`l99sE@_CEgIRC9u z65B9ecj8}mMcr0j^TJF>rr_gFWVz=k%7Z!yF6*f$l_5i1iX|`3sU@|G(FPpPu?}n_ z3PfG#%R=9{V(jcTOuN~Om9)YkzvM0WNXsmAqGJsh#Bvvv1&Y%>AXJv&mHGP%y=lf% zeB<^jlD4`;GerMeP8WgG@sN$3G#AyYY#%kJt}?@eLVLCGQPH!qkuHMd8a5CNmK z(aD3F`f{4_gG0rvSfe%%HXFv?qew!{~I*U2=jRCzvciSYFop9mj68);`nuD*41)MfGPf5X6LEpe9;u3E60gOxWkw zh!KM8^{_nzss0azM~7;+8cD}BNZ$R;79&X!_Qwwr43Uh5uFQB7OPyrhQe4)HL?Y`Z zfAd(<^_8E^VoMTL3-^8zmmv?nk_n{HR^;b94eooT6ocH^2k#%b%&HK>9i678NGGo) zo}{m*Vtxd#u=AH5=;s4fO6*H%AQ#$9vA%7do#IY^bp-Mlur)%6OndH22r1(2V31y` zv#e?@)!)f9*jkTBuR{N3wpel1sEfq1m?0H_Hk)AGRN7+LGeykB z;_(IXd7{yn@OX?P(qubC;?dy&nKwthqk_Cx%pxsNtxQZzH~2jsSCdcO9Cx==`ivkE z1+bO!EBKUC7xl|LMXCz!xsyNXL%LQoHNi#^2X2eL#a*E7IQ>qic!8{r`s*Ysa+vX0 z5nN8s)P&OtE|@>5f%muZaxT9yu3;e47~Xkq8jqymV8!PPkTkcBCWARc1TsfS$77V`erF={G@gY6_Ukf%CHq5LP4nnn7on-<@vYE> znta!!Lmn%D29KC?9k5hc`v^q4(emMzXbJs{GqzGS#{HL5Lhbi+o&fb)qTy+7qttmQr$pl41natkl z8&ycB1A&~UGZUFiyOH^^^f|@p*$%#h%&f|fQ{NHZG=-QRCbLT`)9#UboQwn0Wktg^ zYfZO;<^4`+A62PH=~~R4Q813e*>0T-sXKcd~UV=_AdM0YJS=Wpsv3DxE4;|4JY*z<3M{L~VuI=&g{$qBr|4a6=aIpVpdF1nR+_Ik$ zx$BI!B}~xKp6*CU5;~L@hjCwpCrKCIA`#YbbmXzmPfscam#PF(V2Fh$L#O=7RlW;d zP3?Y21eOV-Vh+B0l6X?8wpFESOff}5G^WcW5+bYF5GG}2OB5&>;ix|lZyXz8RC$U~ zee+{q#&9{{69Uk+=t^iO(DgyAszC#OTD=(LwXmcu`og&OWvtJ6yx*(gUGO6~0S-De z>F3>^&TaIVwH?Gw?n|#7>Q?anD>h0EJ2Q-UF9dDw2%m;&sBvUs2NhG~zFhnP%KJ*3 zSh-cIyWo4`VOdC*2!JJDiA*I&V5S6A`VTVaW>kIpB-13aH_&|mfp)CJ3#>LmCYv-0 z4>6-o)`9LeDPR5oe{>GsKeTQ=otBL1g)oO*WmyY6I`1Q^3I0vK`62z=&~VpbzSw-c z$X;*$>O}rYh0tASp@Gpc-uaqqFd(`?+G@Tyv(aj(g_!KqR;%g`(>_V#HxQSGt zt91MApWY(Zzb*@y{~HPXci-SW<7?+@ftQcK&#x~(5CROy%zu0W*T2LG6Dup%|K=z~iz5yKs>MB|+TuxozSl5jZJt|6i8s6{!08EgXP4NM>^m-dadPDqV z#@5hJnmQgfMHasRIO`0=13cx#I2LIhH#+?=8f~e_FIvI}t;LkTg?}?^zd%qq6&4(Kl~W$1;!_bpipm?<(_Ah7F{xAj_!o% zMB@bg1pmaZ2q0ZrG(e95NnjXw;VH!r@*P}=GsPVMW`7 z+YD@$XdZ5+>`qX-q40cjfAi4M&2`J;7|-0Be2{BESf#o_KD zFDwtx=UhRyM%2aD&diKI8=ah(+(_-2Ze*yt8uHJq$jhzHul>)3kMy^sH!Y+aV|UhR=jp7p zPfV{R4@6Jh`}f(q`lG8H7JEj@``ps##UZN@;V%Tu#1T9-K_~ssfHDMhD=bm|IJvCmPmnR*aXEilE9ky3%i!RE`B{gRqs?I8II&*BT zXS+3AI)gfmou)2w=NU7}%gJ-eGbSg7o~fJVt!G;&!}mxJsSlVBnD?Zf@%%cuB?=3} zCxs76uZ%vw`6ZuDY<>JU6|O3IT&&F0%)E}$r>40D&Uu|nZe%~x4a{z*_H$rzM!6F` zOt-PWu(z-;qK=~8WXDd5rq6TJ*SLY)Ydsck1s8WMfEIkKHxZzg4MQ{E`lBK+qGhe+ zz$U)swq?*JwN+=$)j`Vv7}ZkH64(-MLkbLSMX(yT!kxn~AGf}1^#JnPT(YYH{aZe5 ze1ObruT90x#VzEmO&FL23<+Zif;Uzb%EeoH@hv=ncO^)WzCKsEt zx0EuJ5U}rlbAvrxN=WE-9%+o1W920&x0WuJ5jI zTRX@*BTBh5?}P^rUrgh??0kK`6TTT85w_SFxpjG&YTjL zs5{EF2hM79f{tUMyS4HO_oNF;#hAGMNb zu9P??G2@4GAp+00P2o zf}}Yj67arH*OUpmtrI%+3te9rfK?6Q-|@2tt9k>Z9nB^K)De5_6LQ39))PLiJ{J~O zX*k~xMss1BX6OLj921Ag$PV2#Z>a!jqg)PhglDz|q(=A)qp3~<{h`g9b`1gKSSr+~ zq7FQH9*L`x2R@G2%q106d+1ab+;~L$BN>$0?=cTl8|qXUa^$JNXA;DNQ1kd#$b|6< zz^DN9w%>diyoSm7ux$zCMX4!o5R`vE$h?+AkU!Y95|r7y*8z1KLu48;3m$J>ysj18 znWs&s%m0x8ysZcS4L;7GA8{od{FAaj6#trU*eDdAQ=cJ*a^?$!UJu+a#lh6!4}bQx z3O4&`0=y!gxdXqwP^~n{+Ar|7jkY;ZpP6B)K?tCO1Mbcqr&F8b>~NYDm426jUJV>* zY5}1jT&A1YOxRcFwpPvJF=l@E7>Ehv+8MkeGOqSD`0~|ESa*AG7#w@eHr`PvL#Ogg zSazEOq7#x3q1F1za&$ZFQoDhZ?Q?3N%OwqnwOD}n`tR?yBfmheE`jihc>)~9=b_%o zjpkQSg09k(YvBH2GZNYRp;POl}&bMTu2$N)GS zD7|6Q+qc&|V02^g8{GX{fmoGe|JSdPxxWIUko1-m#K^Qa_Fn<(yxX%u4lZDt17=A3 zr6j%{CE#rgs)b_j_x6Mp5}myu=**AWmj19BUKrTDA4A|@k5xj1^^@R$8{R?$<<{oy0z_24j^uU`6xamqbGlA*Q**0cW=*O5kP!)ezVX|8%qWgUq8fMItcX+(3d@ z_pzeW8wQ1{TL)UR4*Wzgb4NWF6!|f~?MK0n`B~D}D*GE@EfF#e8Q7HoO7UEz#?;#c zL4SV~LYRhp);$xB$!@zAit&2)XGl&!S^K z28irx{vP^q9x1j16^}~jBqy!yXzTw z**h-(1+*y)p7G9X8dRUwbby=Cdh3b()%$%KWZ#5k|LkoJgk?ww_J-6i&A`Za;IEH8 z_R9hi&yz@r=>qmAD9An}i#KE#=`LX~zx8ykkw13ZJ1JcnlDWaO?>-2e z^?0oM859G?^(A2S@7^fV%WGd41lRENiC|0=5<%5Osr(tT+%uQ4oFuzHp2#NMxj{JQn|TEPuqR>vTbO zkVoqvzi+14`nWL|Tx^Pg{P(D7X8s6oP>QABen=4VqX_CER*4ecL)kL-hOT4#^FhQl zT6^Q0!w{LSozC$8J(U@j$nRSo1Foa#HYvDuoW`~?xb=t*=z=@w2rv{6L(m)6JBZ&n z9pSTac8w^~dc}eLv9V9Q0l?S`2^bNFpR|=AbPP;~tLu}1Ji^w0T0$~8oKEnTdg+Mgh zG)V5y6iZ)(cl_b+_Qz<5-l1?k`-+)u4JiA-txsLQ&xj5C$|?UqxsNyh?IHif7L?Db z{`}jv(;Kpu^;IE+-J7D!3NqZ&1xN2AjOM_#&+i@fk(&uP$dylFNuKinz(`|X3osw( zI6p=y!D<5s~O> z?9X+1u83js;$Qm#emn|(r_D?n{bs4LLG0&ce0g*AC(+6 zB1%ld^qr+1nYMmMHeL{qES^&eMT&x&EV(G&c`nR2uBV9bL;(^R^Jg0r^&c5;Xh`rK za}6><$aw2CX+)R=VzSiz_NXy$|{lEP6e=9DN>%(xq4u=Y4vGUA_t6!D|R zu+(JAqpZx?Xz`IF@XU!5B#lx`=^{TU$cvJa;@gc0+Jh%3;YNfVsoSIINKz9AjbQ?i z;&T(CjagQOedS%_c}5vV2^vz@WiE-|MrucDM|~XyUJyLucm)yT!ba>y3-`Y}#^I3w zNEPDx_oZ%=sKZ31(nKYjEub~zE-4Uz)FND02V|Z z6Q|_UKXb@y*`wK_8}S?QIUuAWsppeyaKvlKIpPqEY1?zGNr9t?j->7By@exk`>u{q z?a}WdniS1(=yTE*$qTYINi|8TGG$T6_NS#tGu7KN5jv&E){-YQkHq3&{(q5+cG(tX z0S|oAp{jAo#`RRbfcl*{eTX4v5W?!;MhO?kS4kI~pep`_-RCYXLQ&r2Hi^2aE#G0p zo1mU>iFSsGpLF8RKpitocTetE6A?+>=6Ll#U|H^ty%wa06JQ^??>!aGPa&j_bt@9Y zv39)nJsgv|MC7Tjs5?gpyn9N$#Z(nV4R(Jbm6uZpa8^>9jq+whO`DDC6*G25ZOE4< zmM#>}RnOhsqB!JZke3#X7gZK%jVgJ-Y$)(6Dc5g7I?|Rysg3TtuxsW>^^n`a5kmV1 zeOMPYEVc=@rgs%~QOXgiInW3Vva>^|Mmo!FvR)|Rvradua)m5%KIFUGeq>9j7(*I- zV><$+Zlv-ia=!7tIDptB?z^*PE0y9AJj9bUpG9+*l%JwzRy&T{2@DAPmp*D=N^AsE%02GizHI30+cpg1`IxO>$ z?uA~rDHdNPRVH;``=Fj+Htbm!@QY1Khma+9kzVECiDzBqct7pWB$3(uEa4c{B2SDF zUjpm}_ss7&+SN-A|jKC@pySUI8=Hi z@8v=gf795R>pmCMn2@+N^~WmFWZ&;j1rinnmmZ+myOqx^PfXY0x%(b;3%=j};JfmR zpZDww$(QUYiz}5}M_deE{9pneD?JRIPoI6lR6ZE+Jo=+ioJa|# z;hN#+`-amz)WKr8#f|q{bDlm>hO7d2iy~91%#2ABs^fE(P-X!%WKSE%Sp9mit$jb#(M=~C60%||zM;JE6rU9vOP|FqxGt^iAi?DYL@+9c`wA;qCZB5&@HEr9r zZJYnLZQHhO+tYTxv$4AoZ|rmLJ|8Ng>O@v#Ma9XiQ+e`tF0wd0m`!HRW3@lB#{h6X z*e52tg*%qsxn^hiT?wuC`2??*3koj8F)eNaQ*Q2>v!&dEq%y6m-u%llZD4{1BEM+3 zeGYe(4$o!(VCrkynM!XL(1LVVX~o^(WYUwzHRfzQ3OUy-u*{jmQn?(ybDpPBCHZo> z5UQ}#xIkS><**&&MX^@mfhq*@J1hR5qFjkrWz@mgx5=w?8}Gax)(q$G80N zCrV$FcII@`*`AHgj+4zeE!OLG`w-`%Uyt!bw?FxLd6y5aU!>KAooCI?L7QWM2g&L! z;@dzUPa#VB@L8b0Ha-JjeW zdUr7!0(^u=wq%GQbU>yW31p&dlnoU?#Q+V)k+kK3D$^|iq7tfilr!P_G?|KUCiLQ7 z*1;1V-b4R(=Mmt`Vc1iC27ZMO8}05kqxD&BLP# z52YkqV-d2rVMiiIpAAvOI32xn_Aane=qmOJIqD4WntXHaFn79cjn(oHuj)+6;|htE zTGfX0k;LG^J=eByobRgdVvF97*zFwu67NFy`x4nSt(t_=lh=v1tHwEo9ACYUoX|o7 zsGsM|+-*&b(Y?CJdk-o5Qthp$V(v~K^2+9AHhc;f`gQ6-GfEs+9zp4iaU5O_Co9XM z;1@PyRdpPLFeNQ37HMqCsBE`O%{Sy1rzg>Lw%12;`ljhk`)LlZxg!KZ5&Ob&Q^*d7 zeV(tmWx&qzdcGUlAJ&VOX~x|nM;ufs68IDb8~Y5hQo!#WFm}nN*F-^y(ea{sBhfT) z+EDMrEDhfav?BpR$P*s>MH$4i%yW0l2huOfFSB=~x8>Lf0!0*+??2V=^iSm73cZ;R zao9RNP+l8jd-4QMK~(G#23A2Gv1y;t?le-wc={L>Sbkkvl){Y`iR`}P7%ti~&(69O zGFRTJ9a0{Mj(#w6AX{bo$8Z1MczV7vAvyd>U6ZVd?}37OfrY;cA-X%b=0=b+-!It< zZ>b;u>xA7CDDHNBf0R=bPNlg^L^8$&fqg>wJ8{nWKUJ>5qD4WU>e^En15>T zm`PR21?Z9m=?=GONNo5f1Ushr&I)Cu^I7KS^d3dl7J)4DJo60-niRa|o^$U_=N6SD zQI;&3$My5hzwrji8!pedJb5=q*fdu(S{6IkWKK3|yv}Ra@gKfY!p;`2^4=Vz`Cr+H zCD%U(p-AUAHP}t30#WV!%m-$f-4gxqb?)zkn}m8FqPDr@wia3%Iq$!+V-{APnP&W) zT4SY!LI3OtDau%qpR!u3DqAKt7{^gYwN*I`q6NUH2+83maE9Sfp3dC_V=l3DB-pB& z%%vQlrG&ZU!Lb$I?+eAT5~pmn?09kbE9 z{F#&U`(kZg46b#Fs432TTz>cb!uDa^2E%?Hy6THgQes$w^qt&h=e+64A$7m?S0))7 z-c~cV-9TAk!2+I+QkK%QSg&_HM(}~|#=;^~_|f!hMlg6b`YMP_Nr|-kHyLKeaqY4h zj<~G7*j!~sF0L=k{iaR~u~tf-Le(%$ulTc&p0%SdV`U$F{ksKA+V!cv!qJdFb89y9 zO0toR{B;XLLp(8Yl=v09J$NyNCq-`?8r)y72r>E37`R426>dIWjQC*=10EFmkwVz_ z5XnjK!Ex#(!Q7X!)$aP+bxO)b1$D6*EqJP1%RKt2zn%+URo9E=Wi=#OrEYgy%d_Kt z*k%5t$DD~jOEBFZxuo|Z2#LOgvp-U*$cpj}W+i(8)-JVf%U(F|8mn3tDA-FKzVm_s z$;wP~7Fa9{-EpJoH-mq%HfD^I7ATc&xvPb+he zk1uj%bGYngLNE|nDBDOxYg%xuCz?ML9tM;H_5K>g>3s9$V#+i?Q1sY0kDo zzLXVlCW^wf&xl;Hn&D~1J{S8)zvY z^#_ZhjujQW$5+JnHau}Zn!Mw&d_;eauj7(X+})NUL}t~ov!ws+h?L5M0NV(Mr%=fp zwrtFhF~#Ad4VQ|PQ~~^HBxa1l9w`Um3mS;cP@z7roxpl_Do^2Do)e#9j6HpM6I}2M z2ONn+r1eJ*L@+rpDc2>%>>aRvE4<}>m-znSuj!RUym&ZcxG0izPUFkXSx72oUZC(K z|EgP@++9DTBOO3g&>`cKs_D0op74^vT?<`cxs`acIVwcV^_&QYP93D1u*Ysm{Nt$e zd$u64Cx;KA(~@NJy=*d(hXVsa{bV-__1Y;r`xWxhfQF<$(RT8w?s4ggCT+?p9P({X z&7A6lt!#Kta-=supNM2jm{+(NX$PRlLYvVOVO@|}b-B1wdQ0AUZaZmv*8y2y30%8&11_j>-~ zZ0X~o(e@s4d`!tn5oL*xV0{*@kwpcfa1-5 zNMk_)I#w1xnKQ=puBon4P)tRe(bn##q?eeJm2053_yOG4(S(;L=bF4V#aXPtZ6BM13 z_Rk-`>Vi+*UxQXOa{$WPh~+db329F>>9s%(|*8S!p zvSMp|lMS?_N>K>eRvOU|3n6XxniJmn*W&UO@PWQNDS1`W%!<+$Ux>lRPE&9CUCH5e z6Z;2sRL3zpPcCV(hbS1qbTmmJkJou;|wQ_$Z zl5#6KHtKV#dAUAbS_$x|K0AbR>E*)k*2f4HQL&e5Yqw3tVHl(V)F#qQ(Nqa4Z|smQ z6gT!JX8kMIZ{wC7DcSG_c#O{HJdU4j2AU2bvAnZK*_LuOnF3zt?Xwc}58@a)Er!D; zQ3Wgy1n;S-ybWcK-_o_Z0H?zRv+w)V(v+*I{PcyQ>^MHh$r^F|WxwK|!^v+@b0J&% z<7HYW(?!AyZfd;7I^)a)X?MI_3ga}K342lv%tSSn1ye5+s(ojsjM2h`ddCRy?If{x zDJGh^JoO_{hx^or$2eHCS&cHkKVLc7YFo|Xp1sUk8@r0lE;6T@tj$ih1;w`lzH6F0 z6*c138UE4frmY#R3D*@((;L5;ab(oOmyh!Su)qG}eGYDcL|jKY7qRrF@m`->BOl zH06wA#bno*VS~=8LyVv>k7=f=@Z-oDdlUjSMSw2OZeJor#kU&QU!+r^T6`(d4M=-zu)q}_dUrl&o<9A&rM@t^e~(lT8gmv!ieBW*hzgqbX~7x=8=Ju zLi9@2Z7Te(tor;E^utNc&3#(-^0_SeW1+7nlX>6ZTjbREc#_fJq2_{+w9{p&yPh#) zaGzKr*+>`r0qrhFBrGgpx?~W?Iq^*3ntZsW0H${8A*D$#N7?hpBiG*WK9cKP14!K( z#TyQ14Ih76WA`nokRnlu$b3tu;^j;&-fZmkE4lEXHUrb9`1@gBQlZ=3@gBKc$=$lx z#d{ld~1w?U93xbN@J_l!>R% z5oF``FF_q;y-c0N9Y=7RUBT4Z9(#P}1hRd|V{>{FT}-8kB&Xu$imzDx0#G}vB?=)} z-PIK7y_r!a4hw974c3N;Pawj8f$LN-u$GN}-ko>rlwQJkD`W9Ip5rhPgSiGU&PLUR zGguu4&*}U{K0M*cQ7txLrd`l>T1&WeD=3iYvJBZs)oNufGeUc_=`M264Cngy))Xu8Kq489O;4ItZ1ipZV(V32{?t~% zjE<9Ebx)*id**P+91ISLnhQ>P>^1`JGz-QE{M|N#v$)M2c-A2&v(oJ+(KeayjK-?G zW1nIn^m+S*PV=4aISZ6;)kqGY9LA)=BX1mXpd`AGV4Q`(j3(Bi1R$6|Wr{vdultE3 z04B((y>}Bl|C3%Rq53@|)KUpMuFa;Vo0s9>f8a5`nLBa$wE3jd(9=UD}660!EI+SAp-fdcvc+J+h zZQ7g`L;q||p7^496*BfpB6&(Wo)eV&2GFJ767&POYhg$=DqWP)@wZ`{i zn^pupvHno!lG3p)Z(>baE&-gNe~2}VKPo+#e$XDFcSvuWY*>7UY{SbYg}#)25Uzl zKpi%&U+b%lAn>6@HX9;tS}m|EYQ6a2f0y5tyIo?R^N1rzNp<#J@d!5*$)GbiLtI=Z zp3(O2aKm_&BAw0$k(Wiz7c5bSl5{3b90KzK@q~^AgImwvnF7lkmbCue=E`BcnH>w( zxm>_xD4UEDwtk=0g^RAud594INw0AT99F69Fo!!)Ss#Jgl6nBp?bypv@w3xaPf3bZ z`hb%9mK1N=YClYZemXn`AzgX_-~PqTNXE!r`ry#oeABW}6>nzge0aG}M9G%s;~~0^{o)IAZkLdYLK*!@ za-TYwymsSD`!eaeF1vmecK*4a|yvV5`wAol!llihC?QLXTjXLR%5 zU6Rg5oA^lWM%I?*QsXl z!a^zN9GaPNmgSb!&obRo!^~so9>BWlnf^4};;fZ!6L+2L6aSU>RT=;~zi!2xnkVgt>gIEu8CRBj>fsb&$I9u5?v==t&a9NP7?*Zf1TKdxBw|E>; z*Ax4xR@WnPrToqmq>@Y!8+kWPBwZePXFEtl7=4FM$t_(}-xU;d?|9Xtnn3?{0~liL zl#WelR?+VZ$YWnJGo`5xy)(Ug8To`5&#kEIk!dIjRoRjAmH%F8O>kJ)Q0FHilYS>$ zaf_##oi=8A+!fH2NLEfVsoNqi*e}wSY?wbu%5MuTR13huP7mgkDMI=cVm&EI3w>aL zR6h8r{RkrgPY3^uHoE-#<{y$vy%8qYV5%vR@=OO9?qN)7s%&V>QD1}H)bh;f6T5C{ zzY*Ap%D)x+fu*W;wCC7xN^0!rJv7DqsiA`0M&6_)h2QzizPdm(Q+a!74K*ft6{5MI zV?w(+uSAS`zY)7RQNoC{g9>@3SvEpjfzPg3RYOI$m1dy~AWov`lD$&bP*BpL2)nwP zqPA)fMze!-b4O*%V^FEJ2P7RRXe~S zH`a@!Sc$1Z*qvvWq@iBWLA+8`+R45uFk+lP*ANquTHkgF1$UlUYNIzZJ0%y zwrXInn2G$HV}@LCxZPJFRs%2~gl)KXi1}(A*kC+jLR_sKr~Z_ zzy)nGO=bZ7nmF=Tv?XoO01|25p4eM%i-B zUU+g?qTiQ&#kq!i4JsljT^izwd0u0p=X%HGnYWYH^hHYr%%&}F##$LFFxBKs)w`+7 zYvUC^QGQ+fk$S z=ER@pxR$9eGvi_Wear;^vfyD?8FfnE6Gc=D=u@Oy8Rmq6m1^&~@RT&dI&rYAFq|#u zHZ*Uq!yj}#^va^o9r2q~y2Zrc8y%PkiS-Q+Bq%-F`kG0dM4ZQrKJON*s{BqU!;cZo z3(u>4#_jq`5wo3w^^*C}C_##TOMGgcr(utVe(A#>kKwcJo!c8Y8)v4YM{mXKZFb_} zQ6lu}<3q2hHu6bS6QP1x{S6!;I%Y|9+L0#CzQ@#{-X30+aD&$UWH}uZiTwX$@z8n-P))sam6resGIIa;h4C0*ec%K zdbk}ECs>qz^t2&uB)ZES7iy-K|GPI_{U@U`GA)i}`2JwQR#Ju{#4y*83CGPl*KiAv zAT2MK5?)WtvnW3c&^N}vdCl$mgXBs1i^O}2qU$g6Bj<=AliD7Weezz?p{_p#ZY%lC z+cw-(F1)t)zg2Gf=igv0ij0jSdpRMc%=73YCx6kB{uH@9tl6 z&_WcOxbHMxwkxAW;2kDU59mPO$;HLo^WRef8tZp)l5VHSf6iQzJja$=!Q zqq=>bYd1MD)GCiP3fx)Cb8Fo(pdCWchXjHMqd)@rwjHI zotj0e&$?w3d8JKMj_UhcFj-|?fQlE2cU_>B#@C;@#sbUAFM zlQT?Rv=p`n_JRKY)o~gfW>b&r5~vYVa%lZ z)xez!J1ETY#jA~p{X5)8_J*tx|9Upo!p*U@CMpErqeqnrrALF>2oqc*-C4|_@_Ji^ zdFH$z2k?>4X6FLdvRQJS!fSYA2jGtsQX0|Td^&yUVL4<*V)m5f;kjzhpWJ>>dbH=U zY}fV9VA$%wcA@hXDw=J(6d1Fu5|O}v(Mg?T`frkRv5bJRyqx8}WsUTKpHUrA&5D~W zqn{LQ?sK#H1h)8A59Rs^UL(Bku9t2+V;`nMnc1CK)BgUPc#s{Qe~?xAk%e^7{m%X@ z6xxNaXI5#BXQ-ucGIB56K5fKLw}-~G>$RL+^o)CQus-Zj3uB9zXbZcy|8qE!$-EK``Oi54JTHPdM7uA)LiHWw=} z#F^-GbkHC#Wn47hcc51jA=?ZEzDJTXXzR4Xbt(s%^EH-JA$!$o=xS)_ZTg>k3n`)1 z2}>k&h(WDUh#X8pG}Ni?tf}j1=)`^z_D=ws6FN%n$z^93F0jYke~tb|H!psY&deZk z(rd{h#kL4v2~$%Q1Iw^y#jLDRUq?k^$!a8oqE%U`f^(9}sLZUmP-6>7+qhU0^Y&f( zMK)JsJ>)$jD_b&RH7jfAq0^pzGsiV+PBAF! zD)3bivDa5mAk5o@y12;93l%%0T$K`z1IIMdG*aPAs|X(|f?(1=IzGMA(1Yv@w`_iz zA46=YW^HB>Nl7s()D9|h61SSv;`rWpw|`o&v^76wm0{p@_HW|BMbE-1IQ&+@2iKvt znkY0Zv@fdn)W{|@(vXoBRw2hb#gCDfB! zsN>`I`8o@KnN|I(Nx-nkl#;^IGoP*5-8EfRlc)JAF)&f6x=cA!Ns*`4TxuV6T1`IE zOHaPDsLa~)?-mn0^FLx>D(zfksU>(LhB1a=B5P{-T0(Q4`p}jirKy zb=*^BLfW|#)Z}C|nH=uMJdsT1R%2NQ3nKeJz#HqLjio92sRJ4z`XJ%t7_%DkiYzvs z8o#0@?ik7d0MtK}St{~OBx95`5R+sXX^F5@0m9T-qZp~O^l6+*naawlnyQNG3{kVk z3+Zf~?&zuWTkA?N6OoZ-R!K1ZQvF5gArLnDCihc;1sZ}jQvFqd79qvFnRgb9uAW2v z7=Ngsh`s6pB_a#edgGa)?f_oky~$6N=q zJ$86$!)l|LS^pjt1xlI|Yc~`2l1f_#%fkGi1<%QrgeOwoa%eWMPLl+xFSvBM-yz1V z0M;wiEMm$?qz(V{fRYmvwwK4duOlHQ`VL1IO%T=kC?D)wVKzw8$))hlxu}2RU46%j zrncWyeVG^bZ$lTvBzEUG&uabwbUl$~4B7Pj1vwZ>wKrLgSY>T=@qsywO7<-9?y>iK zVZsQ6am9s7LPm=ARLs3M`S0=?Elq;zn0mS)wRILceBsO{6A%x~=vDF5d^+vUt&cu8(M-2xhJAzJLRy>EFnCc0tQx{2O$Xj;_FdZ*01 z7S^^qODWwhuWp2O?7}*Zw%yQvcb3+7!mMSx9Z|c{nYkS`Zo0T`YPeo%Ji}&ROPRJB zH)La7opODo&$ymhch0nkW=*uPUX4_jPsE&CU&70pSW$KMkGIgcP;1?*&L>E&DCDQrBtplWGQrie|!bArR|WW64t?_fwrO?vd+XZ zIbcocs(E3GL;-tQrD%r6MXfiOa&~pk(0R3>e9V-slQDsQ(g-e`2mn8~_T}mfCZ$e2 zv)1LytZZyh%v3xvE@o48bm&lQNYddME!WPPIpNT#pD~?